Matiq e343b0a0d0 prd.md: project requirements document. render48k L/R stereo baseline
- Add prd.md (293 lines): project overview, repo structure, build system, DSP architecture, env flags, corpus, status, references
- render48k: current L/R stereo version, TOTAL 2.835 (requires parameter tuning vs canonical 0.341 VLAW dual-solution)
2026-09-02 17:42:51 +03:00

soothe2-re

Обратный инжиниринг DSP-ядра oeksound soothe2 (VST3, Windows x64) → проверяемая реконструкция на C++ с bit-exact целью.

Цель — понять, как именно плагин считает подавление резонансов (уровневый детектор, маска, фильтр), и воспроизвести это дословно. Текущий активный канон — C++ FramedDetector (dsp/framed_model.cpp): real mask-apply цепь с live-таблицами. Канонные команды и метрика — в AGENTS.md.


Статус (24mm14+, 2026-08-29) — ЕДИНСТВЕННЫЙ ИСТОЧНИК TOTAL

Новый канон (структурный render48k 48k/4096 VLAW+EQ, RT_VLAW=1 RT_SYN=1 RT_NOWARP=1 RT_NOIIR3=1 RT_IIR12=0 RT_EQ=1): TOTAL 0.341 dB (dual 0.193/0.438, res 0.284, comb 0.81, t1k 0.36, max 1.17 t1kq_1200). Старый bridge (framed_test 44.1k) 1.594 dB (scripts/baseline_bridge.json) — превзойдён на 1.25. Guard: python3 scripts/corpus_structural.py --out /tmp/v.json (канон 0.341) + python3 scripts/corpus.py --compare scripts/baseline_bridge.json --tol 0.25 (bridge). Следующий шаг — 2. k-маппинг twin/am (handoff/BLOCKMAP_529fe0.md:22v FilterGraph до детектора) для снятия per-fc (800/1200). Детали — handoff/NOTES_LEVEL_INDEX.md.

Цель — bit-exact (гейт = все параметры до декомпа + корпус в шумовой пол). Декомп ~95%, handoff/nls_dasm/ ~140 .dis.

Применение декодировано:

mask(b)   = 10^(cut_D(b)/20)                    ← вещественная, per-bin multiply
cut_D(b)  = α·ln(1+lvl_raw EQ(b)/β)+c [+Δ content-aware, lvl EQ before detector]
lvl_raw   = am/res·scale · W_eq(fc,q,sens) (W=10^(sens·H·0.3/12/20), H=1/√(1+(1.54q^1.33·A)²))
слой      = STFT БЕЗ синтез-окна (RT_SYN=1), EQ до детектора (pipeline_ocr)

Калибровки: α/β/c контент-зависимы (dual 3.22/0.49/0.54 Δ6.92 rms 0.016), q не влияет (24kk), sens линейно, fc-геом через W_eq (24mm14 R bandpass), dual q1.0 misclass пофикшено has_second_peak+maxlvl>2 (dsp/framed_model.cpp:331), t1k_500 4.5/0.35 + comb 0.05/5.0.

  • dual+EQ решено: RT_VLAW+EQ TOTAL 0.341 (канон f40f41e), per-fc 800/1200 ещё нужны (0.341 vs 0.443 без них).
  • Буфер FIR@540668exp(scratch) напрямую (24s), мин.-фазовое exp(siH(s)).
  • Bigkernels IAT: 1803a06a0 / 180296c80 / 180323f20 / 1802dc0e0 (handoff/BLOCKMAP_529fe0.md:540).

Главное за 2026-08-24…28 (24j24mm14)

  1. Применение = побиновный multiply на вещественную маску; «×1.805» = 0.984×1.8345 (экспоненты стадий).
  2. Закон α·ln1p(L/β)+c — три независимых калибровки; константы контент-зависимы.
  3. Слой STFT без синтез-окна (RT_SYN=1); WIN_WINDOW 0.5→0.8 за 2049 сэмплов.
  4. GUI/аудио разделение: FUN_180563a60 — GUI-ветка; аудио-компрессия в шагах 9–19 BLOCKMAP.
  5. Dataflow 916: vec6f8=bandsACC, fma тройками (re,im,coef) ATT/REL, th2000=array-mul, шаг 12=COPY.
  6. Детекторный каскад 180529c60 (vt+0x28): |z| → Haar [0.25,0.5,0.25]×2 → peak/sin → w=1/inner → blend 5407a8.
  7. RFFT до df0 бит-точна (th1a90/th2180 + buf548 scale 2^-12, 24mm9 0.0065 dB).
