From 1e2167d005be3a335cf7802c9842f5ba8f8fc434 Mon Sep 17 00:00:00 2001 From: Hyunjin Song Date: Sat, 18 Nov 2023 21:27:09 +0900 Subject: [PATCH] Fix Sf2 player freezing on project unloading with shared SoundFonts (#6950) * Require FluidSynth >= 1.1.7 * Use `fluid_sfont_t` directly without sharing * Adjust formatting a bit --- CMakeLists.txt | 2 +- plugins/Sf2Player/Sf2Player.cpp | 81 ++++++++------------------------- plugins/Sf2Player/Sf2Player.h | 22 +-------- 3 files changed, 20 insertions(+), 85 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ee3ac9e87..858849abd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -540,7 +540,7 @@ ENDIF() # check for Fluidsynth IF(WANT_SF2) - find_package(FluidSynth 1.1.0) + find_package(FluidSynth 1.1.7) if(FluidSynth_FOUND) SET(LMMS_HAVE_FLUIDSYNTH TRUE) if(FluidSynth_VERSION_STRING VERSION_GREATER_EQUAL 2) diff --git a/plugins/Sf2Player/Sf2Player.cpp b/plugins/Sf2Player/Sf2Player.cpp index ee97e98ef..7795671c5 100644 --- a/plugins/Sf2Player/Sf2Player.cpp +++ b/plugins/Sf2Player/Sf2Player.cpp @@ -121,12 +121,6 @@ struct Sf2PluginData -// Static map of current sfonts -QMap Sf2Instrument::s_fonts; -QMutex Sf2Instrument::s_fontsMutex; - - - Sf2Instrument::Sf2Instrument( InstrumentTrack * _instrument_track ) : Instrument( _instrument_track, &sf2player_plugin_descriptor ), m_srcState( nullptr ), @@ -375,31 +369,12 @@ void Sf2Instrument::freeFont() { m_synthMutex.lock(); - if ( m_font != nullptr ) + if (m_font != nullptr) { - s_fontsMutex.lock(); - --(m_font->refCount); - - // No more references - if( m_font->refCount <= 0 ) - { - qDebug() << "Really deleting " << m_filename; - - fluid_synth_sfunload( m_synth, m_fontId, true ); - s_fonts.remove( m_filename ); - delete m_font; - } - // Just remove our reference - else - { - qDebug() << "un-referencing " << m_filename; - - fluid_synth_remove_sfont( m_synth, m_font->fluidFont ); - } - s_fontsMutex.unlock(); - + fluid_synth_sfunload(m_synth, m_fontId, true); m_font = nullptr; } + m_synthMutex.unlock(); } @@ -413,49 +388,29 @@ void Sf2Instrument::openFile( const QString & _sf2File, bool updateTrackName ) char * sf2Ascii = qstrdup( qPrintable( PathUtil::toAbsolute( _sf2File ) ) ); QString relativePath = PathUtil::toShortestRelative( _sf2File ); - // free reference to soundfont if one is selected + // free the soundfont if one is selected freeFont(); m_synthMutex.lock(); - s_fontsMutex.lock(); - // Increment Reference - if( s_fonts.contains( relativePath ) ) + bool loaded = false; + if (fluid_is_soundfont(sf2Ascii)) { - qDebug() << "Using existing reference to " << relativePath; + m_fontId = fluid_synth_sfload(m_synth, sf2Ascii, true); - m_font = s_fonts[ relativePath ]; - - m_font->refCount++; - - m_fontId = fluid_synth_add_sfont( m_synth, m_font->fluidFont ); - } - - // Add to map, if doesn't exist. - else - { - bool loaded = false; - if( fluid_is_soundfont( sf2Ascii ) ) + if (fluid_synth_sfcount(m_synth) > 0) { - m_fontId = fluid_synth_sfload( m_synth, sf2Ascii, true ); - - if( fluid_synth_sfcount( m_synth ) > 0 ) - { - // Grab this sf from the top of the stack and add to list - m_font = new Sf2Font( fluid_synth_get_sfont( m_synth, 0 ) ); - s_fonts.insert( relativePath, m_font ); - loaded = true; - } - } - - if(!loaded) - { - collectErrorForUI( Sf2Instrument::tr( "A soundfont %1 could not be loaded." ). - arg( QFileInfo( _sf2File ).baseName() ) ); + // Grab this sf from the top of the stack and add to list + m_font = fluid_synth_get_sfont(m_synth, 0); + loaded = true; } } - s_fontsMutex.unlock(); + if (!loaded) + { + collectErrorForUI(Sf2Instrument::tr("A soundfont %1 could not be loaded.").arg(QFileInfo(_sf2File).baseName())); + } + m_synthMutex.unlock(); if( m_fontId >= 0 ) @@ -627,12 +582,12 @@ void Sf2Instrument::reloadSynth() { // Now, delete the old one and replace m_synthMutex.lock(); - fluid_synth_remove_sfont( m_synth, m_font->fluidFont ); + fluid_synth_remove_sfont( m_synth, m_font ); delete_fluid_synth( m_synth ); // New synth m_synth = new_fluid_synth( m_settings ); - m_fontId = fluid_synth_add_sfont( m_synth, m_font->fluidFont ); + m_fontId = fluid_synth_add_sfont( m_synth, m_font ); m_synthMutex.unlock(); // synth program change (set bank and patch) diff --git a/plugins/Sf2Player/Sf2Player.h b/plugins/Sf2Player/Sf2Player.h index bd7fa1b81..17ddf5500 100644 --- a/plugins/Sf2Player/Sf2Player.h +++ b/plugins/Sf2Player/Sf2Player.h @@ -114,16 +114,12 @@ public slots: void updateTuning(); private: - static QMutex s_fontsMutex; - static QMap s_fonts; - static int (* s_origFree)( fluid_sfont_t * ); - SRC_STATE * m_srcState; fluid_settings_t* m_settings; fluid_synth_t* m_synth; - Sf2Font* m_font; + fluid_sfont_t* m_font; int m_fontId; QString m_filename; @@ -177,22 +173,6 @@ signals: } ; - -// A soundfont in our font-map -class Sf2Font -{ - MM_OPERATORS -public: - Sf2Font( fluid_sfont_t * f ) : - fluidFont( f ), - refCount( 1 ) - {}; - - fluid_sfont_t * fluidFont; - int refCount; -}; - - namespace gui {