Adequate handling of EG release delay, block version

This commit is contained in:
Jean Pierre Cimalando 2020-03-26 21:57:19 +01:00 committed by Paul Fd
parent 1610b047f4
commit 5f6fa5ac1e

View file

@ -102,11 +102,23 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
{
State currentState = this->currentState;
Type currentValue = this->currentValue;
bool shouldRelease = this->shouldRelease;
int releaseDelay = this->releaseDelay;
while (!output.empty()) {
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);
}
switch (currentState) {
case State::Delay:
while (count < size && delay-- > 0) {
@ -139,23 +151,13 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
}
break;
case State::Sustain:
if (freeRunning)
if (!shouldRelease && freeRunning) {
shouldRelease = true;
if (!shouldRelease) {
count = size;
currentValue = sustain;
sfz::fill(output.first(count), currentValue);
}
else {
if (releaseDelay > 0) {
count = clamp<size_t>(releaseDelay, 0, size);
currentValue = sustain;
sfz::fill(output.first(count), currentValue);
releaseDelay -= count;
}
if (releaseDelay <= 0)
currentState = State::Release;
break;
}
count = size;
currentValue = sustain;
sfz::fill(output.first(count), currentValue);
break;
case State::Release:
while (count < size && (currentValue *= releaseRate) > config::virtuallyZero)
@ -172,11 +174,16 @@ void ADSREnvelope<Type>::getBlock(absl::Span<Type> output) noexcept
break;
}
if (shouldRelease)
releaseDelay = std::max(-1, releaseDelay - static_cast<int>(count));
output.remove_prefix(count);
}
this->currentState = currentState;
this->currentValue = currentValue;
this->shouldRelease = shouldRelease;
this->releaseDelay = releaseDelay;
}
template <class Type>
@ -203,9 +210,6 @@ void ADSREnvelope<Type>::startRelease(int releaseDelay, bool fastRelease) noexce
shouldRelease = true;
this->releaseDelay = releaseDelay;
if (releaseDelay == 0)
currentState = State::Release;
if (fastRelease)
this->releaseRate = 0;
}