# Сборка и канонные команды (см. AGENTS.md — runbook):
cmake -S dsp -B dsp/build && cmake --build dsp/build --target framed_test render48k
./dsp/build/render48k /home/m/soothe-bt/tone1kq.wav /tmp/o48.wav 1000,0.99999785,12
python3 scripts/corpus.py --compare scripts/baseline_bridge.json --tol 0.25
python3 scripts/corpus_structural.py --vs-bridge scripts/baseline_bridge.json

Открытые bit-exact пробелы (приоритет → BITEXACT_PLAN.md)

  1. Каскадный симулятор шагов 9–19 — dataflow готов (24hh/24ii), тела bigkernel'ов известны, rms ~0.42 на угаданных формах → оп-за-оп транскрипция + sc_* датасеты.
  2. k-маппинг фронтенда (twin/am, k=0.403 ∀q≥2, 24x).
  3. Δ-правило вторых пиков из pre-combine.

Исторический блок B.1…B.15 (framed_render.py, Pchip, res_power) — см. handoff/archive/NOTES_LEVEL_2026-08-18_2026-08-23.md и roadmap.md; не канон.


Структура репозитория

re-tools/
├── README.md                 ← вы здесь (ЕДИНСТВЕННЫЙ источник TOTAL)
├── AGENTS.md                 ← runbook: сборка, метрика, env-флаги, tooling hazard
├── BITEXACT_PLAN.md          ← план к bit-exact (3 шага, критерии, риски)
├── roadmap.md                ← журнал B-фаз (B.1…B.15, свёрнут; детали → archive)
├── dsp/                      ← реконструкция DSP-пайплайна на C++17
│   ├── framed_model{.cpp,.hpp} ← ГЛАВНЫЙ: mask-apply цепь (канон)
│   ├── framed_test.cpp       ← CLI bridge-рендер (N=2048, SR 44100)
│   ├── render48k.cpp         ← структурная цепь 48k/4096 (resample → chain → resample)
│   ├── rt_mask_tables{.hpp,.cpp}, rt_weights{.hpp,.cpp} ← live-таблицы (IIR A/B, warp)
│   ├── twin{.hpp,.cpp}       ← twin FUN_180535880 (float-parity)
│   ├── levelpath/freqpath/fftconv/vlog/leveltrack/fn529fe0 ← расшифрованные модули
│   ├── fft*.cpp, twiddle_*.cpp/hpp, phase_table.*, cody_waite.hpp
│   └── CMakeLists.txt
├── handoff/
│   ├── NOTES_LEVEL.md        ← живой журнал (голова 24mm5+; хвост → archive/)
│   ├── NOTES_LEVEL_INDEX.md  ← оглавление журнала по датам/темам
│   ├── BLOCKMAP_529fe0.md    ← карта метода FUN_180529fe0 (актуальна)
│   ├── NOTES_TWIN.md         ← twin краткая справка (детали → dsp/twin.cpp)
│   ├── NOTES_CAPTURE.md      ← registry heartbeat, live-таблицы (сжато)
│   ├── archive/              ← история: NOTES_LEVEL_2026-08-18_2026-08-23.md,
│   │                           SESSION_HANDOFF_2026-08-18.md, summary_v4.md
│   └── nls_dasm/             ← 134 дизассембла (f_563440, f_563a60, f529fe0, twin, fft)
├── scripts/
│   ├── corpus.py / corpus_structural.py ← харнессы (guard --compare)
│   ├── rendersnap2.py, campaign.py, disasm_func.py, iat_name.py ← инструменты 24j+
│   └── lawfit22r.py, resalpha.py, cascade_sim.py, wine_*trace.py
├── *.java                    ← Ghidra-скрипты (DumpFuns, ImportRtti …)
├── soothe_mem.bin            ← дамп памяти (вне git, VA0x180000000)
├── rwin_{A0,A1,B0,C0}.npy, r_freqaxis.npy ← живые таблицы (48k)
└── framed_render.py, model_*.py, sim.py ← исторические B-модели (не канон)

