From 6d56aaaa6c18bfc5e6feac0a2a875e1581deb627 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Wed, 1 Jul 2020 16:21:30 +0200 Subject: [PATCH] Correctly dispatch the CC to the region if it's a sustain ...with some tests --- src/sfizz/Region.h | 2 +- src/sfizz/Synth.cpp | 13 +++++++++-- tests/SynthT.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) diff --git a/src/sfizz/Region.h b/src/sfizz/Region.h index 3e5c4dad..09626703 100644 --- a/src/sfizz/Region.h +++ b/src/sfizz/Region.h @@ -366,6 +366,7 @@ struct Region { // Modifiers ModifierArray> modifiers; + bool triggerOnCC { false }; // whether the region triggers on CC events or note events private: const MidiState& midiState; bool keySwitched { true }; @@ -376,7 +377,6 @@ private: bool aftertouchSwitched { true }; bool noteIsOff { false }; std::bitset ccSwitched; - bool triggerOnCC { false }; absl::string_view defaultPath { "" }; int sequenceCounter { 0 }; diff --git a/src/sfizz/Synth.cpp b/src/sfizz/Synth.cpp index 766c1786..65f61473 100644 --- a/src/sfizz/Synth.cpp +++ b/src/sfizz/Synth.cpp @@ -446,7 +446,9 @@ void sfz::Synth::finalizeSfzLoad() } for (int cc = 0; cc < config::numCCs; cc++) { - if (region->ccTriggers.contains(cc) || region->ccConditions.contains(cc)) + if (region->ccTriggers.contains(cc) + || region->ccConditions.contains(cc) + || (cc == region->sustainCC && region->trigger == SfzTrigger::release)) ccActivationLists[cc].push_back(region); } @@ -915,7 +917,14 @@ void sfz::Synth::hdcc(int delay, int ccNumber, float normValue) noexcept if (voice == nullptr) continue; - voice->startVoice(region, delay, ccNumber, normValue, Voice::TriggerType::CC); + if (!region->triggerOnCC) { + // This is a sustain trigger + const auto replacedVelocity = resources.midiState.getNoteVelocity(region->pitchKeycenter); + voice->startVoice(region, delay, region->pitchKeycenter, replacedVelocity, Voice::TriggerType::NoteOff); + } else { + voice->startVoice(region, delay, ccNumber, normValue, Voice::TriggerType::CC); + } + ring.addVoiceToRing(voice); } } diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index ecc00248..c0d761c9 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -609,3 +609,57 @@ TEST_CASE("[Synth] Sisters and off-by") REQUIRE( synth.getNumActiveVoices() == 2 ); REQUIRE( sfz::SisterVoiceRing::countSisterVoices(synth.getVoiceView(0)) == 1 ); } + +TEST_CASE("[Synth] Release key") +{ + sfz::Synth synth; + synth.loadSfzString(fs::current_path(), R"( + key=62 sample=*sine trigger=release_key + )"); + synth.noteOn(0, 62, 85); + synth.cc(0, 64, 127); + synth.noteOff(0, 62, 85); + REQUIRE( synth.getNumActiveVoices() == 1 ); +} + +TEST_CASE("[Synth] Release") +{ + sfz::Synth synth; + synth.loadSfzString(fs::current_path(), R"( + key=62 sample=*sine trigger=release + )"); + synth.noteOn(0, 62, 85); + synth.cc(0, 64, 127); + synth.noteOff(0, 62, 85); + REQUIRE( synth.getNumActiveVoices() == 0 ); + synth.cc(0, 64, 0); + REQUIRE( synth.getNumActiveVoices() == 1 ); +} + +TEST_CASE("[Synth] Release key (Different sustain CC)") +{ + sfz::Synth synth; + synth.loadSfzString(fs::current_path(), R"( + sustain_cc=54 + key=62 sample=*sine trigger=release_key + )"); + synth.noteOn(0, 62, 85); + synth.cc(0, 54, 127); + synth.noteOff(0, 62, 85); + REQUIRE( synth.getNumActiveVoices() == 1 ); +} + +TEST_CASE("[Synth] Release (Different sustain CC)") +{ + sfz::Synth synth; + synth.loadSfzString(fs::current_path(), R"( + sustain_cc=54 + key=62 sample=*sine trigger=release + )"); + synth.noteOn(0, 62, 85); + synth.cc(0, 54, 127); + synth.noteOff(0, 62, 85); + REQUIRE( synth.getNumActiveVoices() == 0 ); + synth.cc(0, 54, 0); + REQUIRE( synth.getNumActiveVoices() == 1 ); +}