From cef44cbdb67aba8ef448c1736d9a455d88f01bf1 Mon Sep 17 00:00:00 2001 From: Paul Ferrand Date: Wed, 19 Aug 2020 00:50:09 +0200 Subject: [PATCH] Disabled regions don't need to take up polyphony The tests were a bit flaky and the did not seem justified by any behavior in e.g. ARIA The new tests cover a similar situation which is validated in sforzando --- src/sfizz/Voice.cpp | 7 ++-- tests/FilesT.cpp | 50 ---------------------------- tests/SynthT.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 53 deletions(-) diff --git a/src/sfizz/Voice.cpp b/src/sfizz/Voice.cpp index d7517a3d..86dd1cd4 100644 --- a/src/sfizz/Voice.cpp +++ b/src/sfizz/Voice.cpp @@ -51,6 +51,10 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value, triggerValue = value; this->region = region; + + if (region->disabled) + return; + switchState(State::playing); ASSERT(delay >= 0); @@ -715,9 +719,6 @@ bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept if (region == nullptr) return false; - if (delay <= this->triggerDelay) - return false; - if (triggerType == TriggerType::NoteOn && region->offBy == group) { off(delay); return true; diff --git a/tests/FilesT.cpp b/tests/FilesT.cpp index f92f496c..fdc78691 100644 --- a/tests/FilesT.cpp +++ b/tests/FilesT.cpp @@ -471,56 +471,6 @@ TEST_CASE("[Files] Note and octave offsets") REQUIRE( synth.getRegionView(6)->pitchKeycenter == 50 ); } -TEST_CASE("[Files] Off by with different delays") -{ - Synth synth; - synth.setSamplesPerBlock(256); - AudioBuffer buffer(2, 256); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz"); - REQUIRE( synth.getNumRegions() == 4 ); - synth.noteOn(0, 63, 63); - REQUIRE( synth.getNumActiveVoices(true) == 1 ); - auto group1Voice = synth.getVoiceView(0); - REQUIRE( group1Voice->getRegion()->group == 1ul ); - REQUIRE( group1Voice->getRegion()->offBy == 2ul ); - synth.noteOn(100, 64, 63); - synth.renderBlock(buffer); - REQUIRE(group1Voice->releasedOrFree()); -} - -TEST_CASE("[Files] Off by with the same delays") -{ - Synth synth; - synth.setSamplesPerBlock(256); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz"); - REQUIRE( synth.getNumRegions() == 4 ); - synth.noteOn(0, 63, 63); - REQUIRE( synth.getNumActiveVoices(true) == 1 ); - auto group1Voice = synth.getVoiceView(0); - REQUIRE( group1Voice->getRegion()->group == 1ul ); - REQUIRE( group1Voice->getRegion()->offBy == 2ul ); - synth.noteOn(0, 64, 63); - REQUIRE(!group1Voice->releasedOrFree()); -} - -TEST_CASE("[Files] Off by with the same notes at the same time") -{ - Synth synth; - synth.setSamplesPerBlock(256); - synth.loadSfzFile(fs::current_path() / "tests/TestFiles/off_by.sfz"); - REQUIRE( synth.getNumRegions() == 4 ); - synth.noteOn(0, 65, 63); - REQUIRE( synth.getNumActiveVoices(true) == 2 ); - synth.noteOn(0, 65, 63); - REQUIRE( synth.getNumActiveVoices(true) == 4 ); - AudioBuffer buffer { 2, 256 }; - synth.renderBlock(buffer); - synth.noteOn(0, 65, 63); - synth.renderBlock(buffer); - REQUIRE( synth.getNumActiveVoices(true) == 6 ); - REQUIRE( numPlayingVoices(synth) == 2 ); -} - TEST_CASE("[Files] Off modes") { Synth synth; diff --git a/tests/SynthT.cpp b/tests/SynthT.cpp index cf933ead..5d167385 100644 --- a/tests/SynthT.cpp +++ b/tests/SynthT.cpp @@ -1143,3 +1143,83 @@ TEST_CASE("[Synth] Trigger also on the sustain CC") synth.cc(0, 64, 127); REQUIRE( synth.getNumActiveVoices(true) == 1 ); } + +TEST_CASE("[Synth] end=-1 voices are immediately killed after triggering but they kill other voices") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, 256 }; + + synth.loadSfzString(fs::current_path(), R"( + key=60 end=-1 sample=*sine + key=61 end=-1 sample=*silence + key=62 sample=*sine off_by=2 + key=63 end=-1 sample=*saw group=2 + )"); + synth.noteOn(0, 60, 85); + REQUIRE( synth.getNumActiveVoices(true) == 0 ); + synth.noteOn(0, 61, 85); + REQUIRE( synth.getNumActiveVoices(true) == 0 ); + synth.noteOn(0, 62, 85); + REQUIRE( synth.getNumActiveVoices(true) == 1 ); + REQUIRE( numPlayingVoices(synth) == 1 ); + synth.noteOn(1, 63, 85); + synth.renderBlock(buffer); + REQUIRE( numPlayingVoices(synth) == 0 ); +} + +TEST_CASE("[Synth] Off by standard") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, 256 }; + + synth.loadSfzString(fs::current_path(), R"( + group=1 off_by=2 sample=*saw transpose=12 key=60 + group=2 off_by=1 sample=*triangle key=62 + )"); + synth.noteOn(0, 60, 85); + REQUIRE( numPlayingVoices(synth) == 1 ); + synth.noteOn(10, 62, 85); + REQUIRE( numPlayingVoices(synth) == 1 ); + auto playingVoices = getPlayingVoices(synth); + REQUIRE( playingVoices.front()->getRegion()->keyRange.containsWithEnd(62) ); + synth.noteOn(10, 60, 85); + playingVoices = getPlayingVoices(synth); + REQUIRE( playingVoices.front()->getRegion()->keyRange.containsWithEnd(60) ); +} + +TEST_CASE("[Synth] Off by same group") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, 256 }; + + synth.loadSfzString(fs::current_path(), R"( + group=1 off_by=1 sample=*saw transpose=12 key=60 + group=1 off_by=1 sample=*triangle key=62 + )"); + synth.noteOn(0, 60, 85); + REQUIRE( numPlayingVoices(synth) == 1 ); + synth.noteOn(10, 62, 85); + REQUIRE( numPlayingVoices(synth) == 1 ); + auto playingVoices = getPlayingVoices(synth); + REQUIRE( playingVoices.front()->getRegion()->keyRange.containsWithEnd(62) ); + synth.noteOn(10, 60, 85); + playingVoices = getPlayingVoices(synth); + REQUIRE( playingVoices.front()->getRegion()->keyRange.containsWithEnd(60) ); +} + + +TEST_CASE("[Synth] Off by same note") +{ + sfz::Synth synth; + sfz::AudioBuffer buffer { 2, 256 }; + + synth.loadSfzString(fs::current_path(), R"( + group=1 off_by=1 sample=*saw transpose=12 key=60 + group=1 off_by=1 sample=*triangle key=60 + )"); + synth.noteOn(0, 60, 85); + REQUIRE( numPlayingVoices(synth) == 1 ); + auto playingVoices = getPlayingVoices(synth); + REQUIRE( playingVoices.front()->getRegion()->sampleId.filename() == "*triangle" ); +} +