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..4c4bce96 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -579,6 +579,8 @@ void sfz::Synth::noteOn(int delay, int noteNumber, uint8_t velocity) noexcept ASSERT(noteNumber < 128); ASSERT(noteNumber >= 0); + DBG("Note on at " << noteNumber << " (" << +velocity << ")"); + ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration }; resources.midiState.noteOnEvent(delay, noteNumber, velocity); @@ -595,6 +597,8 @@ void sfz::Synth::noteOff(int delay, int noteNumber, uint8_t velocity) noexcept ASSERT(noteNumber >= 0); UNUSED(velocity); + DBG("Note off at " << noteNumber << " (" << +velocity << ")"); + ScopedTiming logger { dispatchDuration, ScopedTiming::Operation::addToDuration }; resources.midiState.noteOffEvent(delay, noteNumber, velocity); @@ -962,3 +966,11 @@ void sfz::Synth::disableLogging() noexcept { resources.logger.disableLogging(); } + +void sfz::Synth::allSoundOff() noexcept +{ + 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;