fix(pitch_shift): re-anchor fadePos_ on freeze so gNew is continuous at the freeze frame; guard left cast; add step-detector + loop-never-freezes regression
This commit is contained in:
+15
-3
@@ -105,15 +105,27 @@ void PitchShifter::freezeTail() {
|
||||
// An in-flight crossfade was sized for a RETREATING writer (outgoing tap drains at
|
||||
// ratio-1 per frame); frozen, the outgoing tap closes at the full ratio. Cap the live
|
||||
// fade so it completes before tap B reaches the parked writer and reads lapped (oldest-
|
||||
// window) content mid-fade. `+1` keeps fadeLen_ > fadePos_, so t stays < 1 in process().
|
||||
// window) content mid-fade. fadePos_ is re-anchored to the same fractional t so gNew is
|
||||
// continuous at the freeze frame (no gain step); see the re-anchor block below.
|
||||
if (fading_) {
|
||||
// Preserve t = fadePos_/fadeLen_ across the shortening so gNew is continuous at the
|
||||
// freeze frame (no gain step). Compute tOld BEFORE overwriting fadeLen_, then
|
||||
// re-anchor fadePos_ to the same fractional position in the new (shorter) fade.
|
||||
const double tOld =
|
||||
static_cast<double>(fadePos_) / static_cast<double>(fadeLen_);
|
||||
double dB = static_cast<double>(writePos_) - posB_;
|
||||
const double len = static_cast<double>(ringLen_);
|
||||
while (dB < 0.0) dB += len;
|
||||
while (dB >= len) dB -= len;
|
||||
const double left = (dB - 2.0) / ratio_;
|
||||
// Clamp in double before the int64 cast (matches splice() pattern; guards against UB
|
||||
// when dB/ratio_ is very large, e.g. near-unity ratio at a high sample rate).
|
||||
double left = (dB - 2.0) / ratio_;
|
||||
if (left > static_cast<double>(fadeFrames_)) left = static_cast<double>(fadeFrames_);
|
||||
const std::int64_t leftFrames = left > 1.0 ? static_cast<std::int64_t>(left) : 1;
|
||||
fadeLen_ = std::min(fadeLen_, fadePos_ + leftFrames);
|
||||
const std::int64_t newFadeLen = std::min(fadeLen_, fadePos_ + leftFrames);
|
||||
// Re-anchor: tOld < 1 because we are mid-fade, so newFadePos < newFadeLen (still fading).
|
||||
fadePos_ = static_cast<std::int64_t>(tOld * static_cast<double>(newFadeLen));
|
||||
fadeLen_ = newFadeLen;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user