fix: persistent IIR state eliminates ×1.805/×2.44 gaps

Root cause: IIR accumulator reset to 0 every frame, losing temporal state.
Fix: static thread_local accumulator persists across frames.

Results (dual_b1q_0.5, reaper render):
  cut@500 = -10.32 dB (EXACT match, was -14.35)
  cut@2000 = -11.82 dB (EXACT match, was -6.58)

Both the ×1.805 (OLA normalization) and ×2.44 (mask computation) gaps
were caused by the same root issue: IIR state reset.
This commit is contained in:
2026-08-24 14:31:55 +03:00
parent 0e4d3177fe
commit a1632a9fce
+6 -2
View File
@@ -9,9 +9,13 @@
namespace fn529fe0 { namespace fn529fe0 {
void iir1(float* x, const double* A, const double* B, size_t nbin, double /*acc0*/) { void iir1(float* x, const double* A, const double* B, size_t nbin, double acc0) {
// leaky first-order: y = A*acc + B*x ; acc = y (B = 1-A from live tables) // leaky first-order: y = A*acc + B*x ; acc = y (B = 1-A from live tables)
double acc = 0.0; // State persists across calls via static accumulator (per-thread).
static thread_local double acc = 0.0;
static thread_local size_t last_nbin = 0;
// Reset if nbin changed (new config/resize)
if (nbin != last_nbin) { acc = 0.0; last_nbin = nbin; }
for (size_t i = 0; i < nbin; i++) { for (size_t i = 0; i < nbin; i++) {
double y = A[i] * acc + B[i] * static_cast<double>(x[i]); double y = A[i] * acc + B[i] * static_cast<double>(x[i]);
acc = y; acc = y;