4.8 KiB
Twin FUN_180535880 transcription (Phase 2)
PHASE-3 CALLER + GRID (2026-08-18)
- Caller FUN_180536300 (decomp 6218 / sp_180536300.txt) decoded at buffer level:
- params: param_1=top DSP, param_2=out, param_3=?, param_4=band obj, param_5=cell count, param_7=scratch (>=52*N bytes complex).
- scratch: +0..8N A-accum, +8N..16N B-accum, +16N..24N z-powers, +24N..32N rotor-in (fill 1.0), +32N..36N phase ramp lVar1, +36N..44N rotor-out z1 (r14), +44N..52N lVar3(1.0)/lVar4(0.0) for interleave+negate+exp build.
- 0x18052da00(lVar1, scale=2pi/(iVar7*sr), N) = ramp fill (float, via 0x180001a00);
- twin always = FUN_180535880 (type-info compare of same addr -> equal); sibling FUN_180536f90 is dead.
- 0x18052dbc0(param_2, lVar4, N) = cplx interleave -> out=(cos,sin)=e^{+i theta}.
- GRID LAW (verified from trace.txt case8 + constructor):
- os = (int)(param_1+0x240080) = 4 (written 0x18052ce3e
mov ...,0x4) - sr = (float)(param_1+0x24) = 44100.0
- fs_total (generator) = os*sr = 176400 => resonance shape f/fc invariant to fs.
- per-cell phase step = 2pi/(ossr); cell k <-> freq = k/os Hz (0.25 Hz steps).
- Phase-1 model FS=44100 was a valid normalization (res(f) depends only on f/fc).
- os = (int)(param_1+0x240080) = 4 (written 0x18052ce3e
- case8 generator call (trace 33361..33490, switchD_1805318ab):
- +0x814 numBands = 1, +0x103 mode flag = 1
- param_5 (float, xmm4) = 10^(sens_dB/20) (pow10 10.0^([band+0x101]/20.0))
- gain = sqrtf(param_5) = 10^(sens_dB/40); model fit gain=4.132 => sens_dB@0x101 ~= 24.65
- freq = [band+0x804], Q = [band+0x80c], fs_total = os*sr (w0 = max(fc,2)*2pi/fs_total)
PHASE-2 GATE: PASSED (2026-08-18)
dsp/twin.hpp+dsp/twin.cppwritten: build_twin_coeff (FUN_180533ec0 double pipeline -> cvtpd2ps), cplx_div_exact (0x181a77520: mulps |A|^2, rcpps + Newton, NaN guard), cplx_mul_exact (0x18000ad60 scalar body @0x18000ae00: vfmaddsub213ps form), twin_apply (seed A0/B0 + 2 vfmadd213ss Horner stages + 2*div).- twin_check gate: fc-scan grid (7 fc, Q=0.9999978, gain=4.132, tone 1000 Hz) max |rel err| = 1.27e-5 vs double reference res_at (float rcpps parity). DUAL sweep (Q=0.1..10 x tones 500/2000, fc=500) max = 1.23e-5. Both PASS.
- Constants locked: A1 = B1 = cos(w0)-2.0, z1 = conj(exp(+itheta)), z2 = cplx_mul(z1,z1), out = 2*B/A.
Confirmed scalar math (from generator + cplx-div kernels)
- Generator FUN_180533ec0 (per band, case8):
fVar1 = sqrtf(param_5)(param_5 = pow(10, sens/20) via cd6 IAT stub)w0 = max(2.0, freq)*2*pi / fs_total(fs_total = 2*FS frame?)p = sin(w0)*0.5 / QdVar5 = p*fVar1(A tap),param_4 = p/fVar1(B tap) A = [1+dVar5, dVar2, 1-dVar5], B = [1+param_4, dVar2, 1-param_4] where dVar2 = cos(w0) * DAT_1824c46b0 (=-2.0? VERIFY) - Twin FUN_180535880: for each FFT bin z (rotor):
res(z) = 2 * B(z) / A(z), B(z)=B0+B1z+B2z^2, A(z)=A0+A1z+A2z^2 implemented as complex FMA accumulation over 3 taps: r15 (A-accum) and r12 (B-accum) via 0x180001fd0 vfmadd213ss (coeff [rsp+k4+0x28]=A_k, [+0x38]=B_k) rbp buffer = z powers via rotor ops (0x1800019a0 fill / 0x1800021e0 / 0x1800018b0 / 0x180001af0 / 0x180001dc0) final 0x180001e20 -> 0x181a775a0 cplx-div: out = 2B/A (xmm7=0x40000000=2.0, xmm6=NaN guard) - cplx-div kernel 0x181a77520: |A|^2 via shufps 0x88/0xdd, rcpps + 1 Newton step (xmm7=2.0), NaN guard via cmpeqps. Matches rotor_kernel.hpp cplx-div exactly.
Dispatch (all stubs share global 0x1826159a0 = 4 = AVX2)
0x180001d00 -> 0x180009860 -> 0x180040d40 (cplx fill const, NT stores) 0x1800019a0 -> 0x180004200 (float fill -> 0x181a63fe0) 0x1800021e0 -> 0x1800130e0 (large AVX, 0x450 stack, rotor/exp?) 0x1800018b0 -> 0x180003040 (-> 0x181a557c0) 0x180001af0 -> 0x180005a20 (loop -> 0x18001a5a0) 0x180001dc0 -> 0x18000ad60 (cplx op r14rbp) 0x180001e20 -> 0x18000b820 (-> 0x181a775a0 cplx-div 2B/A) 0x180001fd0 -> 0x18000f620 (vfmadd213ss: out = srccoeff + dst)
Coefficient layout in twin (param_3 = {double A[3], double B[3]})
stack: +0x28=A0 +0x2c=A1 +0x30=A2 | +0x38=B0 +0x3c=B1 +0x40=B2 loop k=0..2 uses A_k via [rsp+k4+0x28], B_k via [rsp+k4+0x38] r15 = out A-accum, r12 = out B-accum, rbp = z^1..z^2 buffer, r14 = rotor(z) input
PHASE-1 LOCK (empirical, 36 points, LUT chain B.11)
Effective sqrtf(param_5) needed ~= 4.13 (NOT 1.995). => param_5 ~= 17.07 = 10^(1.2325) => internal sens_stored ~= 24.65 dB (not XML 12.0) OR equivalent. RULED OUT: sqrt(10^(12/20))=1.995 (rmse 1.38/5.68); 10^(12/20)=3.981 direct (t1kq 0.056 but t1k 0.934); |2B/A|^2 (1.5/6.6). Sens setters (0x18053795d, 0x18056f002) both store RAW value; +0x808 scaling is HOST-side (plugin controller, outside dump) => must be resolved via bit-exact render or host trace. NOTE: single-gain compromise 4.132; t1kq wants 4.055, t1k wants 4.137 (tilt residual).