From 0d262461ea78634f883f7be1350f068c88e1439e Mon Sep 17 00:00:00 2001 From: Matiq Date: Thu, 20 Aug 2026 15:25:49 +0300 Subject: [PATCH] P4: lock bigkernel semantics (exp2(-mask)*blend) + calibrate scale Read the 0x26b820 SIMD loop: the exp2 result is multiplied by the blend buffer (vmulpd at 0x18026bba0 with ymm11=blend) => mask = exp2(-level)*blend, sign inverted for attenuation. framed_model.cpp corrected to exp2(-scratch)*0.8. Calibrated level_scale=600 -> t1kq err -0.06 dB (ref -14.98). comb per-tone errors reduced (max ~7.8 dB); warp/FFT-conv smoothing still approximated. --- dsp/framed_model.cpp | 7 +++++-- handoff/NOTES_LEVEL.md | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/dsp/framed_model.cpp b/dsp/framed_model.cpp index 9fe26d5..0fa8ebf 100644 --- a/dsp/framed_model.cpp +++ b/dsp/framed_model.cpp @@ -117,9 +117,12 @@ void FramedDetector::processFrame(const std::complex* spectrum, float* m // 4. blend + bigkernel exp2 (0x26b820): // b = freqaxis*(1-mix) + mix*0.8 (= 0.8 at mix=1.0) - // mask = exp2(0.5 * (mask - b)) [exp2 kernel scales input by 0.5] + // mask = exp2(-mask) * b (vectorized exp2 of x blend; + // verified from the SIMD loop: the + // exp2 result is multiplied by the + // blend buffer ymm11). for (size_t k = 0; k <= half; k++) { - scratch[k] = std::exp2(0.5 * (static_cast(scratch[k]) - C_BLEND08)); + scratch[k] = std::exp2(-static_cast(scratch[k])) * C_BLEND08; } // 5. combine / accumulator (0x5407c8[band]): diff --git a/handoff/NOTES_LEVEL.md b/handoff/NOTES_LEVEL.md index 7e0b92d..5936a60 100644 --- a/handoff/NOTES_LEVEL.md +++ b/handoff/NOTES_LEVEL.md @@ -850,3 +850,17 @@ Read /tmp/consumers_out.txt:471-1277 (full decomp) + f529fe0.dis + live snap_rt. ### NOTE (SR mismatch): internal DSP SR=48000, N=4096 (bin spacing 11.713 Hz). Host refs 44100. IIR tables indexed 0..2048 (N/2+1). For bit-exact the detector must run N=4096@48k internally. + +## ============ UPDATE 2026-08-20k: bigkernel 0x26b820 = vectorized exp2 (semantics LOCKED) ============ +Read the SIMD loop (objdump 0x18026b820-0x18026bcaf). Key line 0x18026bba0: + vmulpd ymm12 (exp2 result) by ymm11 (loaded from rbp = blend buffer 0x5406f8). +=> mask[i] = exp2(x) * blend[i], where x is the mask value (0x540678[band]) and + blend = freqaxis*(1-mix)+mix*0.8 (=0.8 at mix=1.0). sign: to get attenuation + (mask<1) x must be negative, so mask = exp2(-level) * blend. Locked. +exp2 is standard log2e/poly/mantissa-table (0x1f34a80..., log2e~1.4424, floor -708.9). + +### Calibration (framed_test, structural chain now in framed_model.cpp): +- t1kq single band (678.76,q~1,sens12): level_scale=600 -> err -0.06 dB (ref -14.98). +- comb 4-band at scale 600: per-tone err 300:-5.1, 500:+7.8, 1000:+4.4, 1500:+3.9, + 2000:-1.3, 3000:+4.8 dB (max 7.8). Mask shape (warp tilt + FFT-conv smoothing) + still approximated.