- handoff/NOTES_LEVEL.md 4413→397 (голова 24mm5+), хвост → handoff/archive/NOTES_LEVEL_2026-08-18_2026-08-23.md - handoff/NOTES_LEVEL_INDEX.md NEW навигатор, handoff/archive/ whitelist .gitignore - SESSION_HANDOFF/summary → archive + редиректы, NOTES_TWIN/NOTES_CAPTURE сжаты - README.md:13 единственный источник TOTAL 1.594/dual 0.193, AGENTS runbook, BITEXACT_PLAN 9→3 шага (каскад 9-19/k-маппинг/Δ)
12 KiB
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-28) — ЕДИНСТВЕННЫЙ ИСТОЧНИК TOTAL
Канон (bridge, framed_test 44.1k): TOTAL 2.286 dB — честная 24-bit trimmed метрика, 62 случая (scripts/baseline_bridge.json). Guard: python3 scripts/corpus.py --compare scripts/baseline_bridge.json --tol 0.25. Детали — handoff/NOTES_LEVEL_INDEX.md.
Цель — bit-exact (гейт смены канона = все параметры прослежены до декомпа + корпус в шумовой пол). Декомп DSP-ядра ~95%, handoff/nls_dasm/ ~140 .dis.
Применение декодировано до формул (сессии 24j…24mm14, журнал — handoff/NOTES_LEVEL.md живая голова + handoff/archive/):
mask(b) = 10^(−cut_D(b)/20) ← вещественная, per-bin multiply кадра
cut_D(b) = α·ln(1+lvl_raw(b)/β)+c [+Δ у вторых пиков]
lvl_raw = am/res·scale (наш детектор-фронтенд, float-parity ✓)
слой = STFT БЕЗ синтез-окна (RT_SYN=1)
Калибровки (три независимых семейства, rms ≤0.016 дБ): α/β/c зависят от контента (α удваивается с числом тонов — частотное смешение шаблонно-локальное), q НЕ влияет на закон (24kk), sens линейно через lvl_raw (24kk).
- dual-семейство решено (env-gated): 22 случая mean 0.193 / max 0.438 dB (канон 3.264). Флаги
RT_VLAW=1 RT_SYN=1 RT_NOWARP=1 RT_NOIIR3=1 RT_IIR12=0. Канон не тронут. - Буфер FIR@540668 — промежуточное мин.-фазовое
exp(s−i·H(s)); аудио =exp(scratch)напрямую. - Тела bigkernel'ов (рантайм IAT):
1803a06a0 / 180296c80 / 180323f20 / 1802dc0e0— x87 exp-семейство (handoff/BLOCKMAP_529fe0.md:540).
Главное за 2026-08-24…28 (24j–24mm14)
- Применение = побиновный multiply на вещественную маску; «×1.805» =
0.984×1.8345(экспоненты стадий). - Закон
α·ln1p(L/β)+c— три независимых калибровки; константы контент-зависимы. - Слой STFT без синтез-окна (
RT_SYN=1);WIN_WINDOW0.5→0.8 за 2049 сэмплов. - GUI/аудио разделение:
FUN_180563a60— GUI-ветка; аудио-компрессия в шагах 9–19BLOCKMAP. - Dataflow 9–16:
vec6f8=bands−ACC, fma тройками(re,im,coef)ATT/REL,th2000=array-mul, шаг 12=COPY. - Детекторный каскад
180529c60(vt+0x28):|z| → Haar [0.25,0.5,0.25]×2 → peak/sin → w=1/inner → blend 5407a8. - RFFT до df0 бит-точна (
th1a90/th2180+buf548scale 2^-12,24mm90.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)
- Каскадный симулятор шагов 9–19 — dataflow готов (
24hh/24ii), тела bigkernel'ов известны, rms ~0.42 на угаданных формах → оп-за-оп транскрипция +sc_*датасеты. - k-маппинг фронтенда (twin/am,
k=0.403 ∀q≥2,24x). - Δ-правило вторых пиков из 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, VA−0x180000000)
├── 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].
Как всё это воспроизвести
- Достать бинарь: установить soothe2 (Windows VST3) под yabridge, запустить
dump_soothe.py→soothe_mem.bin(или взять.vst3, выдернуть секции). - Декомпиляция:
analyzeHeadless <proj> soothe_x64 -process soothe_mem.bin -noanalysis -postScript <X>.java(image_base=0, блокram=[0x180000000,…], адреса = RVA; смещение в файле = VA−0x180000000). - Рендеры:
sweep.pyгенерит.rpp,reaper -renderprojectвыдаёт.wav. - Анализ:
render_parity.py/framed_render.pyсравнивают модель с реальными рендерами (steady-state tone-замер, тримнутая метрика).
Чего не хватает / следующие шаги (bit-exact) → BITEXACT_PLAN.md
- Каскадный симулятор шагов 9–19 (приоритет №1) — см.
BITEXACT_PLAN.md:1. - k-маппинг фронтенда twin/am (приоритет №2).
- Δ-правило вторых пиков (приоритет №3).