Skip to content

Commit

Permalink
Allow simultaneous notes to choke properly
Browse files Browse the repository at this point in the history
  • Loading branch information
pferrand-soundhound authored and paulfd committed Dec 26, 2023
1 parent 5a51e0b commit 85832f2
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 7 deletions.
16 changes: 9 additions & 7 deletions src/sfizz/ADSREnvelope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,13 +97,15 @@ void ADSREnvelope::getBlockInternal(absl::Span<Float> output) noexcept
size_t count = 0;
size_t size = output.size();

if (shouldRelease && releaseDelay == 0) {
// release takes effect this frame
currentState = State::Release;
releaseDelay = -1;
} else if (shouldRelease && releaseDelay > 0) {
// prevent computing the segment further than release point
size = std::min<size_t>(size, releaseDelay);
if (shouldRelease) {
if (releaseDelay > 0) {
// prevent computing the segment further than release point
size = std::min<size_t>(size, releaseDelay);
} else if (releaseDelay == 0 && delay < 0) {
// release takes effect this frame
currentState = State::Release;
releaseDelay = -1;
}
}

Float previousValue;
Expand Down
44 changes: 44 additions & 0 deletions tests/PolyphonyT.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,3 +588,47 @@ TEST_CASE("[Polyphony] Choke same group and note if the region is switched off (
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;
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"(
<region> key=69 off_by=2 off_mode=normal tune=-3200 ampeg_release=1 sample=snare.wav
<region> key=81 group=2 sample=kick.wav
)");
synth.noteOn(1, 69, 63);
synth.noteOn(1, 81, 127);
synth.renderBlock(buffer);
REQUIRE( activeSamples(synth) == std::vector<std::string> { "snare.wav", "kick.wav" } );
REQUIRE( playingSamples(synth) == std::vector<std::string> { "kick.wav" } );
}

TEST_CASE("[Polyphony] A note coming one sample after another note can choke it")
{
sfz::Synth synth;
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"(
<region> key=69 off_by=2 off_mode=normal tune=-3200 ampeg_release=1 sample=snare.wav
<region> key=81 group=2 sample=kick.wav
)");
synth.noteOn(1, 69, 63);
synth.noteOn(2, 81, 127);
synth.renderBlock(buffer);
REQUIRE( activeSamples(synth) == std::vector<std::string> { "snare.wav", "kick.wav" } );
REQUIRE( playingSamples(synth) == std::vector<std::string> { "kick.wav" } );
}

TEST_CASE("[Polyphony] A note coming one sample before another note cannot choke it")
{
sfz::Synth synth;
sfz::AudioBuffer<float> buffer { 2, static_cast<unsigned>(synth.getSamplesPerBlock()) };
synth.loadSfzString(fs::current_path() / "tests/TestFiles/polyphony.sfz", R"(
<region> key=69 off_by=2 off_mode=normal tune=-3200 ampeg_release=1 sample=snare.wav
<region> key=81 group=2 sample=kick.wav
)");
synth.noteOn(1, 81, 127);
synth.noteOn(2, 69, 63);
synth.renderBlock(buffer);
REQUIRE( playingSamples(synth) == std::vector<std::string> { "kick.wav", "snare.wav" } );
}

0 comments on commit 85832f2

Please sign in to comment.