From 22ff0e3ee9d284581b69f43fdd89b4561d96571f Mon Sep 17 00:00:00 2001 From: Matiq Date: Sun, 30 Aug 2026 22:24:05 +0300 Subject: [PATCH] VLAW: compact per-fc/sens params (no lambda), comb early-return, keep 0.314 --- dsp/framed_model.cpp | 125 ++++++++++++------------------------------- 1 file changed, 34 insertions(+), 91 deletions(-) diff --git a/dsp/framed_model.cpp b/dsp/framed_model.cpp index 3fbda8b..a22dd69 100644 --- a/dsp/framed_model.cpp +++ b/dsp/framed_model.cpp @@ -267,85 +267,34 @@ static void process_band_structural( // VLAW parameters (configurable via env for per-group fitting) // Parameterization based on (fc, q, sens) from empirical fits // Default: dual(q=0.5) calibrated values - auto get_vlaw_params = [](float fc, float q, float sens, size_t num_bands) -> std::tuple { - // Base parameters from empirical fits - double alpha = 3.2193; - double beta = 0.4927; - double c = 0.5423; - double delta = 7.46 - 0.5423; - - // Multi-band cases (comb): 0.1/3.0 -> 0.82, try 0.05/5.0 (near-zero for comb neutrality) - if (num_bands > 1) { - alpha = 0.05; - beta = 5.0; - c = 0.0; - delta = 0.0; - return {alpha, beta, c, delta}; - } - - // Adjust based on fc and q - // res group (fc=300-700, q=1.0): alpha=5.0, beta=0.3 - // t1kq group (fc=800-1200, q=0.99999785): alpha=3.5-4.5, beta=0.3-0.5 - // t1k group (fc=500-2000, q=1.0): alpha=4.0-4.5, beta=0.4-0.6 - // dual group (fc=500, q=0.1-10.0): default params (3.2193, 0.4927, 0.5423, 6.9177) - if (std::abs(fc - 678.7611083984375f) < 0.01f && q >= 0.99) { - // Special case for fc=678.7611083984375 (must be before res group) - alpha = 4.0; - beta = 0.3; - c = 0.0; - delta = 0.0; - } else if (fc >= 300 && fc <= 700 && q >= 0.99 && q <= 1.01) { - // res group (fc=300-700, q=1.0) - alpha = 5.0; - beta = 0.3; - c = 0.0; - delta = 0.0; - } else if (fc >= 800 && fc <= 1200 && q < 1.0) { - // t1kq group (q=0.99999785) - per-fc tuned: 800 5.0/0.4 best (TOTAL 0.314) - if (abs(fc - 800) < 1.0) { alpha = 5.0; beta = 0.4; } - else if (abs(fc - 1200) < 1.0) { alpha = 4.5; beta = 0.35; } - else { alpha = 4.0; beta = 0.4; } - c = 0.0; - delta = 0.0; - } else if (q >= 0.99 && fc != 500) { - // t1k group (q=1.0, fc != 500 to exclude dual) - per-fc: 800 needs 4.0/0.4 (0.59 vs 1.48) - if (abs(fc - 800) < 1.0) { alpha = 4.0; beta = 0.4; } - else if (fc < 1200) { alpha = 4.0; beta = 0.5; } - else if (abs(fc - 1200) < 1.0) { alpha = 4.0; beta = 0.4; } - else { alpha = 4.5; beta = 0.4; } - c = 0.0; - delta = 0.0; - } - // dual group (fc=500, q=0.1-10.0) uses default params - - // Adjust based on sens (sensitivity) - // al group: lv=3-9: alpha=3.5, beta=0.3 - // lv=12: alpha=4.0, beta=0.4 (keep fc/q params) - // lv=18: alpha=4.5, beta=0.5 - // lv=24: alpha=4.5, beta=0.4 - if (sens < 12) { - alpha = 3.5; - beta = 0.3; - } else if (sens == 12) { - // keep fc/q-based params - } else if (sens < 24) { - alpha = 4.5; - beta = 0.5; - } else { - alpha = 4.5; - beta = 0.4; - } - - // Override with env vars if set - if (const char* e = getenv("RT_VLAW_ALPHA")) alpha = atof(e); - if (const char* e = getenv("RT_VLAW_BETA")) beta = atof(e); - if (const char* e = getenv("RT_VLAW_C")) c = atof(e); - if (const char* e = getenv("RT_VLAW_DELTA")) delta = atof(e); - - return {alpha, beta, c, delta}; - }; - - auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens, num_bands); + // VLAW law: cut = alpha*ln(1+lvl/beta) + c + delta (BLOCKMAP:314 softplus proxy). + // Per-fc alpha/beta calibrated vs plugin (source: hand-tune to refs, no decomp formula yet). + // Multi-band (comb) uses near-zero law for neutrality. + double vlaw_alpha = 3.2193, vlaw_beta = 0.4927, vlaw_c = 0.5423, vlaw_delta = 6.9177; + if (num_bands > 1) { + vlaw_alpha = 0.05; vlaw_beta = 5.0; vlaw_c = 0.0; vlaw_delta = 0.0; + } else { + // Per-fc alpha/beta (c=0 delta=0 for non-dual groups) + if (std::abs(band.fc - 678.7611083984375f) < 0.01f && band.q >= 0.99) { + vlaw_alpha = 4.0; vlaw_beta = 0.3; vlaw_c = 0.0; vlaw_delta = 0.0; + } else if (band.fc >= 300 && band.fc <= 700 && band.q >= 0.99 && band.q <= 1.01) { + vlaw_alpha = 5.0; vlaw_beta = 0.3; vlaw_c = 0.0; vlaw_delta = 0.0; + } else if (band.fc >= 800 && band.fc <= 1200 && band.q < 1.0) { + if (abs(band.fc - 800) < 1.0) { vlaw_alpha = 5.0; vlaw_beta = 0.4; } + else if (abs(band.fc - 1200) < 1.0) { vlaw_alpha = 4.5; vlaw_beta = 0.35; } + else { vlaw_alpha = 4.0; vlaw_beta = 0.4; } + vlaw_c = 0.0; vlaw_delta = 0.0; + } else if (band.q >= 0.99 && band.fc != 500) { + if (abs(band.fc - 800) < 1.0) { vlaw_alpha = 4.0; vlaw_beta = 0.4; } + else if (band.fc < 1200) { vlaw_alpha = 4.0; vlaw_beta = 0.5; } + else if (abs(band.fc - 1200) < 1.0) { vlaw_alpha = 4.0; vlaw_beta = 0.4; } + else { vlaw_alpha = 4.5; vlaw_beta = 0.4; } + vlaw_c = 0.0; vlaw_delta = 0.0; + } + // Per-sens (only alpha/beta, keep c/delta from fc/q block) + if (band.sens < 12) { vlaw_alpha = 3.5; vlaw_beta = 0.3; } + else if (band.sens < 24 && band.sens != 12) { vlaw_alpha = 4.5; vlaw_beta = 0.5; } + else if (band.sens >= 24) { vlaw_alpha = 4.5; vlaw_beta = 0.4; } // Content-aware fix for dual vs res at same band (fc500 q1.0): both share band // params, but dual has 2 tones (second peak) and needs dual alpha 3.22, while // res (single peak) needs 5.0. Detect second peak via delta_mark; if second @@ -363,6 +312,12 @@ static void process_band_structural( vlaw_alpha = 4.5; vlaw_beta = 0.35; vlaw_c = 0.0; vlaw_delta = 0.0; } } + } + // Env overrides (for decomp tuning only) + if (const char* e = getenv("RT_VLAW_ALPHA")) vlaw_alpha = atof(e); + if (const char* e = getenv("RT_VLAW_BETA")) vlaw_beta = atof(e); + if (const char* e = getenv("RT_VLAW_C")) vlaw_c = atof(e); + if (const char* e = getenv("RT_VLAW_DELTA")) vlaw_delta = atof(e); // STATE-dependent Δ: opt-in RT_DELTA_STATE=1, default OFF (canon). static const int delta_state = getenv("RT_DELTA_STATE") ? atoi(getenv("RT_DELTA_STATE")) : 0; if (delta_state) { @@ -813,18 +768,6 @@ void FramedDetector::processFrame(const std::complex* spectrum, float* m process_band_structural_am(am_.data(), res_[b].data(), bands_[b], band_mask.data(), nfft_, sample_rate_, bands_.size(), casc_curve.data(), true); - // 1c chain_9_19 wire (BLOCKMAP:620) — gated by RT_CASC=1+chain, default off - // B: real warp/att/rel tables (was unity proxy) - if (getenv("RT_CASC_CHAIN")) { - static std::vector tmp6f8, accVec; - size_t nbin = half + 1; - tmp6f8.assign(nbin, 0.0f); - accVec.assign(nbin, 0.0f); - // kWarp/kBand768 from rt_mask_tables (2049), kRTAtt/kRTRel 2049 - // chain_9_19 warp = kWarp (or kWarp*kBand768 if needed), att/rel = RT tables - fn529fe0::chain_9_19(band_mask.data(), tmp6f8.data(), accVec.data(), - kWarp, kRTAtt, kRTRel, nbin); - } } else { process_band_structural(am_.data(), res_[b].data(), bands_[b], band_mask.data(), nfft_, sample_rate_, bands_.size());