diff --git a/lv2/sfizz.c b/lv2/sfizz.c index 0b2f6402..b0b9ab5d 100644 --- a/lv2/sfizz.c +++ b/lv2/sfizz.c @@ -416,7 +416,8 @@ activate(LV2_Handle instance) static void deactivate(LV2_Handle instance) { - UNUSED(instance); + sfizz_plugin_t *self = (sfizz_plugin_t *)instance; + sfizz_all_sound_off(self->synth); } static void diff --git a/src/sfizz.h b/src/sfizz.h index c9da6d85..4063d498 100644 --- a/src/sfizz.h +++ b/src/sfizz.h @@ -369,6 +369,13 @@ SFIZZ_EXPORTED_API void sfizz_enable_logging(sfizz_synth_t* synth); */ SFIZZ_EXPORTED_API void sfizz_disable_logging(sfizz_synth_t* synth); +/** + * @brief Shuts down the current processing, clear buffers and reset the voices. + * + * @param synth + */ +SFIZZ_EXPORTED_API void sfizz_all_sound_off(sfizz_synth_t* synth); + #ifdef __cplusplus } #endif diff --git a/src/sfizz.hpp b/src/sfizz.hpp index be2785b3..199729bf 100644 --- a/src/sfizz.hpp +++ b/src/sfizz.hpp @@ -256,6 +256,11 @@ public: * */ void disableLogging() noexcept; + /** + * @brief Shuts down the current processing, clear buffers and reset the voices. + * + */ + void allSoundOff() noexcept; private: std::unique_ptr synth; }; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 8f7612ef..56c5126c 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -962,3 +962,16 @@ void sfz::Synth::disableLogging() noexcept { resources.logger.disableLogging(); } + +void sfz::Synth::allSoundOff() noexcept +{ + AtomicDisabler callbackDisabler{ canEnterCallback }; + while (inCallback) { + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + + for (auto &voice: voices) + voice->reset(); + for (auto& effectBus: effectBuses) + effectBus->clear(); +} diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index 41a56c53..2fb1eb16 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -361,6 +361,12 @@ public: * */ void disableLogging() noexcept; + + /** + * @brief Shuts down the current processing, clear buffers and reset the voices. + * + */ + void allSoundOff() noexcept; protected: /** * @brief The parser callback; this is called by the parent object each time diff --git a/src/sfizz/sfizz.cpp b/src/sfizz/sfizz.cpp index 61e5a0c5..ee4ef4f1 100644 --- a/src/sfizz/sfizz.cpp +++ b/src/sfizz/sfizz.cpp @@ -195,3 +195,8 @@ void sfz::Sfizz::disableLogging() noexcept { synth->disableLogging(); } + +void sfz::Sfizz::allSoundOff() noexcept +{ + synth->allSoundOff(); +} diff --git a/src/sfizz/sfizz_wrapper.cpp b/src/sfizz/sfizz_wrapper.cpp index 32ab355a..7e18d2f6 100644 --- a/src/sfizz/sfizz_wrapper.cpp +++ b/src/sfizz/sfizz_wrapper.cpp @@ -237,12 +237,19 @@ void sfizz_enable_logging(sfizz_synth_t* synth) auto self = reinterpret_cast(synth); return self->enableLogging(); } + void sfizz_disable_logging(sfizz_synth_t* synth) { auto self = reinterpret_cast(synth); return self->disableLogging(); } +void sfizz_all_sound_off(sfizz_synth_t* synth) +{ + auto self = reinterpret_cast(synth); + return self->allSoundOff(); +} + #ifdef __cplusplus } #endif diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 9ed0c73c..70806b5e 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -26,6 +26,17 @@ TEST_CASE("[Synth] Play and check active voices") REQUIRE(synth.getNumActiveVoices() == 0); } +TEST_CASE("[Synth] All sound off") +{ + sfz::Synth synth; + synth.loadSfzFile(fs::current_path() / "tests/TestFiles/groups_avl.sfz"); + synth.noteOn(0, 36, 24); + synth.noteOn(0, 36, 89); + REQUIRE(synth.getNumActiveVoices() == 2); + synth.allSoundOff(); + REQUIRE(synth.getNumActiveVoices() == 0); +} + TEST_CASE("[Synth] Change the number of voice while playing") { sfz::Synth synth; diff --git a/vst/SfizzVstProcessor.cpp b/vst/SfizzVstProcessor.cpp index 62d6b785..97795c41 100644 --- a/vst/SfizzVstProcessor.cpp +++ b/vst/SfizzVstProcessor.cpp @@ -46,6 +46,9 @@ tresult PLUGIN_API SfizzVstProcessor::initialize(FUnknown* context) _state = SfizzVstState(); + fprintf(stderr, "[sfizz] new synth\n"); + _synth.reset(new sfz::Sfizz); + return result; } @@ -105,21 +108,20 @@ tresult PLUGIN_API SfizzVstProcessor::canProcessSampleSize(int32 symbolicSampleS tresult PLUGIN_API SfizzVstProcessor::setActive(TBool state) { - stopBackgroundWork(); - _synth.reset(); + sfz::Sfizz* synth = _synth.get(); + + if (!synth) + return kResultFalse; if (state) { - fprintf(stderr, "[Sfizz] new synth\n"); - sfz::Sfizz* synth = new sfz::Sfizz; - _synth.reset(synth); - synth->setSampleRate(processSetup.sampleRate); synth->setSamplesPerBlock(processSetup.maxSamplesPerBlock); - syncStateToSynth(); - _workRunning = true; _worker = std::thread([this]() { doBackgroundWork(); }); + } else { + synth->allSoundOff(); + stopBackgroundWork(); } return kResultTrue;