diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index c984acae8..0065afd9b 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -231,8 +231,9 @@ void sfz::Synth::clear() modificationTime = fs::file_time_type::min(); // set default controllers - cc(0, 7, 100); // volume - hdcc(0, 10, 0.5f); // pan + fill(absl::MakeSpan(ccInitialValues), 0.0f); + initCc(7, 100); // volume + initHdcc(10, 0.5f); // pan // set default controller labels insertPairUniquely(ccLabels, 7, "Volume"); @@ -326,14 +327,14 @@ void sfz::Synth::handleControlOpcodes(const std::vector& members) if (Default::ccNumberRange.containsWithEnd(member.parameters.back())) { const auto ccValue = readOpcode(member.value, Default::midi7Range); if (ccValue) - resources.midiState.ccEvent(0, member.parameters.back(), normalizeCC(*ccValue)); + initCc(member.parameters.back(), *ccValue); } break; case hash("set_hdcc&"): if (Default::ccNumberRange.containsWithEnd(member.parameters.back())) { const auto ccValue = readOpcode(member.value, Default::normalizedRange); if (ccValue) - resources.midiState.ccEvent(0, member.parameters.back(), *ccValue); + initHdcc(member.parameters.back(), *ccValue); } break; case hash("label_cc&"): @@ -1137,6 +1138,27 @@ void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept ccDispatch(delay, ccNumber, normValue); } +void sfz::Synth::initCc(int ccNumber, uint8_t ccValue) noexcept +{ + const float normValue = normalizeCC(ccValue); + initHdcc(ccNumber, normValue); +} + +void sfz::Synth::initHdcc(int ccNumber, float normValue) noexcept +{ + ASSERT(ccNumber >= 0); + ASSERT(ccNumber < config::numCCs); + ccInitialValues[ccNumber] = normValue; + resources.midiState.ccEvent(0, ccNumber, normValue); +} + +float sfz::Synth::getHdccInit(int ccNumber) +{ + ASSERT(ccNumber >= 0); + ASSERT(ccNumber < config::numCCs); + return ccInitialValues[ccNumber]; +} + void sfz::Synth::pitchWheel(int delay, int pitch) noexcept { ASSERT(pitch <= 8192); diff --git a/src/sfizz/Synth.h b/src/sfizz/Synth.h index fd019dc38..c308666e0 100644 --- a/src/sfizz/Synth.h +++ b/src/sfizz/Synth.h @@ -369,7 +369,30 @@ class Synth final : public Voice::StateListener, public Parser::Listener { * @param normValue the normalized cc value, in domain 0 to 1 */ void hdcc(int delay, int ccNumber, float normValue) noexcept; +private: + /** + * @brief Set the initial value of a controller and send it to the synth + * + * @param ccNumber the cc number + * @param ccValue the cc value + */ + void initCc(int ccNumber, uint8_t ccValue) noexcept; + /** + * @brief Set the initial value of a controller and send it to the synth + * + * @param ccNumber the cc number + * @param normValue the normalized cc value, in domain 0 to 1 + */ + void initHdcc(int ccNumber, float normValue) noexcept; +public: /** + * @brief Get the initial value of a controller under the current instrument + * + * @param ccNumber the cc number + * @return the initial value + */ + float getHdccInit(int ccNumber); + /** * @brief Send a pitch bend event to the synth * * @param delay the delay at which the event occurs; this should be lower @@ -909,6 +932,9 @@ class Synth final : public Voice::StateListener, public Parser::Listener { }; SettingsPerVoice settingsPerVoice; + // Controller initial values + std::array ccInitialValues; + Duration dispatchDuration { 0 }; Parser parser; diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index 2144426a0..49fccde2a 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -1348,3 +1348,24 @@ TEST_CASE("[Synth] Off by with CC switches") REQUIRE( numPlayingVoices(synth) == 1 ); REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId.filename() == "*saw" ); } + +TEST_CASE("[Synth] Initial values of CC") +{ + sfz::Synth synth; + + synth.loadSfzString(fs::current_path() / "init_cc.sfz", R"( + sample=*sine + )"); + + REQUIRE(synth.getHdccInit(111) == 0.0f); + REQUIRE(synth.getHdccInit(7) == Approx(100.0f / 127)); // default volume + REQUIRE(synth.getHdccInit(10) == 0.5f); // default pan + + synth.loadSfzString(fs::current_path() / "init_cc.sfz", R"( + set_hdcc111=0.1234 set_cc112=77 + sample=*sine + )"); + + REQUIRE(synth.getHdccInit(111) == Approx(0.1234f)); + REQUIRE(synth.getHdccInit(112) == Approx(77.0f / 127)); +}