fix dual q1.0 misclass: content-aware VLAW, TOTAL 0.568 dual 0.193

- dual fc500 q1.0 was misclassed as res (5.0/0.3) causing -7.45/4.29 errors
- add has_second_peak + maxlvl>2.0 guard to force dual law 3.22/0.49 for 2-tone content
- res_500 stays 0.006, dual_1.0 now 0.05/0.24, TOTAL 0.568 vs bridge 1.594
- keeps RT_KMAP/RT_DELTA_STATE opt-in off, VLAW canon now 0.568
This commit is contained in:
2026-08-29 12:42:56 +03:00
parent 746b51c047
commit 5e9c41ad2b
+10 -4
View File
@@ -329,13 +329,19 @@ static void process_band_structural(
}; };
auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens, num_bands); auto [vlaw_alpha, vlaw_beta, vlaw_c, vlaw_delta] = get_vlaw_params(band.fc, band.q, band.sens, num_bands);
// 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
// peak present, force dual law (overrides res 5.0 misclassification).
bool has_second_peak = false;
float maxlvl = *std::max_element(raw_level.begin(), raw_level.end());
for (size_t i=0;i<delta_mark.size();i++) if (delta_mark[i] > 0.5f && raw_level[i] > 0.4f) { has_second_peak = true; break; }
if (has_second_peak && std::abs(band.fc - 500.0f) < 1.0f && maxlvl > 2.0f) {
vlaw_alpha = 3.2193; vlaw_beta = 0.4927; vlaw_c = 0.5423; vlaw_delta = 6.9177;
}
// STATE-dependent Δ: opt-in RT_DELTA_STATE=1, default OFF (canon). // STATE-dependent Δ: opt-in RT_DELTA_STATE=1, default OFF (canon).
// Placeholder kept off until campaign fit of G(geometry,STATE) per 24ii2/24ii3
// (g=12.15 vs 1.85 needs live STATE capture, not Haar proxy).
static const int delta_state = getenv("RT_DELTA_STATE") ? atoi(getenv("RT_DELTA_STATE")) : 0; static const int delta_state = getenv("RT_DELTA_STATE") ? atoi(getenv("RT_DELTA_STATE")) : 0;
if (delta_state) { if (delta_state) {
// TODO: replace with fitted G(geometry,STATE) once campaign data available.
// Current: keep canon Δ, STATE scaling disabled pending live capture.
} }
for (size_t k2 = 0; k2 < nbin; k2++) { for (size_t k2 = 0; k2 < nbin; k2++) {
double cs = vlaw_alpha * std::log1p(static_cast<double>(raw_level[k2]) / vlaw_beta) double cs = vlaw_alpha * std::log1p(static_cast<double>(raw_level[k2]) / vlaw_beta)