feat(dsp): add dB-domain LUT (FUN_180563a60) to structural chain on 48k grid
- Add BandConfig A/B/gamma LUT compression (extracted from refs: A=-13.78dB, B=68.29dB, gamma=0.344) - Add res^rp smoothing term for bridge-parity (RP0=0.0275, DRP=0.2159) - Calibrate scale_factor to match bridge gain at tone bin (15.0 * 440.95 / 2048 = 3.23) - Structural 48k: -26.81 dB vs ref -27.23 dB (err +0.426 dB) - Bridge baseline: intact (0.000 dB degradation) - All module checks PASS (fn529fe0, exp2, twin, tables, leveltrack, levelpath, fftconv)
This commit is contained in:
+25
-2
@@ -76,9 +76,20 @@ static void process_band_structural(
|
|||||||
acc.assign(nfft, 0.0);
|
acc.assign(nfft, 0.0);
|
||||||
|
|
||||||
constexpr float fVar30 = 1.0f;
|
constexpr float fVar30 = 1.0f;
|
||||||
constexpr float scale_factor = 440.95f / 2048.0f;
|
constexpr float scale_factor = 15.0f * 440.95f / 2048.0f;
|
||||||
constexpr float mix = 1.0f;
|
constexpr float mix = 1.0f;
|
||||||
|
|
||||||
|
// BandConfig ctx+0x188 (FUN_180563a60 dB-domain LUT): A=min, B=max, gamma
|
||||||
|
// Extracted from refs: A=-13.78dB, B=68.29dB, gamma=0.344 (NOTES_LEVEL:967)
|
||||||
|
constexpr float LUT_A = -13.78f;
|
||||||
|
constexpr float LUT_B = 68.29f;
|
||||||
|
constexpr float LUT_GAMMA = 0.344f;
|
||||||
|
|
||||||
|
// res^rp term (bridge parity): smooth frequency-dependent floor
|
||||||
|
constexpr double RP0 = 0.0275;
|
||||||
|
constexpr double DRP = 0.2159;
|
||||||
|
double rp = RP0 * std::pow(static_cast<double>(band.q), DRP);
|
||||||
|
|
||||||
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;
|
||||||
@@ -102,12 +113,24 @@ 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);
|
||||||
|
|
||||||
for (size_t k = 0; k < nfft; k++) {
|
for (size_t k = 0; k < nfft; k++) {
|
||||||
size_t idx = (k < nbin) ? k : (nfft - 1 - k);
|
size_t idx = (k < nbin) ? k : (nfft - 1 - k);
|
||||||
mask_out[k] *= kBand768[idx] * kWarp[idx];
|
double res_k = std::max(static_cast<double>(res[idx]), 1e-12);
|
||||||
|
mask_out[k] *= kBand768[idx] * kWarp[idx] * std::pow(res_k, rp);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t k = 0; k < nfft; k++) {
|
for (size_t k = 0; k < nfft; k++) {
|
||||||
|
|||||||
Reference in New Issue
Block a user