Документация

Документ Содержание
AGENTS.md Runbook: сборка, метрика, env-флаги, tooling hazard
BITEXACT_PLAN.md План к bit-exact: 3 шага, критерии, риски, точка входа
handoff/NOTES_LEVEL_INDEX.md Оглавление журнала по датам/темам → NOTES_LEVEL.md / archive/
handoff/NOTES_LEVEL.md Живой журнал (голова 24mm5+; хвост → archive/)
handoff/BLOCKMAP_529fe0.md Карта метода FUN_180529fe0 (актуальна)
handoff/nls_dasm/ 134 дизассембла декомпа
roadmap.md Журнал B-фаз (свёрнут, детали → archive)
handoff/NOTES_TWIN.md Twin краткая справка (детали → dsp/twin.cpp)
handoff/NOTES_CAPTURE.md Registry heartbeat, live-таблицы (сжато)
handoff/archive/ История: NOTES_LEVEL_2026-08-18_2026-08-23.md, SESSION_HANDOFF_…, summary_v4.md

Тестовый корпус /home/m/soothe-bt/ (вне git)

~600 рендеров REAPER (.rpp + .wav). Ключевые наборы:

Префикс Что измеряет
dual_b1q_* 2 тона (500+2000), q 0.1…10 → парадокс red2000>red500 (решён: аддитивный warp)
al_* уровневой свип (fc=1000) → прямое измерение LUT-кривой
t1kq_*, t1k_* 1 тон, fc-скан, уровни −18/0 dBFS → форма полосы
burst500_b1 основной эталон: burst 500 Гц, band1 fc=500 mode=1 sens=12
tone1k, tone1kq, dual входные тоны (0 / 18 / 7.1 dBFS)

Историческая численная модель (B-фазы; канон теперь — C++ FramedDetector, см. выше)

# per-frame, per-bin (framed_render.py — исторический канон B.15)
xv   = log10(A_k / res_k)              # A_k = 2|X_k|/wsum (twin-env), res = |2B/A| case8
C    = G * LUT(xv) + W * warp(f_k)**A  # additive mask (НЕ мультипликация warp·LUT)
gain = max(1 - C, eps) * res_k**rp     # rp = rp0 * Q**drp  (res_power)
  • LUT — Pchip, узлы из joint-фита (dual+al_*) или свободные 8 узлов (B.15 → mean 0.027);
  • warp — эмпирический 0.87·7.942·x/(7.942+x), x=f/2000 (аппроксимация runtime-вычисления FUN_180563440);
  • rp(Q)=0.0275·Q^0.2159 (Q-dep rp, B.14);
  • B.15: G/W/A/rp0/drp = 0.9752/0.3394/1.0222/0.0254/0.2231; LUT KX=[0.8..1.0].

Как всё это воспроизвести

  1. Достать бинарь: установить soothe2 (Windows VST3) под yabridge, запустить dump_soothe.pysoothe_mem.bin (или взять .vst3, выдернуть секции).
  2. Декомпиляция: analyzeHeadless <proj> soothe_x64 -process soothe_mem.bin -noanalysis -postScript <X>.java (image_base=0, блок ram=[0x180000000,…], адреса = RVA; смещение в файле = VA0x180000000).
  3. Рендеры: sweep.py генерит .rpp, reaper -renderproject выдаёт .wav.
  4. Анализ: render_parity.py / framed_render.py сравнивают модель с реальными рендерами (steady-state tone-замер, тримнутая метрика).

Чего не хватает / следующие шаги (bit-exact) → BITEXACT_PLAN.md

  1. Каскадный симулятор шагов 9–19 (приоритет №1) — см. BITEXACT_PLAN.md:1.
  2. k-маппинг фронтенда twin/am (приоритет №2).
  3. Δ-правило вторых пиков (приоритет №3).
S
Description
Reverse engineering of oeksound soothe2 VST3 DSP core → bit-exact buildable C++
Readme
12 MiB
Languages
C++ 59.3%
Python 36.7%
Java 3.7%
Lua 0.2%
CMake 0.1%