Add checks for release voices and note_polyphony
This commit is contained in:
parent
1f65c135bc
commit
fa37669e08
3 changed files with 48 additions and 3 deletions
|
|
@ -976,7 +976,8 @@ void sfz::Synth::checkNotePolyphony(const Region* region, int delay, const Trigg
|
||||||
|
|
||||||
for (Voice* voice : voiceViewArray) {
|
for (Voice* voice : voiceViewArray) {
|
||||||
const sfz::TriggerEvent& voiceTriggerEvent = voice->getTriggerEvent();
|
const sfz::TriggerEvent& voiceTriggerEvent = voice->getTriggerEvent();
|
||||||
if (!voice->releasedOrFree()
|
const bool skipVoice = (triggerEvent.type == TriggerEventType::NoteOn && voice->releasedOrFree()) || voice->isFree();
|
||||||
|
if (!skipVoice
|
||||||
&& voice->getRegion()->group == region->group
|
&& voice->getRegion()->group == region->group
|
||||||
&& voiceTriggerEvent.number == triggerEvent.number
|
&& voiceTriggerEvent.number == triggerEvent.number
|
||||||
&& voiceTriggerEvent.type == triggerEvent.type) {
|
&& voiceTriggerEvent.type == triggerEvent.type) {
|
||||||
|
|
@ -984,8 +985,9 @@ void sfz::Synth::checkNotePolyphony(const Region* region, int delay, const Trigg
|
||||||
switch (region->selfMask) {
|
switch (region->selfMask) {
|
||||||
case SfzSelfMask::mask:
|
case SfzSelfMask::mask:
|
||||||
if (voiceTriggerEvent.value <= triggerEvent.value) {
|
if (voiceTriggerEvent.value <= triggerEvent.value) {
|
||||||
if (!selfMaskCandidate || selfMaskCandidate->getTriggerEvent().value > voiceTriggerEvent.value)
|
if (!selfMaskCandidate || selfMaskCandidate->getTriggerEvent().value > voiceTriggerEvent.value) {
|
||||||
selfMaskCandidate = voice;
|
selfMaskCandidate = voice;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SfzSelfMask::dontMask:
|
case SfzSelfMask::dontMask:
|
||||||
|
|
|
||||||
|
|
@ -193,7 +193,7 @@ void sfz::Voice::registerNoteOff(int delay, int noteNumber, float velocity) noex
|
||||||
if (state != State::playing)
|
if (state != State::playing)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (triggerEvent.number == noteNumber) {
|
if (triggerEvent.number == noteNumber && triggerEvent.type == TriggerEventType::NoteOn) {
|
||||||
noteIsOff = true;
|
noteIsOff = true;
|
||||||
|
|
||||||
if (region->loopMode == SfzLoopMode::one_shot)
|
if (region->loopMode == SfzLoopMode::one_shot)
|
||||||
|
|
|
||||||
|
|
@ -286,6 +286,7 @@ TEST_CASE("[Polyphony] Self-masking only works from low to high")
|
||||||
synth.noteOn(0, 64, 63 );
|
synth.noteOn(0, 64, 63 );
|
||||||
synth.noteOn(0, 64, 62 );
|
synth.noteOn(0, 64, 62 );
|
||||||
REQUIRE( synth.getNumActiveVoices(true) == 2 ); // Both notes are playing
|
REQUIRE( synth.getNumActiveVoices(true) == 2 ); // Both notes are playing
|
||||||
|
REQUIRE( numPlayingVoices(synth) == 2 ); // id
|
||||||
REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 63_norm);
|
REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 63_norm);
|
||||||
REQUIRE(!synth.getVoiceView(0)->releasedOrFree());
|
REQUIRE(!synth.getVoiceView(0)->releasedOrFree());
|
||||||
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 62_norm);
|
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 62_norm);
|
||||||
|
|
@ -386,3 +387,45 @@ TEST_CASE("[Polyphony] Note polyphony do not operate across polyphony groups (wi
|
||||||
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 64_norm);
|
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 64_norm);
|
||||||
REQUIRE(!synth.getVoiceView(1)->releasedOrFree());
|
REQUIRE(!synth.getVoiceView(1)->releasedOrFree());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[Polyphony] Note polyphony operates on release voices")
|
||||||
|
{
|
||||||
|
sfz::Synth synth;
|
||||||
|
sfz::AudioBuffer<float> buffer { 2, blockSize };
|
||||||
|
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"(
|
||||||
|
<region> key=48 note_polyphony=1 sample=*saw trigger=release_key ampeg_attack=1 ampeg_decay=1
|
||||||
|
)");
|
||||||
|
synth.noteOn(0, 48, 63 );
|
||||||
|
synth.noteOff(10, 48, 0 );
|
||||||
|
REQUIRE( synth.getNumActiveVoices(true) == 1);
|
||||||
|
synth.noteOn(20, 48, 65 );
|
||||||
|
synth.noteOff(30, 48, 10 );
|
||||||
|
REQUIRE( synth.getNumActiveVoices(true) == 2 );
|
||||||
|
synth.renderBlock(buffer);
|
||||||
|
REQUIRE(numPlayingVoices(synth) == 1 );
|
||||||
|
REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 63_norm);
|
||||||
|
REQUIRE( synth.getVoiceView(0)->releasedOrFree());
|
||||||
|
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 65_norm);
|
||||||
|
REQUIRE(!synth.getVoiceView(1)->releasedOrFree());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("[Polyphony] Note polyphony operates on release voices (masking works from low to high but takes into account the replaced velocity)")
|
||||||
|
{
|
||||||
|
sfz::Synth synth;
|
||||||
|
sfz::AudioBuffer<float> buffer { 2, blockSize };
|
||||||
|
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"(
|
||||||
|
<region> key=48 note_polyphony=1 sample=*saw trigger=release_key ampeg_attack=1 ampeg_decay=1
|
||||||
|
)");
|
||||||
|
synth.noteOn(0, 48, 63 );
|
||||||
|
synth.noteOff(10, 48, 0 );
|
||||||
|
REQUIRE( synth.getNumActiveVoices(true) == 1);
|
||||||
|
REQUIRE( numPlayingVoices(synth) == 1 );
|
||||||
|
synth.noteOn(20, 48, 61 );
|
||||||
|
synth.noteOff(30, 48, 10 );
|
||||||
|
REQUIRE( synth.getNumActiveVoices(true) == 2 );
|
||||||
|
REQUIRE( numPlayingVoices(synth) == 2 );
|
||||||
|
REQUIRE( synth.getVoiceView(0)->getTriggerEvent().value == 63_norm);
|
||||||
|
REQUIRE(!synth.getVoiceView(0)->releasedOrFree());
|
||||||
|
REQUIRE( synth.getVoiceView(1)->getTriggerEvent().value == 61_norm);
|
||||||
|
REQUIRE(!synth.getVoiceView(1)->releasedOrFree());
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue