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
This commit is contained in:
Paul Ferrand 2020-08-19 00:50:09 +02:00
parent 5c61298f08
commit cef44cbdb6
3 changed files with 84 additions and 53 deletions

View file

@ -51,6 +51,10 @@ void sfz::Voice::startVoice(Region* region, int delay, int number, float value,
triggerValue = value; triggerValue = value;
this->region = region; this->region = region;
if (region->disabled)
return;
switchState(State::playing); switchState(State::playing);
ASSERT(delay >= 0); ASSERT(delay >= 0);
@ -715,9 +719,6 @@ bool sfz::Voice::checkOffGroup(int delay, uint32_t group) noexcept
if (region == nullptr) if (region == nullptr)
return false; return false;
if (delay <= this->triggerDelay)
return false;
if (triggerType == TriggerType::NoteOn && region->offBy == group) { if (triggerType == TriggerType::NoteOn && region->offBy == group) {
off(delay); off(delay);
return true; return true;

View file

@ -471,56 +471,6 @@ TEST_CASE("[Files] Note and octave offsets")
REQUIRE( synth.getRegionView(6)->pitchKeycenter == 50 ); REQUIRE( synth.getRegionView(6)->pitchKeycenter == 50 );
} }
TEST_CASE("[Files] Off by with different delays")
{
Synth synth;
synth.setSamplesPerBlock(256);
AudioBuffer<float> 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<float> 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") TEST_CASE("[Files] Off modes")
{ {
Synth synth; Synth synth;

View file

@ -1143,3 +1143,83 @@ TEST_CASE("[Synth] Trigger also on the sustain CC")
synth.cc(0, 64, 127); synth.cc(0, 64, 127);
REQUIRE( synth.getNumActiveVoices(true) == 1 ); 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<float> buffer { 2, 256 };
synth.loadSfzString(fs::current_path(), R"(
<region> key=60 end=-1 sample=*sine
<region> key=61 end=-1 sample=*silence
<region> key=62 sample=*sine off_by=2
<region> 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<float> buffer { 2, 256 };
synth.loadSfzString(fs::current_path(), R"(
<region> group=1 off_by=2 sample=*saw transpose=12 key=60
<region> 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<float> buffer { 2, 256 };
synth.loadSfzString(fs::current_path(), R"(
<region> group=1 off_by=1 sample=*saw transpose=12 key=60
<region> 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<float> buffer { 2, 256 };
synth.loadSfzString(fs::current_path(), R"(
<region> group=1 off_by=1 sample=*saw transpose=12 key=60
<region> 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" );
}