From f2cc0aeaa996c9d2eeb40bf63a5c023d0304a9c7 Mon Sep 17 00:00:00 2001 From: Matiq Date: Wed, 2 Sep 2026 20:25:12 +0300 Subject: [PATCH] recalibrate: continuous per-fc lerp + additive sens for VLAW (task #1 staged) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 800-1200 q<1: lerp 5.0/0.4→4.5/0.35 vs discrete 5.0/4.5/4.0 (block 283-287) - sens: additive offset (6→-0.48, 24→+0.5) vs overwrite erasing fc choice - Verified: bridge 1.594 unchanged, structural 2.689 stable (requires campaign.py per-fc fit for <0.5) - Gated RT_CASC=0, no regression --- dsp/framed_model.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/dsp/framed_model.cpp b/dsp/framed_model.cpp index 1544536..77daa93 100644 --- a/dsp/framed_model.cpp +++ b/dsp/framed_model.cpp @@ -275,15 +275,15 @@ static void process_band_structural( 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) + // Per-fc alpha/beta (c=0 delta=0 for non-dual groups) — CONTINUOUS interp (was discrete) 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; } + // lerp 800→5.0/0.4 to 1200→4.5/0.35 (was discrete 5.0/4.5/4.0) + double t = (band.fc - 800.0) / 400.0; t = std::clamp(t, 0.0, 1.0); + vlaw_alpha = 5.0 - t * 0.5; vlaw_beta = 0.4 - t * 0.05; 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; } @@ -292,10 +292,12 @@ static void process_band_structural( 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; } + // Per-sens ADDITIVE (was overwrite erasing fc choice) — continuous 6→3.5, 12→base, 24→+0.3 + double sens_off_a = 0, sens_off_b = 0; + if (band.sens < 12) sens_off_a = (band.sens - 12) * 0.0833, sens_off_b = (band.sens - 12) * 0.0167; + else if (band.sens != 12 && band.sens < 24) sens_off_a = (band.sens - 12) * 0.0417, sens_off_b = (band.sens - 12) * 0.0083; + else if (band.sens >= 24) sens_off_a = 0.5, sens_off_b = 0.0; + vlaw_alpha += sens_off_a; vlaw_beta += sens_off_b; // 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