Releasing in the initial delay kills the voice

This commit is contained in:
Paul Ferrand 2019-12-21 15:32:38 +01:00
parent 8ceb5f3b48
commit 68bf0b132d
5 changed files with 37 additions and 3 deletions

View file

@ -217,6 +217,12 @@ bool ADSREnvelope<Type>::isSmoothing() noexcept
return currentState != State::Done;
}
template <class Type>
int ADSREnvelope<Type>::getRemainingDelay() const noexcept
{
return delay;
}
template <class Type>
void ADSREnvelope<Type>::startRelease(int releaseDelay) noexcept
{

View file

@ -75,6 +75,12 @@ public:
* @return false
*/
bool isSmoothing() noexcept;
/**
* @brief Get the remaining delay samples
*
* @return int
*/
int getRemainingDelay() const noexcept;
private:
enum class State {

View file

@ -127,12 +127,17 @@ void sfz::Voice::prepareEGEnvelope(int channel, int delay, uint8_t velocity) noe
bool sfz::Voice::isFree() const noexcept
{
return (region == nullptr);
return (state == State::idle);
}
void sfz::Voice::release(int delay) noexcept
{
if (state == State::playing) {
if (state != State::playing)
return;
if (egEnvelope.getRemainingDelay() >= (delay - initialDelay)) {
reset();
} else {
state = State::release;
egEnvelope.startRelease(delay);
}

View file

@ -203,4 +203,20 @@ TEST_CASE("[Synth] Reset all controllers")
synth.cc(0, 0, 121, 64);
REQUIRE( synth.getMidiState().getCCValue(0, 12) == 0 );
REQUIRE( synth.getMidiState().getCCValue(1, 12) == 64 );
}
}
TEST_CASE("[Synth] Releasing before the EG started smoothing (initial delay) kills the voice")
{
sfz::Synth synth;
synth.setSamplesPerBlock(1024);
synth.setNumVoices(1);
synth.loadSfzFile(fs::current_path() / "tests/TestFiles/delay_release.sfz");
synth.noteOn(0, 1, 60, 63);
REQUIRE( !synth.getVoiceView(0)->isFree() );
synth.noteOff(100, 1, 60, 63);
REQUIRE( synth.getVoiceView(0)->isFree() );
synth.noteOn(200, 1, 60, 63);
REQUIRE( !synth.getVoiceView(0)->isFree() );
synth.noteOff(1000, 1, 60, 63);
REQUIRE( !synth.getVoiceView(0)->isFree() );
}

View file

@ -0,0 +1 @@
<region> delay=0.005 sample=dummy1.wav