24n-2: Delta-branch implemented (peak+neighbourhood, two-pass); dual end-to-end 9.32/11.58 vs ref 10.32/11.82; VLAW corpus: dual 0.708 (was 3.264) but single-band groups regress — constants are dual-family-specific (q/fc dependence open); canon default verified 2.286
This commit is contained in:
+27
-15
@@ -142,26 +142,38 @@ static void process_band_structural(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RT_VLAW=1 (NOTES 24m): decoded two-stage detector law.
|
// RT_VLAW=1 (NOTES 24m): decoded two-stage detector law.
|
||||||
// cutS(b) = 1.7436*ln(1 + lvl_raw/0.3824) [stage-S, center form]
|
// cutS(b) = 1.729*ln(1 + lvl_raw/0.3824) + Delta(b) [stage-S]
|
||||||
// applied gain = 10^(-gamma0*cutS/20), gamma0 = 1.79
|
// applied gain = 10^(-gamma0*cutS/20), gamma0 = 1.79
|
||||||
|
// Delta-branch: neighbourhoods of off-center content peaks get +4.18 dB.
|
||||||
// Bypasses LUT/exp2/blend/warp/IIR3 entirely.
|
// Bypasses LUT/exp2/blend/warp/IIR3 entirely.
|
||||||
static const int vlaw = getenv("RT_VLAW") ? atoi(getenv("RT_VLAW")) : 0;
|
static const int vlaw = getenv("RT_VLAW") ? atoi(getenv("RT_VLAW")) : 0;
|
||||||
static int frame_dbg_ctr = 0;
|
static int frame_dbg_ctr = 0;
|
||||||
for (size_t k = 0; k < nbin; k++) {
|
if (vlaw) {
|
||||||
double res_k = std::max(static_cast<double>(res[k]), 1e-12);
|
double kfc = static_cast<double>(band.fc) / (sample_rate / 2.0) * (nbin - 1);
|
||||||
double lvl = raw_level[k];
|
static thread_local std::vector<float> delta_mark;
|
||||||
if (vlaw) {
|
delta_mark.assign(nbin, 0.0f);
|
||||||
double cutS = 1.7436 * std::log1p(lvl / 0.3824);
|
for (size_t k2 = 1; k2 + 1 < nbin; k2++) {
|
||||||
double g = std::pow(10.0, -1.79 * cutS / 20.0);
|
if (raw_level[k2] <= 0.25) continue;
|
||||||
if (getenv("RT_VDBG") && (k == 43 || k == 171) && (frame_dbg_ctr < 2))
|
if (std::fabs((double)k2 - kfc) <= 8.0) continue;
|
||||||
fprintf(stderr, "[VLAW] k=%zu lvl=%.5f cutS=%.5f g=%.5f\n",
|
bool lmax = true;
|
||||||
k, lvl, cutS, g);
|
for (int d = -5; d <= 5 && lmax; d++) {
|
||||||
band_level[k] = static_cast<float>(g);
|
int kk = (int)k2 + d;
|
||||||
} else {
|
if (kk < 0 || kk >= (int)nbin || d == 0) continue;
|
||||||
band_level[k] = static_cast<float>(lvl);
|
if (raw_level[kk] > raw_level[k2]) lmax = false;
|
||||||
|
}
|
||||||
|
if (!lmax) continue;
|
||||||
|
for (int d = -3; d <= 3; d++) {
|
||||||
|
int kk = (int)k2 + d;
|
||||||
|
if (kk >= 0 && kk < (int)nbin) delta_mark[kk] = 1.0f;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
for (size_t k2 = 0; k2 < nbin; k2++) {
|
||||||
if (!vlaw)
|
double cs = 1.729 * std::log1p(raw_level[k2] / 0.3824)
|
||||||
|
+ (delta_mark[k2] ? 4.177 : 0.0);
|
||||||
|
band_level[k2] = static_cast<float>(std::pow(10.0, -1.79 * cs / 20.0));
|
||||||
|
}
|
||||||
|
frame_dbg_ctr++;
|
||||||
|
} else
|
||||||
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 = raw_level[k];
|
double lvl = raw_level[k];
|
||||||
|
|||||||
@@ -3119,3 +3119,34 @@ cut@2000=4.14 (реф 11.82 — Δ-ветка ещё не реализована
|
|||||||
калибровка α/γ₀. Следующие шаги: (а) реализовать Δ-ветку (правило второго
|
калибровка α/γ₀. Следующие шаги: (а) реализовать Δ-ветку (правило второго
|
||||||
пика); (б) разобрать слой применения до сходимости; (в) источник γ₀/стадий
|
пика); (б) разобрать слой применения до сходимости; (в) источник γ₀/стадий
|
||||||
в декомпе; (г) корпус с полным флаг-набором.
|
в декомпе; (г) корпус с полным флаг-набором.
|
||||||
|
|
||||||
|
## ============ ДОПОЛНЕНИЕ 24n-2: Δ-ветка в коде; dual 0.708 (было 3.264); константы НЕ универсальны ============
|
||||||
|
|
||||||
|
### Реализовано (framed_model.cpp, vlaw-ветка v2)
|
||||||
|
Δ-правило: локальные максимумы lvl_raw>0.25 вне ±8 бинов от fc помечают
|
||||||
|
окрестность ±3 бина → +4.177 дБ. Двухпроходно (без O(n²)).
|
||||||
|
dual_b1q_0.5 end-to-end: **9.32 / 11.58** vs реф 10.32 / 11.82
|
||||||
|
(скирт −0.24 дБ!, центр −1.0).
|
||||||
|
|
||||||
|
### Корпус с флагами (62 случая):
|
||||||
|
| group | canon | VLAW |
|
||||||
|
|-------|-------|------|
|
||||||
|
| t1kq | 0.768 | 3.633 |
|
||||||
|
| t1k | 2.114 | 3.296 |
|
||||||
|
| al | 0.986 | 2.620 |
|
||||||
|
| res | 0.437 | 3.896 |
|
||||||
|
| **dual** | 3.264 | **0.708** |
|
||||||
|
| comb | 6.116 | 4.014 |
|
||||||
|
| TOTAL | 2.286 | 2.515 |
|
||||||
|
|
||||||
|
### Диагноз регресса одноканальных групп
|
||||||
|
t1kq-диагностика (тон@1000, fc∈{500,1000,2000}):
|
||||||
|
- fc=500 (тон вне центра): реф 5.45, VLAW 10.37 ⇒ Δ НЕ должен применяться к
|
||||||
|
этому случаю (реф = shallow-уровень!); при q≈1 и отступе 500 Гц офсета нет,
|
||||||
|
а в dual (q=0.5, отступ 1500 Гц) был +4.18 ⇒ правило Δ зависит от q/дистанции.
|
||||||
|
- fc=1000 (тон в центре): реф 8.70 vs dual-центр 10.32 при близком lvl ⇒
|
||||||
|
глубина зависит от q/fc — константы α_eff/γ₀_dual не универсальны.
|
||||||
|
Вывод: закон верен В СЕМЕЙСТВЕ калибровки (dual_b1q_0.5: q=0.5, sens=12).
|
||||||
|
Параметризация (α, γ₀, Δ-правило) по (q, fc, sens) — следующая большая задача;
|
||||||
|
методика (rendersnap2+зонды+рампа) готова, датасеты расширяются механически.
|
||||||
|
Канон не тронут: default-корпус воспроизведён (TOTAL 2.286 ✓).
|
||||||
|
|||||||
Reference in New Issue
Block a user