22j: white-noise probe — real TF is flat (warp not output multiplier), reduction is contrast-driven; adaptive-twin lead
This commit is contained in:
+37
-8
@@ -118,10 +118,33 @@ static void process_band_structural(
|
|||||||
band_level[k] = static_cast<float>(lvl);
|
band_level[k] = static_cast<float>(lvl);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn529fe0::iir1(band_level.data(), kIIR_A1, kIIR_B1, nbin, 0.0);
|
// RT_IIR12 mode (NOTES 22j, EXPERIMENTAL): how IIR1/IIR2 run.
|
||||||
std::copy(band_level.begin(), band_level.begin() + nbin, f6f8.begin());
|
// fwd (default/canon): ascending-bin cascade within frame.
|
||||||
|
// bidir: forward+backward passes like IIR3.
|
||||||
fn529fe0::iir1(band_level.data(), kIIR_A2, kIIR_B2, nbin, 0.0);
|
// off: skip entirely — equivalent of pure per-bin TIME smoothing at
|
||||||
|
// steady state (DC gain 1 => lvl unchanged).
|
||||||
|
static const int iir_mode = getenv("RT_IIR12") ? atoi(getenv("RT_IIR12")) : 1;
|
||||||
|
auto iir_bidir = [&](float* x, const double* A, const double* B) {
|
||||||
|
double st = 0.0;
|
||||||
|
for (size_t i = 0; i < nbin; i++) {
|
||||||
|
st = static_cast<double>(x[i]) * B[i] + st * A[i];
|
||||||
|
x[i] = static_cast<float>(st);
|
||||||
|
}
|
||||||
|
st = x[nbin - 1];
|
||||||
|
for (size_t i = nbin - 2; i >= 1; i--) {
|
||||||
|
st = static_cast<double>(x[i]) * B[i] + st * A[i];
|
||||||
|
x[i] = static_cast<float>(st);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (iir_mode == 2) {
|
||||||
|
iir_bidir(band_level.data(), kIIR_A1, kIIR_B1);
|
||||||
|
std::copy(band_level.begin(), band_level.begin() + nbin, f6f8.begin());
|
||||||
|
iir_bidir(band_level.data(), kIIR_A2, kIIR_B2);
|
||||||
|
} else if (iir_mode == 1) {
|
||||||
|
fn529fe0::iir1(band_level.data(), kIIR_A1, kIIR_B1, nbin, 0.0);
|
||||||
|
std::copy(band_level.begin(), band_level.begin() + nbin, f6f8.begin());
|
||||||
|
fn529fe0::iir1(band_level.data(), kIIR_A2, kIIR_B2, nbin, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
// RT_LVL_CAP: EXPERIMENTAL detector-level cap (NOTES 22f/22g/22h) — the real
|
// RT_LVL_CAP: EXPERIMENTAL detector-level cap (NOTES 22f/22g/22h) — the real
|
||||||
// plugin's reduction floors at blend*ln10/20 (sens12/mix100), implying a cap
|
// plugin's reduction floors at blend*ln10/20 (sens12/mix100), implying a cap
|
||||||
@@ -153,10 +176,16 @@ static void process_band_structural(
|
|||||||
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++) {
|
// RT_NOWARP=1 (NOTES 22j, EXPERIMENTAL): skip warp/W attenuation — white-noise
|
||||||
size_t idx = (k < nbin) ? k : (nfft - 1 - k);
|
// probe shows the real plugin passes broadband content at unity, so the warp
|
||||||
double res_k = std::max(static_cast<double>(res[idx]), 1e-12);
|
// term cannot be a blanket output multiplier.
|
||||||
mask_out[k] *= kBand768[idx] * kWarp[idx] * std::pow(res_k, rp);
|
static const int nowarp = getenv("RT_NOWARP") ? atoi(getenv("RT_NOWARP")) : 0;
|
||||||
|
if (!nowarp) {
|
||||||
|
for (size_t k = 0; k < nfft; k++) {
|
||||||
|
size_t idx = (k < nbin) ? k : (nfft - 1 - k);
|
||||||
|
double res_k = std::max(static_cast<double>(res[idx]), 1e-12);
|
||||||
|
mask_out[k] *= kBand768[idx] * kWarp[idx] * std::pow(res_k, rp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 9 (NOTES_LEVEL:830 + consumers_out.txt:955-1075): IIR3 inline,
|
// Step 9 (NOTES_LEVEL:830 + consumers_out.txt:955-1075): IIR3 inline,
|
||||||
|
|||||||
@@ -1659,3 +1659,39 @@ lvl_raw детектора перестаёт расти при эффектив
|
|||||||
пиков) теряет ~x2.8. ПРИОРИТЕТ СДВИНУТ: чинить детекторный фронт (амплитудная
|
пиков) теряет ~x2.8. ПРИОРИТЕТ СДВИНУТ: чинить детекторный фронт (амплитудная
|
||||||
нормировка am, форма res_k, сила IIR1/2 вдоль частоты), а не форму кривой.
|
нормировка am, форма res_k, сила IIR1/2 вдоль частоты), а не форму кривой.
|
||||||
RT_LVL_CAP оставлен в коде как инструмент (opt-in, инертен при текущих уровнях).
|
RT_LVL_CAP оставлен в коде как инструмент (opt-in, инертен при текущих уровнях).
|
||||||
|
|
||||||
|
## ============ UPDATE 2026-08-22j: WHITE-NOISE PROBE — архитектура расшифрована ============
|
||||||
|
|
||||||
|
Белошумный пробник через сатурированный конфиг (trim0 на шуме −6 dBFS RMS):
|
||||||
|
|
||||||
|
REAL (плагин): передача ПЛОСКАЯ −0.01…−1.65 dB на ВСЕХ частотах;
|
||||||
|
лёгкая вмятина −1.04 @678 (центр полосы), HF rolloff −1.5 @8k.
|
||||||
|
МОДЕЛЬ (canon): фейковый низкочастотный «пол» −24 дБ @50Гц от W=kBand768·kWarp·res^rp.
|
||||||
|
МОДЕЛЬ (NOWARP): форма совпала — плоско ~−2.1…−2.7, вмятина −4.45 @678.
|
||||||
|
|
||||||
|
### ВЫВОДЫ АРХИТЕКТУРЫ
|
||||||
|
1. W=warp НЕ является бланкетным множителем выхода: реальный плагин пропускает
|
||||||
|
широкополосный контент почти на unity ⇒ RT_NOWARP правилен по духу.
|
||||||
|
2. Реальный плагин режет СТАЦИОНАРНЫЙ ТОН на −20.72, но НЕ режет шум ⇒ редукция
|
||||||
|
управляется КОНТРАСТОМ бина к соседям/шумовому полу (смысл IIR1/2 вдоль частоты =
|
||||||
|
бегущий референс), а не абсолютным уровнем.
|
||||||
|
3. Без blend в выходе уровни ШУМА сходятся: real lvl≈+0.123 vs наш +0.098 (Δ0.02 окт);
|
||||||
|
уровни ТОНА: real 3.444 vs наш 3.012 (Δ0.43 окт = ×1.35 амплитуда) ⇒ расхождение
|
||||||
|
растёт с уровнем ⇒ подозрение на res_k (twin АДАПТИРУЕТСЯ к сигналу во времени,
|
||||||
|
res_k уменьшается при длительном тоне) либо am-нормировку при высоких уровнях.
|
||||||
|
4. blend(0.8) в нашей модели даёт фантомный −1.94 dB бланкет — в реальном выходе его нет;
|
||||||
|
exp2(−lvl) без blend точнее описывает шумовой случай.
|
||||||
|
|
||||||
|
### Рабочая гипотеза цепочки (v22j)
|
||||||
|
lvl_raw[k,t] = am[k,t]/res_k(t)·scale (res_k(t) — адаптивный twin!)
|
||||||
|
lvl_ref[k,t] = IIR1/IIR2 вдоль ЧАСТОТЫ от lvl_raw (бегущий референс соседей)
|
||||||
|
редукция = f(lvl_raw − lvl_ref или lvl_raw/lvl_ref) ← контраст
|
||||||
|
mask = exp2(−редукция) (без blend-бланкета)
|
||||||
|
sidechain-in clamp ±1.0 (колено/пин при 0 dBFS)
|
||||||
|
|
||||||
|
### NEXT
|
||||||
|
1. Декод FUN_18052d650/IIR1 семантики заново: аргументы (что есть x, что есть acc),
|
||||||
|
направление и КАК результат используется (референс vs сигнал).
|
||||||
|
2. Тест адаптивного twin: рендер тона разной ДЛИТЕЛЬНОСТИ (0.5/2/8 c) через мост —
|
||||||
|
если пол зависит от длины ⇒ res_k(t) адаптируется, взять динамику из NOTES_TWIN.
|
||||||
|
3. Формулы контраста перебрать офлайн на траекториях RT_DUMP_ALL (движок phaseA готов).
|
||||||
|
|||||||
Reference in New Issue
Block a user