22k: bare exp2 chain CONFIRMED on white-noise probe; remaining tone gap = detector level scale x1.14

This commit is contained in:
2026-08-22 20:58:18 +03:00
parent dee3864c3c
commit 355ce828f4
5 changed files with 786 additions and 3 deletions
+21 -3
View File
@@ -123,6 +123,9 @@ static void process_band_structural(
// bidir: forward+backward passes like IIR3.
// off: skip entirely — equivalent of pure per-bin TIME smoothing at
// steady state (DC gain 1 => lvl unchanged).
// time (NOTES 22k): per-bin TIME-domain envelope follower across frames
// using A_ATTACK/A_RELEASE tables as FEED-FORWARD coefficients
// (manual: attack faster on HF; razor-sharp notches). State persists.
static const int iir_mode = getenv("RT_IIR12") ? atoi(getenv("RT_IIR12")) : 1;
auto iir_bidir = [&](float* x, const double* A, const double* B) {
double st = 0.0;
@@ -136,7 +139,18 @@ static void process_band_structural(
x[i] = static_cast<float>(st);
}
};
if (iir_mode == 2) {
static thread_local std::vector<double> env_time;
if (iir_mode == 3) {
if ((int)env_time.size() != (int)nbin) env_time.assign(nbin, 0.0);
for (size_t k2 = 0; k2 < nbin; k2++) {
size_t ti = k2; // tables are already 2049-long, direct bin index
double x = band_level[k2];
double att = kRTAtt[ti], rel = kRTRel[ti];
if (x > env_time[k2]) env_time[k2] += (x - env_time[k2]) * att; // attack: feed-forward
else env_time[k2] = rel * env_time[k2] + (1.0 - rel) * x; // release: retention
band_level[k2] = (float)env_time[k2];
}
} else if (iir_mode == 2) {
iir_bidir(band_level.data(), kIIR_A1, kIIR_B1);
std::copy(band_level.begin(), band_level.begin() + nbin, f6f8.begin());
iir_bidir(band_level.data(), kIIR_A2, kIIR_B2);
@@ -163,7 +177,10 @@ static void process_band_structural(
}
for (size_t k = 0; k < nfft; k++) {
mask_out[k] = static_cast<float>(std::exp2(-static_cast<double>(band_level[k])) * f6f8[k]);
double mm = std::exp2(-static_cast<double>(band_level[k]));
static const int noblend = getenv("RT_NOBLEND") ? atoi(getenv("RT_NOBLEND")) : 0;
if (!noblend) mm *= f6f8[k];
mask_out[k] = static_cast<float>(mm);
}
// RT_DUMP_BIN debug: capture pre-warp mask (opt-in, no cost when unset).
@@ -192,7 +209,8 @@ static void process_band_structural(
// 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++) {
static const int no_iir3 = getenv("RT_NOIIR3") ? atoi(getenv("RT_NOIIR3")) : 0;
for (int pass = 0; pass < 2 && !no_iir3; pass++) {
double st = 0.0;
for (size_t i = 0; i < nbin; i++) {
double y = static_cast<double>(mask_out[i]) * kIIR_B3[i] + st * kIIR_A3[i];