diff --git a/core/src/orbit_delay_core.cpp b/core/src/orbit_delay_core.cpp index a476a27..6dae22b 100644 --- a/core/src/orbit_delay_core.cpp +++ b/core/src/orbit_delay_core.cpp @@ -713,19 +713,35 @@ float OrbitDelayCore::processChannelFast(float input, const float maxGuardBySize = 0.25f * delaySize; const float guardSamples = clampf(kOrbitReadGuardMinSamples, 1.0f, maxGuardBySize); if (readMode_ == ReadMode::AccidentalReverse) { - float reverseDelaySamples = params.tempoDelaySamples + spread + lfoSamples; + // Effective reverse delay follows the smoothed tempo delay plus the same + // channel-dependent offsets used by the forward path. + float reverseDelaySamples = params.tempoDelaySamples + params.offsetSamples + spread + lfoSamples; reverseDelaySamples = clampf(reverseDelaySamples, guardSamples, fmaxf(delaySize - guardSamples, guardSamples)); float& reverseCounter = (&delay == &delayL_) ? reverseCounterL_ : reverseCounterR_; float& reverseWindowSize = (&delay == &delayL_) ? reverseWindowSizeL_ : reverseWindowSizeR_; - const float readPos = wrapPosFloat(writePos - reverseDelaySamples + reverseCounter, delaySize, invDelaySize); - const float distanceBackward = wrapPosFloat(writePos - readPos, delaySize, invDelaySize); - if (distanceBackward < guardSamples || distanceBackward > (delaySize - guardSamples)) { + + // Safe fallback: insufficient usable region between the two guard bands + // for the minimum reverse window size. + constexpr float kMinReverseWindowSamples = 8.0f; + if (delaySize < kMinReverseWindowSamples + 2.0f * guardSamples) { reverseCounter = 0.0f; reverseWindowSize = 0.0f; reverseDelaySamples = guardSamples; + wet = 0.0f; + baseReadPos = wrapPosFloat(writePos - guardSamples, delaySize, invDelaySize); + } else { + const float readPos = wrapPosFloat(writePos - reverseDelaySamples + reverseCounter, delaySize, invDelaySize); + const float distanceBackward = wrapPosFloat(writePos - readPos, delaySize, invDelaySize); + if (distanceBackward < guardSamples || distanceBackward > (delaySize - guardSamples)) { + reverseCounter = 0.0f; + reverseWindowSize = 0.0f; + reverseDelaySamples = guardSamples; + } + // Window size is explicitly derived in readReverseWindowed() from this + // effective smoothed delay value. + wet = readReverseWindowed(delay, reverseDelaySamples, writePos, delaySize, invDelaySize, reverseCounter, reverseWindowSize); + baseReadPos = wrapPosFloat(writePos - reverseDelaySamples + reverseCounter, delaySize, invDelaySize); } - wet = readReverseWindowed(delay, reverseDelaySamples, writePos, delaySize, invDelaySize, reverseCounter, reverseWindowSize); - baseReadPos = wrapPosFloat(writePos - reverseDelaySamples + reverseCounter, delaySize, invDelaySize); } else { const float orbitDelaySamples = params.tempoDelaySamples * params.orbit; const float modulatedDelaySamples = orbitDelaySamples + params.offsetSamples + spread + lfoSamples;