From 2b9737bcfb2d4c51eb9f2499d700ddd3bff6f1c5 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Wed, 20 Nov 2019 22:35:51 +0100 Subject: [PATCH] Added a dynamic number of voices --- sfizz/Synth.cpp | 31 +++++++++++++++++++++++++++---- sfizz/Synth.h | 8 +++++++- sfizz/sfizz.cpp | 14 ++++++++++++++ sfizz/sfizz.h | 15 +++++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/sfizz/Synth.cpp b/sfizz/Synth.cpp index d9157e14..d966ed8c 100644 --- a/sfizz/Synth.cpp +++ b/sfizz/Synth.cpp @@ -35,11 +35,9 @@ #include using namespace std::literals; -sfz::Synth::Synth() +sfz::Synth::Synth(int numVoices) { - for (int i = 0; i < config::numVoices; ++i) - voices.push_back(std::make_unique(midiState)); - voiceViewArray.reserve(config::numVoices); + resetVoices(numVoices); } void sfz::Synth::callback(absl::string_view header, const std::vector& members) @@ -506,4 +504,29 @@ float sfz::Synth::getVolume() const noexcept void sfz::Synth::setVolume(float volume) noexcept { this->volume = Default::volumeRange.clamp(volume); +} + +int sfz::Synth::getNumVoices() const noexcept +{ + return numVoices; +} + +void sfz::Synth::setNumVoices(int numVoices) noexcept +{ + ASSERT(numVoices > 0); + resetVoices(numVoices); +} + +void sfz::Synth::resetVoices(int numVoices) +{ + AtomicDisabler callbackDisabler{ canEnterCallback }; + while (inCallback) { + std::this_thread::sleep_for(1ms); + } + + voices.clear(); + for (int i = 0; i < numVoices; ++i) + voices.push_back(std::make_unique(midiState)); + voiceViewArray.reserve(numVoices); + this->numVoices = numVoices; } \ No newline at end of file diff --git a/sfizz/Synth.h b/sfizz/Synth.h index 19242ffb..527771f2 100644 --- a/sfizz/Synth.h +++ b/sfizz/Synth.h @@ -39,7 +39,8 @@ namespace sfz { class Synth : public Parser { public: - Synth(); + Synth() {} + Synth(int numVoices); bool loadSfzFile(const fs::path& file) final; int getNumRegions() const noexcept; int getNumGroups() const noexcept; @@ -63,6 +64,8 @@ public: void tempo(int delay, float secondsPerQuarter) noexcept; int getNumActiveVoices() const noexcept; + int getNumVoices() const noexcept; + void setNumVoices(int numVoices) noexcept; void garbageCollect() noexcept; protected: void callback(absl::string_view header, const std::vector& members) final; @@ -74,6 +77,7 @@ private: int numMasters { 0 }; int numCurves { 0 }; void clear(); + void resetVoices(int numVoices); void handleGlobalOpcodes(const std::vector& members); void handleControlOpcodes(const std::vector& members); void buildRegion(const std::vector& regionOpcodes); @@ -107,6 +111,8 @@ private: std::atomic canEnterCallback { true }; std::atomic inCallback { false }; + int numVoices { config::numVoices }; + LEAK_DETECTOR(Synth); }; diff --git a/sfizz/sfizz.cpp b/sfizz/sfizz.cpp index 0e0e63dd..7b3a4a01 100644 --- a/sfizz/sfizz.cpp +++ b/sfizz/sfizz.cpp @@ -24,6 +24,7 @@ #include "Synth.h" #include "sfizz.h" +#define UNUSED(x) (void)(x) #ifdef __cplusplus extern "C" { #endif @@ -122,6 +123,7 @@ void sfizz_render_block(sfizz_synth_t* synth, float** channels, int num_channels auto self = reinterpret_cast(synth); // Only stereo output is supported for now ASSERT(num_channels == 2); + UNUSED(num_channels); self->renderBlock({{channels[0], channels[1]}, static_cast(num_frames)}); } @@ -143,6 +145,18 @@ float sfizz_get_volume(sfizz_synth_t* synth) return self->getVolume(); } +void sfizz_set_num_voices(sfizz_synth_t* synth, int num_voices) +{ + auto self = reinterpret_cast(synth); + self->setNumVoices(num_voices); +} + +int sfizz_get_num_voices(sfizz_synth_t* synth) +{ + auto self = reinterpret_cast(synth); + return self->getNumVoices(); +} + #ifdef __cplusplus } #endif \ No newline at end of file diff --git a/sfizz/sfizz.h b/sfizz/sfizz.h index c5537bcd..86f578c4 100644 --- a/sfizz/sfizz.h +++ b/sfizz/sfizz.h @@ -232,6 +232,21 @@ void sfizz_set_volume(sfizz_synth_t* synth, float volume); */ float sfizz_get_volume(sfizz_synth_t* synth); +/** + * @brief Sets the number of voices used by the synth + * + * @param synth + * @param num_voices + */ +void sfizz_set_num_voices(sfizz_synth_t* synth, int num_voices); +/** + * @brief Returns the number of voices + * + * @param synth + * @return num_voices + */ +int sfizz_get_num_voices(sfizz_synth_t* synth); + #ifdef __cplusplus } #endif \ No newline at end of file