618 lines
42 KiB
Markdown
618 lines
42 KiB
Markdown
# BLOCK MAP: FUN_180529fe0 (полная разметка по raw asm, 22v)
|
||
|
||
Источник: `handoff/nls_dasm/f529fe0_full.dis` (soothe_mem.bin, база 0x180000000,
|
||
диапазон 529c60–52ba00; старый f529fe0.dis был ОБРЕЗАН на 52a813).
|
||
Регистры: r13 = индекс полосы, r12 = state-ptr ctx+0x440518, esi/r8d = nbin,
|
||
rbx = nbands ([rsp+0x30]), rdi = ctx. Флаг 0x5408b8 выбирает float/double
|
||
вариант thunk-операций (семантика пар идентична).
|
||
|
||
## Исправление адресации (главное)
|
||
«Скалярные» буферы NOTES 21b — МАССИВЫ пер-полосных векторов (шаг 16 байт):
|
||
- bands[i] = [ctx+0x540678+i·16] — кривые полос
|
||
- acc[i] = [ctx+0x5407c8+i·16] — ПЕР-ПОЛОСНЫЙ аккумулятор combine
|
||
- track[i] = [ctx+0x540768+i·16] — трек основного цикла
|
||
|
||
## Thunk-таблица (ILT-стаб 180001xxx -> jmp [table + idx*8], idx @1826159a0)
|
||
Резолв при live idx=4; семантика из тел + NOTES 21b:
|
||
| стаб float | стаб double | impl | op |
|
||
|---|---|---|---|
|
||
| 0x180001f10 | 0x180001c70 | dc40 / **8d60** | dst = B − A (sub) |
|
||
| 0x180001fa0 | 0x180001940 | ee20→487a0 / **3c40** | fma att/rel половин |
|
||
| 0x180001d60 | —(встречен в 1b80-паре?) | — / **5a20** | dst += B (add) |
|
||
| 0x180001970 | — | **3f40** | sub (float) |
|
||
| 0x1800019a0 | — | **4200** | mul scalar? (делегирует 181a63fe0) |
|
||
| 0x180001a00 | — | **4720** | mul |
|
||
| 0x180001a60 | — | **5160** | sub DOUBLE |
|
||
| 0x180001850 | — | **25e0** | add DOUBLE |
|
||
| 0x180002000 | 0x180001c40 | ? | axpy-класс (band ⊕ track) |
|
||
| 0x180002060 | 0x180002120 | 10860/11940 | transform со скаляром xmm3 |
|
||
| 0x180002270 | 0x1800022a0 | 14c40/15060 | transform со скаляром xmm0/xmm1 |
|
||
| 0x180002030 | 0x180001d30 | ? | transform float/double |
|
||
| in-place кернелы | | 140950/140980/1409b0/1409e0/140a40/140ad0/140b00/140b60 | bigkernel-семейство (exp2/mask) |
|
||
|
||
## Карта блоков
|
||
|
||
### Пролог
|
||
- `52a03a–52a396`: PRNG-пролог. LCG state @ctx+0x2404e0, шаги +0x3cdca,
|
||
+0x140236, +0x10d56, +0xdf6b6, +0xa8c5e, +0x72916; LUT ptr @ctx+0x5408b0;
|
||
константы 262b704/262b5c8(int)/262b700(int)/24c3c58. Результат: индексы
|
||
iVar7/iVar8 ([rsp+0x130]/счётчики) и стартовая позиция цикла.
|
||
Live-поведение залочено раньше (fVar30=1).
|
||
- `52a397`: r14 = &bands[0].
|
||
|
||
### Pre-combine #1 (52a397–52a421)
|
||
- `52dbc0(f6f8_data, bands[0], nbin)` — copy bands[0] → f6f8.
|
||
- цикл i=1..nbands−1 по массиву @0x540688 (= &bands[1]!): transform(f6f8, bands[i])
|
||
через 20f0(float)/1850(double=25e0 ADD). ⇒ **f6f8 = Σ_{i≥1} bands[i]** (или min/max
|
||
— точный op 20f0 не залочен, кандидат ADD по double-паре!).
|
||
|
||
### Нормировка + mix-вес (52a421–52a458)
|
||
- `52d920(f6f8, xmm11/[rsp+0x148](int), nbin)` — f6f8 /= K.
|
||
- `xmm7 = powf([ctx+0x2c], xmm13)` — mix^p.
|
||
|
||
### Pre-combine #2 (52a45e–52a4f6) по всем полосам
|
||
- band[i] *= (xmm11 − xmm7) [thunk 2030/1d30]
|
||
- f6f8 ⊕= ... с весом xmm7 [thunk 1fd0/2150]
|
||
⇒ взвешенное смешение кривых полос ДО основного цикла.
|
||
|
||
### Основной цикл по полосам (52a4fb..52b3c7, тело с 52a580)
|
||
На каждую полосу i (r13):
|
||
1. `scale` (52a583–52a5c4): s = xmm11·[0x540870]; если флаг 0x5408b8:
|
||
s ← exp(PRNG)-ветка; затем ·[0x54088c]. Читается track_i (@0x540768[i]) в [rsp+0x40].
|
||
2. `transform(bands[i], s)` (52a5cc–52a607): bands[i] *= s [2030/1d30].
|
||
3. флаг-оп (52a608–52a645): transform(bands[i], bands[i]) через 140980/1409b0
|
||
(bigkernel, вероятно exp2-кернел) — только при флаге.
|
||
4. `52d650(state@0x440518, f6f8, bands[i], nbin)` (52a646–52a658) — БИДИР-IIR #1:
|
||
band → f6f8 (double, коэф down@0x440528/up@0x4c0528, acc@0x540528, reset внутри).
|
||
5. Инлайн БИДИР-IIR #2 (52a65d–52a85a, только при флаге; иначе прыжок на 6):
|
||
вход f6f8 → выход bands[i] (тот же state 0x440518, reset отдельно).
|
||
6. `transform(f6f8 ⊕ bands[i])` (52a85b–52a896) [1970/1a60 = 3f40 SUB float /
|
||
5160 SUB double]: f6f8 −= bands[i]? (аргументы rcx=f6f8, rdx=band).
|
||
7. **БИДИР-IIR #3** (52a897–52aa6e, инлайн): state base 0x3404f8
|
||
(down@0x2404f8, up@0x2c04f8, acc@0x3404f8), длина из поля ctx+0x2404e8,
|
||
IN-PLACE по bands[i]. Reset каждый вызов.
|
||
8. `op(bands[i], скаляр xmm9=0?)` (52aa6e–52aaaf) [2060/2120].
|
||
9. Ветка флага==0 (52aabc–52ab90):
|
||
- op(vec@0x540698, f6f8, scalar=(конст1 − [0x54087c])) [1a00/1be0 = mul]
|
||
- op(f6f8, scalar=[0x54087c]·xmm10) [2270/22a0]
|
||
- bigkernel `140b60/140950(bands[i], f6f8, bands[i], nbin)`
|
||
10. **COMBINE (52ab90–52abd7)**: acc_i = [0x5407c8+i·16];
|
||
`op(rcx=acc_i, rdx=bands[i], r8=f6f8, r9=nbin)` [1f10→dc40 float-SUB /
|
||
1c70→8d60 double-SUB]: **f6f8 = bands[i] − acc_i** ✓ NOTES 21b.
|
||
11. Половины f6f8 + fma (52abd7–52ad04):
|
||
- rbp = f6f8 + nbin (верхняя половина); op(f6f8_low?, ...) [2060/2120, scalar 0]
|
||
- op(rcx=f6f8_upper, rdx=vec@0x5406c8, r8=acc_i) [1fa0/1940 = **3c40 fma**]
|
||
- op(rcx=f6f8_lower, rdx=vec@0x5406e8, r8=acc_i) [1fa0/1940]
|
||
⇒ fma с коэф-массивами 0x5406c8 (upper/att) и 0x5406e8 (lower/rel) ✓.
|
||
12. `acc_i += bands[i]` (52acf4–52ad03) [1b80→6840 / 1d60→**5a20** add] ✓.
|
||
13. Ветка флага!=0 (52ad04–52ae57): повтор п.9 с теми же адресами
|
||
(0x540698, f6f8-blend, bigkernel 1409e0/140ad0).
|
||
14. `op(bands[i], скаляры 0x1824c4680 / xmm13)` (52ae58–52ae56 хвост).
|
||
15. `bands[i] ⊕= track_i [rsp+0x40]` (52ae74–52ae8a) [2000/1c40].
|
||
16. `op(vec@0x5406a8, bands[i])` (52ae8f–52aecа) [2000/1c40].
|
||
17. флаг → bigkernel in-place 140980/1409b0 (52aecb–52af08).
|
||
18. **БИДИР-IIR #4 ×2** (52af09–52b2af и повтор 52b0de–52b2af):
|
||
state base 0x440510 (down@0x340510, up@0x3c0510, acc@0x440510),
|
||
длина ctx+0x340500, in-place bands[i]. ДВА прохода подряд (каждый с reset).
|
||
19. Финальные scale/op полосы (52b2af–52b3af):
|
||
- скаляр `[ctx+0x1c+i·4] · xmm14` → transform [2030/1d30]
|
||
- bigkernel in-place 1409e0/140ad0 (при флаге) ИЛИ
|
||
op(scalar=xmm12/xmm8) [2270/22a0] + `140a40/140b00(band,band,scalar)`
|
||
20. Инкремент i (52b3af–52b3c7), выход при i ≥ nbands.
|
||
|
||
### Эпилог (52b3cd–52b935)
|
||
- GUI-snapshot блок (флаг 0x2404bc): копии векторов @0x540728 ← bands[i]
|
||
(совпадает с consumers_out.txt:144-183).
|
||
- Остаток до 52b935: восстановить при транскрипции (вероятно dry/wet + mirror).
|
||
|
||
## Состояния бидир-IIR (4 базы, лейаут {down,+0x80000 up,+0x80010/+0x100010 acc})
|
||
| # | база | downCoef | upCoef | acc | длина |
|
||
|---|------|----------|--------|-----|-------|
|
||
| 1–2 (52d650+инлайн) | 0x440518 | +0x10 | +0x80010 | +0x100010 | nbin |
|
||
| 3 | 0x2c04f8-группа | 0x2404f8 | 0x2c04f8 | 0x3404f8 | поле ctx+0x2404e8 |
|
||
| 4 ×2 | 0x340510/0x3c0510 | 0x340510 | 0x3c0510 | 0x440510 | поле ctx+0x340500 |
|
||
|
||
## Открытые вопросы к транскрипции
|
||
1. Точный op thunk 20f0/1850 в pre-combine #1 (ADD — кандидат).
|
||
2. Аргументный порядок 2000/1c40 (axpy) и 2060/2120.
|
||
3. Семантика bigkernel-семейства 1409xx/140axx/140bxx (какой где: exp2(-x),
|
||
exp2(-x)·blend, mirror?).
|
||
4. Что пишется в track_i @0x540768[i] (writer вне метода — искать отдельной охотой;
|
||
кандидат FUN_18052e9b0).
|
||
5. Эпилог 52b4eb–52b935.
|
||
|
||
## ДОПОЛНЕНИЕ 22v: декод генератора коэффициентов
|
||
|
||
### FUN_180530b60 (апдейт параметров, size=462)
|
||
- fVar2 = powf([ctx+0x540878], K1); fVar3 = powf([ctx+0x54087c], K2)
|
||
(оба live = 0.5 — параметры attack/release-класса);
|
||
- лог-интерполяция констант → [ctx+0x540894] и [ctx+0x540898] (тау-скаляры);
|
||
- вызовы генератора на все три состояния:
|
||
- 180533340(ctx+0x2404e8, tau=0x540894-ветка, C=DAT_1824c459c, sr, ...)
|
||
- 180533340(ctx+0x340500, tau=[0x540894], ...)
|
||
- 180533340(ctx+0x440518, tau=[0x540898], ..., mult=DAT_1824c4564)
|
||
|
||
### FUN_180533340(state, tau, C, sr, p, mult) — ГЕНЕРАТОР КОЭФ. БИДИР-IIR
|
||
```
|
||
sr' = sr · DAT_1824c3d8c
|
||
acc = 0; downCoef[0] = 1.0 (int-пара {0, 0x3ff00000} @+0x10)
|
||
n = state[0]; fc_norm = (C/sr')·n
|
||
for i in 1..n-1:
|
||
g = (i <= fc_norm) ? fc_norm/i : powf(fc_norm/i, p) # частотный варп!
|
||
c = 1/(g·tau/mult + 1)
|
||
up[i] = exp(c·g·tau/state[2] · DAT_1824c46b8)
|
||
down[i] = 1 − up[i]
|
||
```
|
||
ЛЕЙАУТ СОСТОЯНИЯ СОШЁССЯ: downCoef[] @base+0x10, upCoef[] @base+0x80010
|
||
(pdVar6[0x10000] = +0x80000 байт), acc — скаляр в хвосте. Это ЧАСТОТНО-
|
||
ЗАВИСИМОЕ сглаживание маски: сила растёт к низким бинам (1/i) с питч-законом
|
||
выше кросса. Вот где «размазывание» нотча в реале — НЕ плоский IIR, который
|
||
мы отвергли офлайн (22u), а пер-биновый варп!
|
||
|
||
### Статус сбора (решение: без коммитов до первой валидации)
|
||
Незакоммичено: f529fe0_full.dis, BLOCKMAP_529fe0.md, thunk-резолвер,
|
||
правки NOTES_LEVEL (22v будет добавлена при транскрипции). Следующий шаг —
|
||
транскрипция process_frame_faithful по этой карте.
|
||
|
||
## ДОПОЛНЕНИЕ 23b: резолв ILT + декод FIR-цикла (52b550–52b8bb)
|
||
|
||
### Резолвер
|
||
`scripts/ilt_resolve.py`: стаб = `mov eax,[rip+idx]; lea r10,[rip+tbl]; jmp [r10+rax*8]`;
|
||
live idx=4 у всех; таблицы @0x1826xxxx. Полная таблица «стаб→impl»:
|
||
| стаб | impl | роль (уточн.) |
|
||
|---|---|---|
|
||
| 0x180002210 | 0x136e0 | copy scratch→FIR? (валидатор → 39de0/3a040/3a220) |
|
||
| 0x180002180 | 0x125e0 | complex-op A/C float (воркер 3a4a0; r9 НЕ передаётся ⇒ длина из объекта) |
|
||
| 0x180001bb0 | 0x6a40 | complex-op A/C double |
|
||
| 0x180001a90 | 0x5560 | complex-op B/D float — ЧИСТЫЙ FMA (fma=28, mul/add=0!) |
|
||
| 0x1800019d0 | 0x4340 | complex-op B/D double |
|
||
| 0x180001880 | 0x2c60 | paired-scalar op 1 (флаг-ветка) |
|
||
| 0x180001ca0 | 0x9380 | paired-scalar op 2 |
|
||
| 0x180001df0 | 0xb3c0 | final op float |
|
||
| 0x180001f70 | 0xe360 | final op double |
|
||
| 0x180140a10 | 0x141400→[1826181d8]=**0x1802a24c0** | дизайн float |
|
||
| 0x180140a70 | 0x141580→[1826183c8]=**0x1802fa420** | дизайн double |
|
||
| 2030/1d30 | ffe0 / 9be0 | scalar-transform |
|
||
| 2270/22a0 | 14c40 / 15060 | scalar-transform-2 |
|
||
| 2000/1c40 | fb60 / 8700 | axpy-класс |
|
||
| остальное | dc40,8d60,5a20,4720,4200,3f40,5160,25e0,ee20,3c40 | как в BLOCKMAP ✓ |
|
||
|
||
### Дизайн-тело 0x1802a24c0 (float, вход=rcx bands[i], выход=rdx scratch@0x540628)
|
||
Функция входа 0..0x675 (~1.6КБ), далее сиблинги. Алгоритм = **ВЕКТОРНЫЙ LOG2**
|
||
(range reduction бит-трюком с 0.6666667, полином Хорнера на YMM-константах
|
||
−0.5, 0.3333656, −0.2500466, 0.198225, −0.1646246, 0.1696488, −0.1517721,
|
||
реконструкция ×ln2=0.6931472; константы @FN+0x1cdfac0..d20). Маскированный
|
||
хвост через vmaskmovps/popcnt-таблицы (@0x181F8xxxx). ИТОГ: **scratch = log(bands[i])**.
|
||
Диспетчер 535a70 делает swap аргументов (rcx↔rdx) перед прыжком!
|
||
|
||
### Структура FIR-цикла (полностью залочена)
|
||
На полосу: 2×scalar-transform(bands[i], xmm8·[540888] при флаге 540890==0, иначе
|
||
xmm8; затем xmm12−xmm8) [ср. decomp 184-185: A=[0x540874]−expf(K), wet=[0x540888]]
|
||
→ DESIGN=log(bands[i])→scratch → copy(scratch→FIR@0x540668) [2210]
|
||
→ opA(FIR,buf548,buf598) [2180/1bb0] → FIR[n]=0 (n=0x540534=4096!)
|
||
→ 52d920(&FIR[1], xmm13, n/2−1) деление; 52db50(&FIR[2049], xmm9, n/2−1)
|
||
→ opB [1a90/19d0] → bigkernel in-place 140b30/140aa0 (n/2+1)
|
||
→ opC [2180/1bb0] → FIR[n]=0 → 52d990(FIR, WIN_freq+n/2, n/2) УМНОЖЕНИЕ на
|
||
**падающую половину Hann** (WIN_freq=wperiodicHann4096: w[1024]=0.5,w[2048]=1.0!)
|
||
→ 52db50(&FIR[2048], xmm9, n/2) → opD [1a90/19d0] → FIR[0]=1.0, FIR[1]=0
|
||
→ флаг-ветка: парно-скалярные 1880/ca0 → dry/wet scale ×[0x540888] над **2n флоатов**
|
||
→ final(df0/f70) с сохранённым track_i ([rsp+0x138][i]).
|
||
|
||
### Живые буферы (firtrace.py по s1/s2 + свежие захваты dual_b1q_0.5)
|
||
- 0x540658 WIN_freq = периодический Hann(4096), пик 1.0 @bin2048 (НЕ рамп 0.5→0.8!)
|
||
- 0x540758 freqaxis = линейный, шаг ≈11.713 Гц (≈48000/4096=11.71875, лёгкое
|
||
занижение — похоже на накопительную ошибку f32 при построении суммой)
|
||
- 0x540598 = SIMD-маски: 8×1.0 / 8×0.0 периодом 16 флоатов, ровно 1024 шт
|
||
(YMM lane-select для комплексных кернелов)
|
||
- 0x540550 NULL (float-путь активен, флаг 0x5408b8=0); 0x540628 scratch нулевой
|
||
между колбеками; 0x540668 FIR = комплексная единица (1,0)×2049 бинов МЕЖДУ
|
||
колбеками — кернел потребляется и сбрасывается внутри колбека
|
||
- 0x5406f8 хранит аудио-масштабный сигнал (~±0.1) между колбеками — overlap/STFT
|
||
буфер conv-движка (не «нулевой acc»!)
|
||
- 0x540788 vs 0x5407f8 различаются (max 1.108; @171: 1.751 vs 1.409) — две РАЗНЫЕ
|
||
кривые; ни одна не достигает нужных 3.89×@171 (11.82 дБ) ⇒ применённый фильтр
|
||
≠ поточечная копия любой из живых кривых (подтверждение разрыва 22y)
|
||
|
||
## ДОПОЛНЕНИЕ 24l: точный декод FIR-цикла по дизасму (52b550–52b8bb) + константы
|
||
|
||
Инструмент: scripts/disasm.py (capstone, base 0x180000000 над soothe_mem.bin).
|
||
ILT-резолв bigkernel-стабов даёт impl в 141100..141940 — все они IAT-thunk
|
||
массивы (`mov rax,[rip+..]; jmp rax`) вне дампа ⇒ тела за импортами; НО
|
||
последовательность и КОНСТАНТЫ цикла видны полностью:
|
||
|
||
### Пошагово (float-ветка, флаг 0x540890==0):
|
||
```
|
||
52b5a3: xmm6 = xmm8 · [ctx+0x540888]
|
||
52b5bf: th2030(bands[i], xmm6, n) ; bands *= 1.0·s888 (xmm8=double 1.0!)
|
||
52b5f6: th2270(bands[i], xmm7, n) ; scalar-transform-2
|
||
52b62f: 535a70(scratch@540628, bands[i], n/2+1) ; DESIGN: swap→scratch=log(bands)
|
||
52b644: th2210(rcx=scratch, rdx=0, r8=FIR, r9=n/2+1) ; копия (+упаковка?)
|
||
52b696: FIR[n]=0 ; float-индекс n=4096
|
||
52b69e: 52d920(&FIR[1], xmm13=-1.0, n/2-1) ; РАЗДЕЛЕНИЕ НА −1 ⇒ ИНВЕРСИЯ ЗНАКА бинов 1..n/2!
|
||
52b6ab: 52db50(&FIR[n/2+1], xmm9=0, n/2-1) ; ОБНУЛЕНИЕ верхней половины до exp!
|
||
52b6e1: opB = th1a90(FIR, buf548, mask598, n/2-1) ; FMA-complex (twiddle!)
|
||
52b716: BIGKERNEL 140b30(FIR, FIR, n/2+1) ; EXP in-place (тело за IAT)
|
||
52b74b: opC = th2180(FIR, buf548, mask598, n/2-1)
|
||
52b76d: FIR[n]=0
|
||
52b77c: 52d990(FIR, WINfreq+n/2, n/2) ; окно: th2000-класс (FMA axpy!)
|
||
52b78c: 52db50(&FIR[n/2], xmm9=0, n/2) ; верхняя половина ×0 снова
|
||
52b7ba: opD = th1a90(...)
|
||
52b7d4: FIR[0]=1.0f; FIR[1]=0
|
||
если флаг f890!=0:
|
||
52b803: th1880(FIR, {xmm10,xmm9}, n) ; парно-скалярный с (−1|0.8, 0)
|
||
52b81f: th1ca0(FIR, {xmm12,xmm9}, n) ; парно-скалярный с (1.0, 0)
|
||
52b857: th2030(FIR, s888, 2n) ; ×wet (=1 live)
|
||
52b893: final df0(FIR, track_i, n)
|
||
```
|
||
|
||
### Константы (статические значения из дампа):
|
||
| reg | адрес | значение | роль |
|
||
|-----|-------|----------|------|
|
||
| xmm8 | 1824c4140 (double) | 1.0 | множитель шага 1 = NO-OP при s888=1 |
|
||
| xmm13 | 1824c46a0 (double) | −1.0 | делитель бинов 1..n/2 (ИНВЕРСИЯ!) |
|
||
| xmm9 | xorps | 0.0 | обнуление верхних половин |
|
||
| xmm10 | 1824c4680 / 1824c3e28 | −1.0 / **0.8** | парный скаляр (0.8 активен в цикле) |
|
||
| xmm12 | 1824c3ea4 | 1.0 | парный скаляр 2 |
|
||
| xmm14 | 1824c4674 | −0.7 | (использование вне FIR) |
|
||
| xmm15 | 1824c4670 | −0.5 | (использование вне FIR) |
|
||
| xmm7 | вычисл. | sens·[540870]-цепочка | аргумент th2270 |
|
||
|
||
### СЛЕДСТВИЯ (меняют понимание построения кернела):
|
||
1. Перед EXP: бины 1..n/2 = −log(bands) ⇒ после exp = **1/bands** (обратная
|
||
величина!), бины выше = exp(0)=1. Экспонента применяется НЕ к спектру маски
|
||
напрямую — вокруг неё twiddle-FMA стадии (ops B/C/D = радиальные проходы
|
||
FFT-класса над упакованным вещественным спектром; buf548 = cos/sin таблица,
|
||
mask598 = lane-select).
|
||
2. «×0.984» из 23d НЕ найден как константа цикла — либо внутри exp-IAT-обёртки,
|
||
либо следствие нормировки twiddle-стадий. Требуется численная репликация
|
||
пайплайна против живых захватов (rendersnap2 ph*.npz содержат готовые пары).
|
||
3. Шаг 1 и шаг ×s888 — no-op при дефолтных параметрах (s888=1, live 24j).
|
||
4. 52d920/52d990/52db50 = тонкие обёртки: 920→th2030/1d30 (scalar-op),
|
||
990→th2000/1c40 (axpy!), db50→то же. «УМНОЖЕНИЕ на окно» реализовано
|
||
axpy-кернелом, «деление» — scalar-op.
|
||
5. Ops A–D работают над дескрипторными векторами (проверка тега [obj]==6 в
|
||
4ca80; ошибка 0xfffffff3 при несоответствии).
|
||
|
||
### Динамика (попытки перехвата; окружение)
|
||
- realtime-playback НЕ тикает DSP (нет аудио-девайса; треды спят в futex);
|
||
кривые 22y = результат инициализации при загрузке проекта
|
||
- `-renderproject`: полный цикл init+render+exit хоста занимает ~0.8 c
|
||
(host@1.2s, workers@1.4s, wav@1.6s, exit@2.0s); обработка идёт в окне ~0.5 c
|
||
- INT3-ptrace: SEIZE+TRACECLONE обязательны до CONT (иначе untraced thread
|
||
ловит SIGTRAP и убивает процесс — подтверждено); DR-брейкпоинты: DR0@user+0x380,
|
||
но POKEUSER DR7 даёт EIO. Скрипты: fntrace*.py, fnhw.py, fnall.py, firstop.py,
|
||
firtrace.py, hotips.py (см. scripts/)
|
||
- Вывод: FUN_180529fe0 и 52d650/536300/52e260 НЕ ловятся в рендер-окне —
|
||
маск-цепь выполняется при ЗАГРУЗКЕ/изменении параметров, стационарный рендер
|
||
использует закэшированный кернел; либо трассировать надо момент инициализации
|
||
- Выход плагина НЕдетерминирован: md5 двух свободных рендеров различен при
|
||
одинаковом rms (PRNG-дизеринг из LCG-прологов) — метрика только спектральная!
|
||
|
||
## ДОПОЛНЕНИЕ 24t: ТОЧНЫЕ СЕМАНТИКИ СКАЛЯР-ОПОВ + опознание 563a60
|
||
|
||
Инструмент: scripts/disasm_func.py (полный дизасм функции с резолвом
|
||
RIP-констант инлайн).
|
||
|
||
### Тела скаляр-трансформов (float-ветки):
|
||
| стаб/impl | семантика | спец-случаи |
|
||
|---|---|---|
|
||
| th2030→ffe0 | dst[i] *= scalar | scalar==1 → скип; ==0 → zero-fill |
|
||
| th2270→14c40 | dst[i] += scalar | scalar==0 → скип |
|
||
Оба: скалярный хвост + AVX2 основной цикл (vmulps/vaddps ymm). Двойные
|
||
ветки (1d30/22a0) аналогичны на sd/pd.
|
||
|
||
### FUN_180563a60 = init-time ПОСТРОИТЕЛЬ таблицы (не per-bin!)
|
||
- Один caller: 1805636c2 (init-семейство).
|
||
- Константы пролога: xmm11=8.68589 (20/ln10 — ln⇒дБ!), xmm12=1/1024,
|
||
xmm14=0.5, xmm10=2, xmm9=−1, xmm6=1; вызов IAT 181a14cd0 (log-класс)
|
||
над double из [obj+0x4198], ×8.68589 → дБ, запись пар во вектор
|
||
([obj+0xe0], рост через realloc 56c640).
|
||
- Вывод: строит дБ-доменную таблицу парами при param-rebuild — согласуется
|
||
с «LUT» ролью. Хвост с вирт. вызовом [rax+0x10] не декодирован.
|
||
|
||
### Алгебра T1: обе формы фитуют серию драйва (8 точек недоопределены)
|
||
- softplus α·ln1p(L/β)+c: rms 0.016 (α=3.2193 β=0.4927 c=0.542)
|
||
- LUT-форма t=((dB−A)/(B−A))^γ·M: rms 0.029 (A=−36.2 B=20.0 γ=2.097 M=10.49)
|
||
Различить только декомпом тракта am/res→scratch или бОльшим числом точек.
|
||
|
||
### Открытые микровопросы
|
||
1. Значение xmm7 на входе th2270 в FIR-цикле (52b5f6): трассировка от
|
||
52a583; если mix^p=1 → «bands+=1» противоречит провалам ⇒ xmm7 иной
|
||
либо порядок аргументов иной.
|
||
2. Раскладка объекта-вектора (тег 6) для ops A–D.
|
||
|
||
## ДОПОЛНЕНИЕ 24u: WIN_WINDOW движка — кусочное окно аудио-пути
|
||
|
||
Таблица WIN_WINDOW[8193] (dsp/tables_data.hpp, live-захват):
|
||
- [0]=0.500000, плавный подъём до [2048]=0.800000, затем СКАЧОК до 1.0
|
||
и единица до конца ([2049..8192]).
|
||
- Длина перехода = РОВНО 2049 сэмплов = число бинов кернела (4096-сетка)!
|
||
- Формула перехода не каноническая (ханн/синус/степенные не сошлись,
|
||
maxdiff ≥0.09); для репликации достаточно встраивания таблицы как есть.
|
||
- Структура намекает: блок аудио 8192 сэмплов ({16384,8192} из cfg движка),
|
||
первые 2049 позиций получают взвешивание 0.5..0.8 (область «кернельного
|
||
взаимодействия»?), остальное прозрачно; 0.8 подозрительно = blend.
|
||
Проверка употребления — в resize fe00 / audio-клее (следующий раунд).
|
||
|
||
### Движок dc30: карта инициализаторов (24u)
|
||
ctor 18052dc30 вызывает: 5335c0 (×2 — до/после валидатора), 534550 (×5 —
|
||
регистрация конфиг-итемов, аргументы edx из стека [rsp+0x30..0x4c] =
|
||
цепочка {2,4096},{16384,8192},{2,257}), затем ILT-стабы 2240/1c10.
|
||
Следующий шаг декода: тела 534550/5335c0 + употребление WIN_WINDOW
|
||
(по xref на таблицу или указатель из объекта).
|
||
|
||
## ДОПОЛНЕНИЕ 24w-3: ЖИВЫЕ КОНСТАНТЫ ГЕНЕРАТОРА 533340 (параметры частотных IIR)
|
||
|
||
Из scalar-bank (rendersnap2 v4+) на дефолтных параметрах multi:
|
||
```
|
||
p (экспонента) = [ctx+0x54087c] = 1.000000
|
||
tau1 = [ctx+0x540894] = 1200.000122
|
||
tau2 = [ctx+0x540898] = 180.000015
|
||
mult (стадия-3) = DAT_1824c4564 = 360
|
||
C_hz = DAT_1824c459c = 1000
|
||
константы 530b60 : 0.7, 2, 800→(×2)=1600, 1200, 15, 9, 180, 0.01,
|
||
[540898]=180*p+xmm6 (формула видна в дизасме)
|
||
```
|
||
Формула тела подтверждена дизасмом: g=min(fc_norm/i,(fc_norm/i)^p);
|
||
c=1/(1+g*tau/mult); up=exp(...); down=1-up.
|
||
Эксперимент: одноразовый bidir с этими коэф. НЕ двигает центр кривой
|
||
⇒ q-зависимость катов не через эти IIR напрямую; тракт между main-loop
|
||
и scratch содержит ещё этапы (ops A–D / steps 9–19 BLOCKMAP).
|
||
|
||
## ДОПОЛНЕНИЕ 24z: FUN_180563a60 ДЕКОДИРОВАН ПОЛНОСТЬЮ — ЭТО ДЕТЕКТОРНАЯ LUT-ФОРМА!
|
||
|
||
Постройка (на каждый банд, 1024 точки, вход double[+0x4198+i·8],
|
||
выход пары-floats в вектор [+0xe0], stride вектора 0x18):
|
||
```
|
||
dB = log(input) · 8.68589
|
||
idx = i / 1024 → store[2j]
|
||
t = (dB − A) / (B − A) ; A=[sub+0], B=[sub+4] (sub=obj@[rcx+0x180])
|
||
t = clamp(t, 0, 1)
|
||
если γ(=[sub+0xc]) ≠ 1:
|
||
если [sub+0x10]==0: out = t^γ (классика)
|
||
иначе : out = sign(2t−1)·|2t−1|^γ + 1 (симметричный режим!)
|
||
else: out = t
|
||
out *= 0.5 → store[2j+1]
|
||
```
|
||
Виртуальная альтернатива: [sub+0x90]!=0 → вызов [sub vtbl+0x10](A,B,dB)
|
||
с клампом [0,1].
|
||
⇒ ЭТО ТА САМАЯ ФОРМА, ЧТО ДАЛА ФИТ cut=LUT(A,B,γ,M)! Стадия компрессии
|
||
уровня найдена материально: A/B/γ живут в объекте [band+0x180],
|
||
заполняются сеттерами. Осталось: снять их live-значения для наших конфигов
|
||
(расширить scalar-dump на [ctx+0x180]-объект) и найти потребителя таблицы
|
||
(интерполятор dB→out) в аудио-тракте.
|
||
|
||
## ДОПОЛНЕНИЕ 24cc: точная формула коэф. 533340 (дизасм+live)
|
||
[state+8] = n = 2049 (∀ трёх состояний; live probe_states.py).
|
||
```
|
||
fc_norm = (X/(sr·0.5))·n ; X=xmm2 (C_hz=1000 или tau — уточнить)
|
||
g(i) = min(fc_norm/i, (fc_norm/i)^p) ; p=[ctx+0x54087c]=1 @defaults
|
||
c = 1/(1 + g/mult) ; mult=360 (стадия-3)
|
||
arg = |c| · g / n ← НАСЫЩАЮЩАЯ форма (пол g→mult/n)
|
||
up[i] = exp(arg · (−2π)) ; down[i]=1−up[i]
|
||
```
|
||
При дефолтах down ∈ [0.003..0.19] — очень мягкие сглаживатели; эффект
|
||
только каскадом в полной цепочке шагов 9–19.
|
||
Осталось уточнить: роль xmm13 (множитель перед c), знак/конст экспоненты,
|
||
соответствие X=C_hz-vs-tau.
|
||
|
||
## ДОПОЛНЕНИЕ 24ff: семантика шага 11 (fma att/rel) — тройки (re,im,coef)
|
||
|
||
Цепочка вызова: ee20 → 487a0 → 1065c0; воркер получает r10=n/2·12 байт
|
||
⇒ элементы по 12 байт = (dst_re f32, dst_im f32, coef f32).
|
||
Call-site (52ac70–52acd4):
|
||
```
|
||
шаг 11a: fma(rcx=f6f8_upper, rdx=ATT@[5406c8], r8=ACC_i, r9=n/2)
|
||
шаг 11b: fma(rcx=f6f8_lower, rdx=REL@[5406e8], r8=ACC_i, r9=n/2)
|
||
```
|
||
⇒ семантика: f6f8[k] += coef[k]·ACC_i[k] (комплексный axpy с пер-биновым
|
||
скаляром), верхняя половина спектра — с ATTACK коэф., нижняя — с RELEASE.
|
||
ACC_i персистентен между кадрами ⇒ утечный интегратор: стационар
|
||
ACC = input/(1−coef); усиление 1/(1−att): @43=2.57 @85=2.93 @171=3.42.
|
||
Коэф. массивы СТАТИЧНЫ (∀ конфигов бит-в-бит — проверено dual/qmap/sens18).
|
||
Гипотеза: резонансное усиление ACC объясняет k>1 аномалии уровней
|
||
(q2: impl/ours=2.48 ≈ A(85)); точная алгебра подачи ACC в кривую — в
|
||
остатке шагов 13–19.
|
||
|
||
## ДОПОЛНЕНИЕ 24gg: шаг 12 — ЭТО КОПИЯ (исправление BLOCKMAP)
|
||
|
||
th1b80→6840→1a5a0→181a646c0 = ЧИСТЫЙ MEMCPY (vmovdqu без арифметики).
|
||
«acc_i += bands[i]» из старого BLOCKMAP — НЕВЕРНО; реально копия
|
||
(направление/роли rbx/rbp уточнить трассировкой регистров через цикл —
|
||
аргументы на 52acf8: rcx=rbx, rdx=rbp, r8=n; значения rbx/rbp меняются
|
||
через 52ac98 [0x5406e8] и др. — нужен полный dataflow-проход шагов 9–19).
|
||
|
||
Следствие: если acc_i не накапливается сложением, «резонансная» гипотеза
|
||
24ff требует пересмотра — возможно ACC обновляется через fma шага 11
|
||
(ACC входит как источник), а шаг 12 синхронизирует массивы.
|
||
|
||
### Статус декода шагов 9–19 (24ff+24gg)
|
||
- шаг 11: f6f8[k] += att/rel_coef[k]·ACC_i[k] ✓ (тройки re,im,coef)
|
||
- шаг 12: COPY (не add!) ✓ исправлено
|
||
- шаги 13–16: th2270-add ветка с xmm6=xmm12−[54087c]; bigkernel 140950;
|
||
axpy 2000/1c40 с vec@540778 — тела не декодированы
|
||
- полный dataflow-проход = задача следующего раунда (связная, ~сессия)
|
||
|
||
## ДОПОЛНЕНИЕ 24hh: DATAFLOW шагов 9–12 (точный, из дизасма)
|
||
|
||
```
|
||
шаг 9a: vec698 *= (xmm12 − [54087c]) ; th1a00=MUL; при 1−1=0 → ZERO
|
||
шаг 9b: vec6f8 += 0.8 ; xmm10=0.8 ([1824c3e28]); th2270=ADD
|
||
шаг 9c: bigkernel 140b60(vec6f8, bands_curve_i, vec6f8)
|
||
шаг 10: vec6f8 = bands_curve_i − ACC_i ; dc40: out[r8]=rdx−r10 ✓COMBINE
|
||
шаг 11: f6f8_upper += ATT[k]·ACC_i[k] ; тройки re/im/coef
|
||
f6f8_lower += REL[k]·ACC_i[k]
|
||
шаг 12: COPY(...) ; направление уточнить
|
||
```
|
||
Регистры: rbx↔vec698/6f8/acc_i, rbp↔bands_curve/[5406e8], r14=vec6f8.
|
||
Картина: строится КОРРЕКЦИОННАЯ кривая (bands−ACC), модулированная
|
||
att/rel-огибающими ACC — адаптивная петля редукции.
|
||
Остаток прохода: шаги 13–19 + эпилог + связь с FIR-секцией (52b3cd+).
|
||
|
||
## ДОПОЛНЕНИЕ 24ii: семантики шагов 13–16 + ИСПРАВЛЕНИЕ th2000
|
||
|
||
th2000/fb60 (и 1c40/8700) = ПОЭЛЕМЕНТНОЕ УМНОЖЕНИЕ МАССИВОВ
|
||
(dst[k] *= src[k]) — НЕ axpy! Исправляет интерпретации:
|
||
|
||
```
|
||
шаг 13 (флаг≠0): зеркало шага 9 (vec698*=..., vec6f8+=0.8·..., bigkernel)
|
||
шаг 14: bands_curve += (−1.0) ; константа [1824c4680]=−1 через th2270!
|
||
затем bigkernel 1409e0/140ad0 IN-PLACE на bands_curve
|
||
шаг 15: bands_curve *= track_i ; th2000 array-multiply
|
||
шаг 16: bands_curve *= kWarp@[5406a8] ; th2000 array-multiply
|
||
шаг 17(флаг): bigkernel in-place ещё раз
|
||
```
|
||
Картинка: кривая центрируется (−1), проходит нелинейность (bigkernel,
|
||
вероятно exp/abs — тела за IAT), модулируется track и warp.
|
||
Против log-входа design'а значение после этих шагов должно быть >0.
|
||
|
||
### Bigkernel-тела за ВЛОЖЕННЫМ диспатчем
|
||
Таблицы стабов содержат смесь IAT-слотов и внутренних адресов (напр.
|
||
table[7]=140a00), но внутренние ведут к call runtime-helper + НОВЫЙ
|
||
ILT-стаб с собственной idx-ячейкой (паковка/протектор). Статическое
|
||
разворачивание обрывается. Тела bigkernel'ов (exp/abs-нелинейность шага
|
||
14/17) остаются за пакером — при необходимости снимаются дампом памяти
|
||
ВОКРУГ вызова в рантайме (STOP + чтение таблиц после инициализации).
|
||
|
||
## ДОПОЛНЕНИЕ 24jj: ТЕЛА BIGKERNEL'ОВ НАЙДЕНЫ (рантайм-резолв IAT)
|
||
|
||
iat_name.py v2 (SIGSTOP + двойной deref + PE-экспорты) резолвит:
|
||
```
|
||
стаб 140b30/140b60 → runtime 1803a06a0 (общий для float/double!)
|
||
стаб 1409e0 → runtime 180296c80
|
||
стаб 140ad0 → runtime 180323f20
|
||
стаб 140a40 → runtime 1802dc0e0
|
||
```
|
||
Все — НАСТОЯЩИЕ функции внутри дампа (не импорты!): большие стек-фреймы,
|
||
x87 FNU-контроль, AVX2 полиномы, ДВЕ x87-трансцендентные инструкции
|
||
(fyl2x/f2xm1 класс = 2^x/exp семейство). Полный декод математики каждого —
|
||
отдельная сессия; вход/выход уже известны из контекста вызовов
|
||
(in-place над n/2+1 элементами FIR-буфера).
|
||
|
||
## ДОПОЛНЕНИЕ 24jj2: R@540788 — БАНДПАС-ФОРМА, НЕ совпадающая с нашим twin!
|
||
|
||
Сравнение (multi6, band1=500/q0.5/s12):
|
||
```
|
||
бин R@540788 наш_res R/наш
|
||
43 0.802 0.117 6.84
|
||
85 1.086 0.374 2.91
|
||
171 1.517 0.839 1.81
|
||
342 3.521 1.401 2.51 ← ПИК ~3.5-4 кГц!
|
||
512 2.910 1.673 1.74
|
||
684 1.829 1.811 1.01
|
||
1024 1.146 1.931 0.59
|
||
1536 0.689 1.988 0.35
|
||
```
|
||
Наш twin res растёт монотонно от fc; R@788 — БАНДПАС с пиком ~bin300-342
|
||
(~3.5-4 кГц) и СПАДОМ к Найквисту. Форма напоминает кривую равной
|
||
громкости / слухового взвешивания!
|
||
R@5407f8 = единичная нормировка (все 1.0000 в этом прогоне).
|
||
|
||
### ГИПОТЕЗА (проверяемая):
|
||
Детекторный уровень = am · ВЕС(f) / res(f), где ВЕС — кривая типа
|
||
равной громкости (R@788?). Тест: X=am·R/res против катов multi6 —
|
||
НЕ сошлось лобово (X@43=1.44 макс при мин кате) ⇒ взвешивание входит
|
||
иначе (до/после res-деления, или в log-домене).
|
||
### Ценность
|
||
Объясняет ВСЕ аномалии дальних бинов разом: наши дальние res слишком
|
||
велики (нет спада), их lvl занижен, каты недобираются. Формула ВЕСА —
|
||
ключ к кросс-конфиг параметризации.
|
||
|
||
## ДОПОЛНЕНИЕ 24kk3: слот [ctx+0x540668] ПОЛИМОРФНЫЙ!
|
||
|
||
Прямой проб во время рендера: [ctx+0x540668] содержит
|
||
`3fdbcd8940000000` = ДВА FLOAT (~0.434, 2.0), НЕ указатель!
|
||
(пробник probe_668.py; EIO на части чтений — слот мигрирует).
|
||
|
||
### Следствия:
|
||
1. rendersnap2 пропускает слот 668 (ptr<0x10000 или мусорный ptr) ⇒
|
||
во ВСЕХ новых захватах (sc_multi4b, sc_tt*, sc_q*, ...) НЕТ FIR-массивов.
|
||
2. Старые захваты rendersnap.py v1 ИМЕЛИ валидный FIR-указатель в эти
|
||
моменты (ловили фазу обработки). Данные старых phase*.npz про FIR —
|
||
валидны для своих моментов, но смешивать с новыми нельзя.
|
||
3. Все «FIR mag» анализы через этот слот зависят от ТОГО, в какой фазе
|
||
слот был пойман: указатель-на-буфер vs скаляры vs сброс.
|
||
4. Значения скаляров (~0.43, 2.0) — кандидаты: att/rel? dry/wet? g-компоненты?
|
||
### Статус
|
||
Канонический путь чтения ПРИМЕНЁННОЙ маски: слот [ctx+0x540678] (кривая
|
||
банды) — он стабилен и МАТЧИТ АУДИО в deep-фазах (±5%).
|
||
|
||
## ДОПОЛНЕНИЕ 24mm2: ПОЛНАЯ РЕЗОЛЮВСЯ ВСЕХ 10 ЯДЕР + ИСПРАВЛЕНИЯ DATAFLOW
|
||
|
||
Инструмент: статический резолв цепочки стаб→таблица→L2→IAT-слот по
|
||
soothe_mem.bin (без live). Стаб = `movsxd rax,[idx@1826159a0]; lea r10,[tbl];
|
||
jmp [r10+rax*8]`, idx=4, L2=`mov rax,[slot]; jmp rax`.
|
||
|
||
### Таблица резолва (исправляет 24jj!)
|
||
| стаб | таблица | runtime | опознание по константам |
|
||
|------|---------|---------|------------------------|
|
||
| 140950 | 182617448 | **18026b820** | exp2/exp DOUBLE (ln2, log2e, 1021.5, 2^27) |
|
||
| 140980 | 182617488 | **18027c120** | **logf** FLOAT (ряд −½,+⅓,−¼,+⅕,−⅙; ln2 hi/lo; 2^32) |
|
||
| 1409b0 | 1826174c8 | **18028d1e0** | **powf/log+exp** DOUBLE (ряд log + магия expf вместе) |
|
||
| 1409e0 | 182617508 | 180296c80 ✓ | **expf** FLOAT — ДЕКОДИРОВАН ПОЛНОСТЬЮ (ниже) |
|
||
| 140a40 | 182617588 | 1802dc0e0 ✓ | exp-вариант FLOAT c hi/lo сплитами |
|
||
| 140aa0 | 182617608 | **18030fee0** | **sincos** DOUBLE (1/6,1/120,1/5040; π hi/lo) |
|
||
| 140ad0 | 182617648 | 180323f20 ✓ | кусочно-табличная DOUBLE (сетка Δ=0.00541521) |
|
||
| 140b00 | 182617688 | **180367980** | pow/exp DOUBLE (1023/1022, магия 1.5·2^20) |
|
||
| 140b30 | 1826176c8 | **1803831c0** | кусочно-табличная FLOAT (π/2, π/4, сетка 184.665!) |
|
||
| 140b60 | 182617708 | 1803a06a0 ✓ | **DIVIDE** FLOAT B/A (rcp+квантование+vpermps-таблицы+полином невязки) |
|
||
|
||
**ИСПРАВЛЕНИЕ 24jj**: «140b30/140b60 → общий 1803a06a0» — НЕВЕРНО.
|
||
FIR-секция вызывает 140b30 = 1803831c0 (табличная кривая), divide только в шаге 9c.
|
||
|
||
### ДИСПЕТЧЕР float/double
|
||
Каждый call-site имеет ПАРУ стабов через `call [181bab008]; test eax,eax; jne`:
|
||
float-стаб (eax==0) / double-стаб. Дескрипторы type_info СТАТИЧЕСКИ идентичны
|
||
(оба →182650db8) ⇒ eax=0 ⇒ **double-ядра мертвы на нашем пути**; рендеры
|
||
идут по float. Double-тела не транскрибируем (отмечено на будущее M8).
|
||
|
||
### expf 180296c80 — полная формула (горячий цикл, FMA-точно)
|
||
```
|
||
n = fma(log2e_hi=1.4427, x, MAGIC=12582912.0) ; округление до int
|
||
k = n − MAGIC
|
||
r = (x − 0.693146·k) − 1.42861e-06·k ; ln2 hi/lo
|
||
p = (((0.00829172·r + 0.0418735)·r + 0.166674)·r + 0.499994)·r + 1)·r + 1
|
||
out = bits( (k<<23) + bits(p) ) ; vpaddd сборка
|
||
guard: |x|>87.3365 → slow-path; head/tail через vmaskmovps+popcnt-маски
|
||
```
|
||
Коэф. минимаксные — транскрибировать КАК ЕСТЬ.
|
||
|
||
### DIVIDE 1803a06a0 — структура (90%)
|
||
```
|
||
A=[rcx], B=[rdx], dst=[r8]; r9d=n
|
||
q0 = rcp(A); q0 += 2^23-magic (округление); q = q0 & 0xfff00000 ; 12 бит
|
||
e = (q>>23); idx = q>>20 → vpermps tbl@1821269c0 (127±ε) и @182126a00
|
||
err = 1 − q·A
|
||
полином невязки {0.207515, −0.241687, 0.288535, −0.360671, ..., 0.240264, 0.0555119}
|
||
сборка через магию 1.5·2^20 + vpslld 20
|
||
результат ≈ B/A с точностью ~0.5 ulp
|
||
```
|
||
Таблицы коррекций сдамплены (per-mantissa-top-bits).
|
||
|
||
### ИСПРАВЛЕНИЯ DATAFLOW (по fn529fe0.dis, адреса call-sites)
|
||
1. **Шаг 14 порядок ОБРАТЕН к BLOCKMAP 24ii**: сначала `bigkernel exp IN-PLACE
|
||
на bands_curve` (52ae0e), ПОТОМ `bands_curve += (−1.0)` (52ae40, конст.
|
||
1824c4680 через th2270).
|
||
2. Шаг 9b точно: `vec6f8 += [ctx+54087c] · 0.8` (xmm10=0.8@1824c3e28,
|
||
множитель виден в asm: mulss xmm6,xmm10 после movss xmm6,[54087c]).
|
||
3. Шаг 9a: `vec698 *= (xmm12=1.0 − [54087c])` ⇒ zero-fill при дефолтах ✓.
|
||
4. Шаг 10 combine dc40: аргументы rcx=ACC_i(**таблица указателей @0x5407c8**,
|
||
НЕ дампилась rendersnap2!), rdx=bands_curve_i(@678+i), r8=vec6f8(@6f8),
|
||
семантика dst=r8: vec6f8 = bands_curve_i − ACC_i. ACC-слот надо ДОБАВИТЬ
|
||
в SLOTS rendersnap2 (0x5407c8).
|
||
5. Шаги 15/16 подтверждены: th2000/th1c40 array-mul; затем rbx=[5406a8]
|
||
(kWarp) — array-mul на bands_curve.
|
||
6. Эпилог: скалярная часть из decomp (consumers_out 100-143): mix-веса,
|
||
`fVar17 = [540874] − expf(DAT_1824c4704=-ln1000)` → bands += f17·[540888].
|
||
|
||
### Call-site карта больших ядер (fn529fe0)
|
||
```
|
||
52a63a/52a641: 140980(logf-float)/1409b0 — pre-combine #1
|
||
52ab84/52ab8b: 140b60(divide)/140950 — шаг 9c
|
||
52acd? : (шаги 10–12 мелкие ILT)
|
||
52ae0e/52ae15: 1409e0(expf)/140ad0 — шаг 14 нелинейность
|
||
52b32c/52b336: 1409e0(expf)/140ad0 — шаг 17 (повтор)
|
||
52b3a0/52b3aa: 140a40(exp-var)/140b00 — пост-17
|
||
52b716/52b71d: 140b30(кривая-float)/140aa0 — FIR-секция
|
||
```
|