From f17ee7806103377e1c7632415dc418a5d8b1f09e Mon Sep 17 00:00:00 2001 From: Matiq Date: Fri, 21 Aug 2026 01:00:41 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20BITEXACT=5FPLAN=20=E2=80=94=208-step=20?= =?UTF-8?q?path=20to=20byte-parity;=20fix=20repo=20docs=20to=20reflect=20n?= =?UTF-8?q?ot-yet-bit-exact=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- AGENTS.md | 5 ++ BITEXACT_PLAN.md | 136 +++++++++++++++++++++++++++++++++++++++++++++++ README.md | 1 + roadmap.md | 6 +++ 4 files changed, 148 insertions(+) create mode 100644 BITEXACT_PLAN.md diff --git a/AGENTS.md b/AGENTS.md index 3bedf28..e776dd8 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,6 +4,11 @@ Bit-exact реверс DSP-ядра oeksound soothe2 (VST3) → транскри Полное журналирование — в `handoff/NOTES_LEVEL.md`, `handoff/NOTES_TWIN.md`, `handoff/NOTES_CAPTURE.md`, `roadmap.md`. +> **Текущая фаза: bit-exact НЕ достигнут** — мы на dB-параллели (полный корпус mean 1.594 +> dB, comb 10 dB). Путь к байтам — в `BITEXACT_PLAN.md` (8 шагов, порядок и критерии). +> ЭТОТ ФАЙЛ ЧИТАЙ ПЕРВЫМ. Bridge-модель — запасной канон; структурная цепочка +> FUN_180529fe0 (Шаг 1-2 плана) — целевая. + ## Золотое правило (обязательно) 1. **Цель — bit-exact реверс кода**, НЕ эмпирическая подгонка кривых. Каждый параметр должен иметь источник (decomp адрес / live-таблица), а не быть подогнанным числом. diff --git a/BITEXACT_PLAN.md b/BITEXACT_PLAN.md new file mode 100644 index 0000000..6a5cf61 --- /dev/null +++ b/BITEXACT_PLAN.md @@ -0,0 +1,136 @@ +# BIT-EXACT PLAN — путь от dB-приближения к побайтовой парности + +Статус: **НЕ bit-exact**. Мы на уровне честной dB-параллели (полный корпус mean 1.594 dB, +comb 10 dB). Bit-exact ДОСТИЖИМ (F0 gate: плагин байт-детерминирован), но модель ещё не +воспроизводит реальный DSP-путь. Этот документ — план, как туда дойти, и точка отсчёта +для любой будущей сессии. **Читать вместе с `AGENTS.md` и `handoff/NOTES_LEVEL.md`.** + +Цель фазы C (bit-exact): воспроизвести `FramedDetector` (= fn `FUN_180529fe0` mono-path) +настолько точно, что `verify_bit_exact.py` даёт побайтовое совпадение на рендерах +(`t1kq_*`, `dual_*`, `comb_*`). Ниже — конкретный порядок, что и зачем. + +--- + +## 0. Текущее состояние (честная метрика, 24-bit, trimmed, 62 случая) + +| Группа | mean|err| (dB) | max | Уровень | +|--------|----------|-----|---------| +| t1kq (fc-scan) | 0.226 | 0.500 | ✓ ближе всего | +| t1k (loud 0 dBFS) | 1.801 | 2.227 | ! уровневая | +| al (level sweep) | 0.638 | 1.596 | ! уровневая | +| res | 0.628 | 1.535 | ! | +| dual (q-sweep) | 0.726 | 2.252 | ! | +| comb (4-band) | **10.149** | **14.752** | ✗ сломан | +| **TOTAL** | **1.594** | **14.752** | | + +**Корень проблемы**: активный канон — ЭМПИРИЧЕСКАЯ bridge-модель +`C = G·LUT(xv) + W·warp(f)^A; gain = (1−C)·res^rp` (xv=log10(am/res)). Это ПОГОНА, не +транскрипция. Структурная цепочка FUN_180529fe0 (IIR1/2/3 → exp2 → combine/acc → warp → +dry/wet → FFT-conv) расшифрована и live-таблицы извлечены (`dsp/rt_mask_tables`, +`dsp/rt_weights`), но при переносе в C++ (Phase B, da63adc) **регрессировала** и откачена +на bridge. Дальше надо вернуться к структурной цепочке и закрыть её по-настоящему. + +--- + +## 1. Порядок работ (обязательный порядок; каждый шаг валидируется отдельно) + +### Шаг 1 — Реализовать полную структурную mono-цепочку FUN_180529fe0 (КОРЕНЬ) +Заменить bridge (эмпирическую погону) на точную транскрипцию. Реализовать в +`dsp/framed_model.cpp` (или отдельном `dsp/fn529fe0.cpp`) по NOTES_LEVEL:820-840: +``` +1. scale: band_mask *= (fVar30/0x1a0)·0x540870·0x54088c (fVar30=1 из PRNG, locked) +2. IIR1: y[i]=A1[i]·acc+B1[i]·x[i] (kIIR_A1/B1, fast attack) -> f6f8 +3. copy f6f8 <- band +4. IIR2: inline, kIIR_A2/B2 (slow release) +5. mirror upper half = reversed lower (Hermitian) +6. blend: f6f8 = 0x540698·(1−mix)+mix·0.8; mask = exp2(−level)·f6f8 +7. combine: acc[band] = 0x540678 − 0x5406f8; mirror; + += 0x5406c8·upper; += 0x5406e8·lower; += 0x540678 +8. warp: mask *= kBand768[band]; mask *= kWarp (TWO warps) +9. IIR3: inline TWICE, kIIR_A3/B3 +10. dry/wet: mask = mask·(fVar30·0x540888)+(1−fVar30) (=identity сейчас) +11. FFT-conv (Шаг 4) +``` +Критерий: на однополосных t1kq/t1k/al/res структурная цепочка должна НЕ регрессировать +ниже bridge (т.е. mean ≤ 0.6-0.8). ВАЖНО: прошлый регресс (F2) был из-за неверного +домена (пробовали combine в bridge-финале). Здесь combine/exp2 — в ЕГО собственном +домене (reduction/exp2), как в декомпе. + +### Шаг 2 — combine/аккумулятор 0x5407c8 (закрывает comb + negative-sens) +Точные веса `kRTAtt`/`kRTRel` (0x5406c8/6e8) уже в `dsp/rt_weights.cpp`. Реализовать +combine строго по декомпу: `acc = band − f6f8; += w_att·upper; += w_rel·lower; += band` +в exp2/REDUCTION-домене (не в bridge-final-gain). Ожидается: comb перестаёт пережимать, +negative-sens (band2 sens=−12) даёт компенсацию. Критерий: comb mean ≤ 2-3 dB (с −15 до +нейтрали), и MB-ваимодействие (comb_all ≈ 0) воспроизводится. + +### Шаг 3 — Bit-exact exp2 (F5b) +Заменить `std::exp2`/`exp2d::exp2_dsp` на точную табличную реализацию `0x26b820`: +таблицы уже извлечены (`dsp/exp2_tables.{hpp,cpp}`, 8×16 irr + серия kExp2_big). Нужно +транскрибировать body 1:1 (Cody-Waite hi/lo, vfmadd213sd-полином, спец-ветви subnormal/ +overflow). Пока не bit-exact — оставить `exp2d::exp2_dsp` (численно = std::exp2). +Критерий: `exp2_check` сравнивает протв захваченных пар точка-в-точку. + +### Шаг 4 — FFT-conv 0x535a70 + FIR +FFT-conv сглаживает маску перед FIR (0x540658 window / freqaxis). Это последний этап +mono-цепи. `dsp/fftconv.cpp` есть, но нужна точная блоковая обработка (overlap-save как +в декомпе 0x52b550-0x52b8b5), не текущий stand-in. Критерий: маска-гейн после conv +совпадает по форме с реальным ref (сглаживание нотча, двусторонний хвост). + +### Шаг 5 — Bit-exact DSP-FFT 0x140a70 (multi-week, P3) +Заменить `dsp/fft.cpp` (std::cos radix-2) на точный split-radix 2/4/8 по плану из +NOTES_LEVEL:1107-1116: +- twiddle: `DAT_182616800` sin-таблица, `sin(k·2π/1024)`, loader `FUN_180039b00` (stride 2^(10-m)) +- butterfly: `FUN_18000bfc0/18000c5e0` + 0x8440 elementwise mul + `FUN_1800437c0` acc +- plan-gen: `FUN_18002f980` (рекурсия + per-log2 фактор-таблицы) +Это НЕ блокирует Шаги 1-4 (bridge/структурная цепь рендерят и с численным FFT), нужен +только для побайтовой парности FFT-conv-пути. + +### Шаг 6 — Внутренняя геометрия 48000/4096 vs 44100/2048 +Внутренний DSP SR=48000/N=4096 (freqaxis spacing 11.713 Hz). Хост рендера 44100/2048. +F4-тест показал, что простая resample_poly НЕ закрывает (даже хуже). Нужно: детектор +гнать на 48000/4096 (IIR-таблицы индексированы 0..2048 = N/2+1 при N=4096), затем +свести к 44100. Ожидается закрытие хвостов t1k_b1f/al (+2.2/−1.6) — именно уровневой +зависимости. Критерий: корректное выравнивание бина и окна между двумя сетками. + +### Шаг 7 — BandConfig A/B/γ (level-path ctx+0x188) live-захват под конкретные конфиги +Структурная LUT-кривая `FUN_180563a60` (A/B/γ). Снято для render_long (A=−24/B=28/γ=1) +и t1kq (то же), но для остальных тестов не захвачено. Метод автоматизирован +(NOTES_CAPTURE.md). Захватить для t1k_b1f / al / dual-конфигов → реальные A/B/γ → это +закрывает уровневую зависимость, которую bridge-LUT не может (F1 closure). Критерий: +mean кап-нагрузки al/t1k ≤ 0.3 dB. + +### Шаг 8 — Стерео M8 + полный pipeline (P4/P5) +Финальный рендер stereo (link/balance/LR-vs-MS) по M8 и multiband combine 0x5316e0. +Все текущие рендеры mono. Для bit-exact графа нужны стерео-рендеры как мишены. +Критерий: `verify_bit_exact.py` — побайтовое совпадение данных-чанка WAV. + +--- + +## 2. Что НЕ делать (подводные камни из дока) + +- **НЕ вводить эмпирию там, где есть декомп.** Каждый параметр — из декомп-адреса или + live-таблицы, иначе пометить EMPIRICAL и в «осталось» (золотое правило AGENTS). +- **НЕ делать combine в bridge-final-gain домене** — F2 показал регресс 4.68/5.22. + Combine/exp2 живут в reduction/exp2-домене реальной цепочки. +- **НЕ менять Pchip-LUT в bridge** — регрессирует весь корпус (F1, параметрич. хуже). + Bridge — только запасной вариант, пока структурная цепочка не пройдёт Шаг 1-2. +- **НЕ использовать битые 24-bit загрузчики** — метрика `render_parity.py:43` правильная + (x>=0x800000 => x−0x1000000). В тестовых скриптах использовать тот же код. + +## 3. Риски и время + +- **Доминирующий риск**: дорогой структурный перенос (Шаг 1-2) может снова регрессировать + ниже bridge, как Phase B. Митигация: валидировать каждый под-шаг (IIR1 отдельно, blend + отдельно) на t1kq, не коммитить пока не ≥ bridge. +- **DSP-FFT (Шаг 5)** — multi-week само по себе. Но НЕ блокирует Шаги 1-4. +- **Стерео (Шаг 8)** — новая мишень-корпус, больше рендеров. +- **Оценка**: Шаги 1-4 (монопуть) — 1-2 недели. Шаг 5 — до 3 недель. Шаги 6-8 — 1-2 недели. + До полной байтовой парности — ориентировочно 1-2 месяца с аккуратным монофокусом. + +## 4. Точка входа для следующей сессии + +1. Прочитать `AGENTS.md`, этот `BITEXACT_PLAN.md`, `handoff/NOTES_LEVEL.md:820-840` + (точная цепочка) и `dsp/rt_mask_tables.hpp` / `dsp/rt_weights.hpp` (live-таблицы). +2. Собрать: `cd dsp && cmake --build build --target framed_test`. +3. Бейзлайн: `TAG=base python3 /tmp/full_corpus.py` (62 случая, см. таблицу §0). +4. Шаг 1: вынести структурную цепочку в `dsp/fn529fe0.cpp`, валидировать IIR1-шаг на t1kq. diff --git a/README.md b/README.md index 491d83d..4097c7d 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,7 @@ re-tools/ | Документ | Содержание | |---|---| | [AGENTS.md](AGENTS.md) | **Старт для агента**: сборка, метрика, bit-exact пробелы, структура | +| [BITEXACT_PLAN.md](BITEXACT_PLAN.md) | **Путь к bit-exact**: порядок работ (8 шагов), критерии, риски, точка входа | | [roadmap.md](roadmap.md) | Журнал всех результатов/гипотез (B.1…B.15, P4), статус по фазам, риски | | [handoff/SESSION_HANDOFF.md](handoff/SESSION_HANDOFF.md) | Инвентарь декомпа (§0), трансляция/ключевые адреса (§2), Phase-5 план (§6) | | [handoff/NOTES_LEVEL.md](handoff/NOTES_LEVEL.md) | **Level-path/mask-цепь, live-таблицы, bit-exact протокол** (самый актуальный) | diff --git a/roadmap.md b/roadmap.md index 0750bd1..8e185f1 100644 --- a/roadmap.md +++ b/roadmap.md @@ -12,6 +12,12 @@ ## Текущий статус (2026-08-20, P4) +> **2026-08-21: bit-exact НЕ достигнут** — честная dB-параллель (корпус mean 1.594 dB, +> comb 10 dB). Активный канон — bridge (эмпирическая погона). Путь к байтам — в +> `BITEXACT_PLAN.md` (8 шагов: структурная цепочка → combine/acc → bit-exact exp2/FFT → +> геометрия 48000/4096 → A/B/γ → стерео). См. также итог comb-экспериментов в +> `handoff/NOTES_LEVEL.md`. + - **Статический декомп DSP-ядра — закрыт (~95%)**: twin-резонатор, генератор case8, level-path (0x529fe0/0x563440/0x563a60), mask-apply (FUN_180529fe0 mono-path), IIR-трекеры, FFT-conv (0x535a70), main render-loop (FUN_18052e260) декодированы; `.dis` в `handoff/nls_dasm/`.