feat(dsp): move dB-LUT to level domain (pre-IIR/exp2) in structural chain

Mask-domain LUT clamps t<0 on loud input (t1k mask_dB < A=-13.78) causing
-24dB over-cut. Level-domain keeps quiet/loud inside [A,B] domain:
t1k err -24.04 -> +2.45 dB (3-case smoke: mean|err| 8.2 -> 1.09).
Params: gamma=0.344 (decomp-extracted), mult=3.8 (placeholder, empirical).
Module checks pass; corpus (bridge path) unchanged at 1.594.
This commit is contained in:
2026-08-21 12:35:57 +03:00
parent 9b7e9d3099
commit 535b150f75
+8 -11
View File
@@ -84,6 +84,7 @@ static void process_band_structural(
constexpr float LUT_A = -13.78f; constexpr float LUT_A = -13.78f;
constexpr float LUT_B = 68.29f; constexpr float LUT_B = 68.29f;
constexpr float LUT_GAMMA = 0.344f; constexpr float LUT_GAMMA = 0.344f;
constexpr float LUT_MULT = 3.8f;
// res^rp term (bridge parity): smooth frequency-dependent floor // res^rp term (bridge parity): smooth frequency-dependent floor
constexpr double RP0 = 0.0275; constexpr double RP0 = 0.0275;
@@ -93,6 +94,13 @@ static void process_band_structural(
for (size_t k = 0; k < nbin; k++) { for (size_t k = 0; k < nbin; k++) {
double res_k = std::max(static_cast<double>(res[k]), 1e-12); double res_k = std::max(static_cast<double>(res[k]), 1e-12);
double lvl = static_cast<double>(am[k]) / res_k * scale_factor; double lvl = static_cast<double>(am[k]) / res_k * scale_factor;
// dB-domain LUT (FUN_180563a60) on LEVEL before IIR/exp2: keeps both
// quiet (t1kq) and loud (t1k) inputs inside the LUT domain [A,B],
// avoiding the t<0 clamp collapse that mask-domain LUT hits on loud input.
double dB = std::log10(std::max(lvl, 1e-12)) * 20.0;
double t = (dB - LUT_A) / (LUT_B - LUT_A);
t = std::min(std::max(t, 0.0), 1.0);
lvl = std::pow(t, static_cast<double>(LUT_GAMMA)) * LUT_MULT;
band_level[k] = static_cast<float>(lvl); band_level[k] = static_cast<float>(lvl);
} }
@@ -113,17 +121,6 @@ static void process_band_structural(
mask_out[k] = static_cast<float>(std::exp2(-static_cast<double>(band_level[k])) * f6f8[k]); mask_out[k] = static_cast<float>(std::exp2(-static_cast<double>(band_level[k])) * f6f8[k]);
} }
// dB-domain LUT compression (FUN_180563a60): mask_dB -> t -> t^gamma -> linear
// Compresses the exp2 collapse into a smooth log curve (NOTES_LEVEL:948)
for (size_t k = 0; k < nfft; k++) {
double m = std::max(static_cast<double>(mask_out[k]), 1e-12);
double dB = std::log10(m) * 20.0;
double t = (dB - LUT_A) / (LUT_B - LUT_A);
t = std::min(std::max(t, 0.0), 1.0);
double val = std::pow(t, static_cast<double>(LUT_GAMMA));
mask_out[k] = static_cast<float>(val);
}
fn529fe0::combine_acc(acc.data(), band_level.data(), f6f8.data(), fn529fe0::combine_acc(acc.data(), band_level.data(), f6f8.data(),
kRTAtt, kRTRel, nfft); kRTAtt, kRTRel, nfft);