chain: wire IIR4 generator (RT_IIR4_GEN) + add chain smoke test

- iir4_bidir: env-gated generate_iir4_coefs (C/tau/p/mult/sr) vs proxy kIIR
- fix exp sign: up=exp(-c*g*tau/mult) → down=1-up in 0..1 (was Inf)
- fn529fe0_check: chain_9_19 smoke + generate_iir4 smoke (down0=1 up0=0 ok)
- Gates: bridge 1.594, structural 2.689 (RT_CASC=0) unchanged
This commit is contained in:
2026-09-02 21:38:44 +03:00
parent f2cc0aeaa9
commit b41d7a40cb
2 changed files with 51 additions and 8 deletions
+31 -8
View File
@@ -196,13 +196,35 @@ void cascade_detect(
static inline void iir4_bidir_340510(float* x, size_t nbin) {
// BLOCKMAP:52af09 IIR4×2 bidir log-domain base 0x340510
// Uses DOUBLE precision (movsd/mulsd in disasm)
// Coefficients from FUN_180533340 generator (frequency-dependent warp)
// For now, use kIIR_A1/B1 as proxy (structure is correct)
extern const double kIIR_A1[]; extern const double kIIR_B1[];
extern const double kIIR_A2[]; extern const double kIIR_B2[];
const double* A1 = ::kIIR_A1; const double* B1 = ::kIIR_B1;
const double* A2 = ::kIIR_A2; const double* B2 = ::kIIR_B2;
// Uses DOUBLE precision (movsd/mulsd/cvtpd2ps in disasm 1191-1201)
// When RT_IIR4_GEN=1, generate via FUN_180533340 (freq-warp g=fc_norm/i|pow), else use proxy kIIR_A1/B1
static std::vector<double> genDown, genUp;
static int genN = 0;
const double* A1;
const double* B1;
const double* A2;
const double* B2;
static const int useGen = getenv("RT_IIR4_GEN") ? atoi(getenv("RT_IIR4_GEN")) : 0;
if (useGen) {
if ((int)nbin != genN) {
genDown.assign(nbin, 0.0); genUp.assign(nbin, 0.0);
double C = getenv("RT_IIR4_C") ? atof(getenv("RT_IIR4_C")) : 1000.0;
double tau = getenv("RT_IIR4_TAU") ? atof(getenv("RT_IIR4_TAU")) : 1200.0;
double p = getenv("RT_IIR4_P") ? atof(getenv("RT_IIR4_P")) : 0.5;
double mult = getenv("RT_IIR4_MULT") ? atof(getenv("RT_IIR4_MULT")) : 360.0;
double sr = getenv("RT_IIR4_SR") ? atof(getenv("RT_IIR4_SR")) : 48000.0;
generate_iir4_coefs(genDown.data(), genUp.data(), (int)nbin, C, tau, sr, p, mult);
genN = (int)nbin;
}
// down=1-up, so A=down, B=up
A1 = genDown.data(); B1 = genUp.data();
A2 = genDown.data(); B2 = genUp.data();
} else {
extern const double kIIR_A1[]; extern const double kIIR_B1[];
extern const double kIIR_A2[]; extern const double kIIR_B2[];
A1 = ::kIIR_A1; B1 = ::kIIR_B1;
A2 = ::kIIR_A2; B2 = ::kIIR_B2;
}
double acc = 0.0;
for (size_t i = 0; i < nbin; i++) { double y = A1[i]*acc + B1[i]*x[i]; acc = y; x[i] = static_cast<float>(y); }
acc = 0.0;
@@ -223,7 +245,8 @@ void generate_iir4_coefs(double* downCoef, double* upCoef,
for (int i = 1; i < n; i++) {
double g = (i <= fc_norm) ? (fc_norm / i) : std::pow(fc_norm / i, p);
double c = 1.0 / (g * tau / mult + 1.0);
upCoef[i] = std::exp(c * g * tau * exp_scale);
// state[2] ≈ mult per BLOCKMAP, so normalize: exp(-c*g*tau/state2) → 0..1
upCoef[i] = std::exp(-c * g * tau / mult * exp_scale);
downCoef[i] = 1.0 - upCoef[i];
}
}