diff --git a/dsp/framed_model.cpp b/dsp/framed_model.cpp index 0a95d97..af2f24c 100644 --- a/dsp/framed_model.cpp +++ b/dsp/framed_model.cpp @@ -84,7 +84,7 @@ static void process_band_structural( constexpr float LUT_A = -13.78f; constexpr float LUT_B = 68.29f; constexpr float LUT_GAMMA = 0.344f; - constexpr float LUT_MULT = 4.4f; + constexpr float LUT_MULT = 4.2f; // res^rp term (bridge parity): smooth frequency-dependent floor constexpr double RP0 = 0.0275; @@ -130,10 +130,23 @@ static void process_band_structural( mask_out[k] *= kBand768[idx] * kWarp[idx] * std::pow(res_k, rp); } - // Step 9 (NOTES_LEVEL:830): IIR3 inline TWICE (kIIR_A3/B3), post-warp - // spectral smoothing of the mask; upper half re-mirrored afterwards. - fn529fe0::iir1(mask_out, kIIR_A3, kIIR_B3, nbin, 0.0); - fn529fe0::iir1(mask_out, kIIR_A3, kIIR_B3, nbin, 0.0); + // Step 9 (NOTES_LEVEL:830 + consumers_out.txt:955-1075): IIR3 inline, + // TWO bidirectional passes [reset, forward, backward] x2 (state persists + // from forward into backward within a pair; reset between pairs). + // y = B3[i]*x[i] + A3[i]*state (decomp operand order verified). + for (int pass = 0; pass < 2; pass++) { + double st = 0.0; + for (size_t i = 0; i < nbin; i++) { + double y = static_cast(mask_out[i]) * kIIR_B3[i] + st * kIIR_A3[i]; + st = y; + mask_out[i] = static_cast(y); + } + for (size_t i = nbin - 2; i >= 1; i--) { + double y = static_cast(mask_out[i]) * kIIR_B3[i] + st * kIIR_A3[i]; + st = y; + mask_out[i] = static_cast(y); + } + } for (size_t k = 0; k < half; k++) { mask_out[nfft - 1 - k] = mask_out[k]; }