From 360d441eaa04d1a2c73203c8656601f2b6a47b7f Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Mon, 8 Feb 2021 19:22:56 +0100 Subject: [PATCH] Simplified the skipVoice check in note polyphony checks Removed the trigger type check; both attack and release can choke each other --- src/sfizz/VoiceManager.cpp | 8 ++--- tests/PolyphonyT.cpp | 66 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/src/sfizz/VoiceManager.cpp b/src/sfizz/VoiceManager.cpp index 490927b2..122b87a7 100644 --- a/src/sfizz/VoiceManager.cpp +++ b/src/sfizz/VoiceManager.cpp @@ -189,13 +189,9 @@ void VoiceManager::checkNotePolyphony(const Region* region, int delay, const Tri for (Voice* voice : activeVoices_) { const TriggerEvent& voiceTriggerEvent = voice->getTriggerEvent(); - const bool skipVoice = - (triggerEvent.type == TriggerEventType::NoteOn && voice->releasedOrFree()) - || voice->isFree(); - if (!skipVoice + if (!voice->releasedOrFree() && voice->getRegion()->group == region->group - && voiceTriggerEvent.number == triggerEvent.number - && voiceTriggerEvent.type == triggerEvent.type) { + && voiceTriggerEvent.number == triggerEvent.number) { notePolyphonyCounter += 1; switch (region->selfMask) { case SfzSelfMask::mask: diff --git a/tests/PolyphonyT.cpp b/tests/PolyphonyT.cpp index 58a5cd54..c2c75aa3 100644 --- a/tests/PolyphonyT.cpp +++ b/tests/PolyphonyT.cpp @@ -439,7 +439,7 @@ TEST_CASE("[Polyphony] Note polyphony operates on release voices and sustain ped sfz::Synth synth; sfz::AudioBuffer buffer { 2, blockSize }; synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"( - key=48 sample=*silence + key=48 sample=*sine key=48 note_polyphony=1 sample=*saw trigger=release ampeg_attack=1 ampeg_decay=1 )"); synth.cc(0, 64, 127); @@ -450,9 +450,17 @@ TEST_CASE("[Polyphony] Note polyphony operates on release voices and sustain ped synth.noteOn(4, 48, 63 ); synth.noteOff(5, 48, 0 ); REQUIRE( synth.getNumActiveVoices() == 3); + REQUIRE( synth.getVoiceView(0)->getRegion()->sampleId->filename() == "*sine"); + REQUIRE( synth.getVoiceView(1)->getRegion()->sampleId->filename() == "*sine"); + REQUIRE( synth.getVoiceView(2)->getRegion()->sampleId->filename() == "*sine"); + synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 3 ); synth.cc(20, 64, 0); REQUIRE( synth.getNumActiveVoices() == 6 ); + REQUIRE( synth.getVoiceView(3)->getRegion()->sampleId->filename() == "*saw"); + REQUIRE( synth.getVoiceView(4)->getRegion()->sampleId->filename() == "*saw"); + REQUIRE( synth.getVoiceView(5)->getRegion()->sampleId->filename() == "*saw"); + synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 1 ); REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 61_norm); REQUIRE( synth.getVoiceView(0)->releasedOrFree()); @@ -473,7 +481,7 @@ TEST_CASE("[Polyphony] Note polyphony operates on release voices and sustain ped sfz::Synth synth; sfz::AudioBuffer buffer { 2, blockSize }; synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"( - key=48 sample=*silence + key=48 sample=*sine key=48 note_polyphony=1 sample=*saw trigger=release ampeg_attack=1 ampeg_decay=1 )"); synth.cc(0, 64, 127); @@ -484,9 +492,17 @@ TEST_CASE("[Polyphony] Note polyphony operates on release voices and sustain ped synth.noteOn(4, 48, 61 ); synth.noteOff(5, 48, 0 ); REQUIRE( synth.getNumActiveVoices() == 3); + REQUIRE( synth.getVoiceView(0)->getRegion()->sampleId->filename() == "*sine"); + REQUIRE( synth.getVoiceView(1)->getRegion()->sampleId->filename() == "*sine"); + REQUIRE( synth.getVoiceView(2)->getRegion()->sampleId->filename() == "*sine"); + synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 3 ); synth.cc(20, 64, 0); REQUIRE( synth.getNumActiveVoices() == 6 ); + REQUIRE( synth.getVoiceView(3)->getRegion()->sampleId->filename() == "*saw"); + REQUIRE( synth.getVoiceView(4)->getRegion()->sampleId->filename() == "*saw"); + REQUIRE( synth.getVoiceView(5)->getRegion()->sampleId->filename() == "*saw"); + synth.renderBlock(buffer); REQUIRE( numPlayingVoices(synth) == 3 ); REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 63_norm); REQUIRE( synth.getVoiceView(0)->releasedOrFree()); @@ -501,3 +517,49 @@ TEST_CASE("[Polyphony] Note polyphony operates on release voices and sustain ped REQUIRE( synth.getVoiceView(5)->getTriggerEvent().value == 61_norm); REQUIRE(!synth.getVoiceView(5)->releasedOrFree()); } + +TEST_CASE("[Polyphony] Bi-directional choking (with polyphony)") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, blockSize }; + synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"( + key=60 polyphony=1 + sample=kick.wav loop_mode=one_shot + sample=snare.wav trigger=release + )"); + synth.noteOn(0, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 1); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "kick.wav" ); + synth.noteOff(10, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 2); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "snare.wav" ); + synth.noteOn(20, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 3); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "kick.wav" ); +} + +TEST_CASE("[Polyphony] Bi-directional choking (with note_polyphony)") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, blockSize }; + synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"( + key=60 note_polyphony=1 + sample=kick.wav loop_mode=one_shot + sample=snare.wav trigger=release + )"); + synth.noteOn(0, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 1); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "kick.wav" ); + synth.noteOff(10, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 2); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "snare.wav" ); + synth.noteOn(20, 60, 63 ); + REQUIRE( synth.getNumActiveVoices() == 3); + REQUIRE( numPlayingVoices(synth) == 1 ); + REQUIRE( getPlayingVoices(synth).front()->getRegion()->sampleId->filename() == "kick.wav" ); +}