Don't send note offs when CCs are choking

This commit is contained in:
Paul Ferrand 2023-12-26 21:41:38 +01:00
parent 689200f810
commit 000b263344
3 changed files with 29 additions and 29 deletions

View file

@ -1309,12 +1309,12 @@ void Synth::Impl::startVoice(Layer* layer, int delay, const TriggerEvent& trigge
ring.addVoiceToRing(selectedVoice);
}
void Synth::Impl::checkOffGroups(const Region* region, int delay, int number)
void Synth::Impl::checkOffGroups(const Region* region, int delay, int number, bool chokedByCC)
{
for (auto& voice : voiceManager_) {
if (voice.checkOffGroup(region, delay, number)) {
const TriggerEvent& event = voice.getTriggerEvent();
if (event.type == TriggerEventType::NoteOn)
if (event.type == TriggerEventType::NoteOn && !chokedByCC)
noteOffDispatch(delay, event.number, event.value);
}
}
@ -1451,7 +1451,7 @@ void Synth::Impl::ccDispatch(int delay, int ccNumber, float value, int extendedA
if (region.useTimerRange && ! voiceManager_.withinValidTimerRange(&region, midiState.getInternalClock() + delay, sampleRate_))
continue;
checkOffGroups(&region, delay, ccNumber);
checkOffGroups(&region, delay, ccNumber, true);
startVoice(layer, delay, triggerEvent, ring);
}
}

View file

@ -260,7 +260,7 @@ struct Synth::Impl final: public Parser::Listener {
* @param delay
* @param number
*/
void checkOffGroups(const Region* region, int delay, int number);
void checkOffGroups(const Region* region, int delay, int number, bool chokedByCC = false);
/**
* @brief Resets the callback duration breakdown to 0

View file

@ -589,6 +589,31 @@ TEST_CASE("[Polyphony] Choke same group and note if the region is switched off (
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*sine" } );
}
TEST_CASE("[Polyphony] Choking on poly-aftertouch respects the note number")
{
sfz::Synth synth;
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyat_choke.sfz", R"(
<region> key=55 group=1 off_by=2 sample=*saw
<region> key=55 group=2 on_locc130=127 on_hicc130=127 trigger=release sample=*sine
)");
synth.noteOn(0, 55, 63 );
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 54, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 57, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 55, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*sine"} );
synth.hdPolyAftertouch(0, 55, 0.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*sine"} );
}
TEST_CASE("[Polyphony] A note coming at the same time as another can choke it")
{
sfz::Synth synth;
@ -632,28 +657,3 @@ TEST_CASE("[Polyphony] A note coming one sample before another note cannot choke
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "kick.wav", "snare.wav" } );
}
TEST_CASE("[Polyphony] Choking on poly-aftertouch respects the note number")
{
sfz::Synth synth;
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyat_choke.sfz", R"(
<region> key=55 group=1 off_by=2 sample=*saw
<region> key=55 group=2 on_locc130=127 on_hicc130=127 trigger=release polyphony=1 sample=*sine
)");
synth.noteOn(0, 55, 63 );
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 54, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 57, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*saw" } );
synth.hdPolyAftertouch(0, 55, 1.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*sine"} );
synth.hdPolyAftertouch(0, 55, 0.0f);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "*sine"} );
}