Files
soothe2-re/handoff/NOTES_CAPTURE.md
T

3.8 KiB

RUNTIME CAPTURE — LIVE DSP TABLES (2026-08-19)

BREAKTHROUGH: heap "registry" object found & read during offline render

  • During reaper -nosplash -renderproject render_long.rpp, the yabridge-host allocates a DSP arena containing a registry array: a run of {u64 count, u64 ptr} pairs (stride 0x10) pointing at every DSP buffer. At capture time: registry base = 0x29b06c0 (in anon region 0x2922000, 0x77e000). (GUI-session registry was 0x28b06c0 — same object, shifted by arena layout.)
  • Finding it live: scan host-readable memory (chunked, 8MB) for u64==8193 (0x2001) followed by a readable ptr, then require a run of count/ptr pairs at stride 0x10.
  • Registry owner chain: 0 hits for a u64==registry address, so it is reached structurally (object member at some fixed offset), not via an explicit global.

Captured tables (SR=44100 project, but internal freq-axis = 48000!)

reg idx count ptr content
[00] 8193 0x2a72600 identity ~1.0
[01] 8193 0x2111140 WIN_freq: 0.5 -> 1.0 (saturates; idx1024=0.68, idx2048=0.8) — the FFT-conv window (0x540658)
[02] 8193 0x29f2280 0 -> ~0.01 (levels/curve)
[03] 8193 0x29fa300 0.596 -> 0.126 = matches known rwin_C0
[04] 8193 0x2a02340 0.404 -> 0.874 = 1-[03] complement
[05] 8193 0x2a0a3c0 0.0435 -> ~0 (weight, small)
[06] 8193 0x2a12400 0.9565 -> ~1.0 (1-[05])
[07] 8193 0x2aca740 zeros + small negatives
[0d] 2049 0x2cd0fc0 freq-axis 0..23988.3 Hz, spacing 11.713 = 48000/4096 → internal SR=48000
[0e] 8193 0x2cd9000 2.017 -> 0 (LUT/knee?)
[0f] 16384 0x2ce9080 same as [0e] doubled
[10] 16384 0x2cf90c0 1.2914 -> 0
[12] 16384 0x2a62540 11.29.. (scattering)
[14]/[15] 8193 .. first-fire IR? 0,0.022,0.104,0.084,0.018,0
[17] 32768 0x2d29140 0.9999 -> ~1 (ramp)
[19] 32768 0x2d69200 1.2915 -> 1.0
others 32768/65536 .. ones / ramps (FFT plans, mirrors)
  • Key numeric check: registry[03] head 0.5960761, idx1024 0.168, idx2048 0.1257 — byte-identical to earlier GUI rwin_C0 (0.596 -> 0.126). Confirms registry IS the authoritative per-bin weight source; tables are stable across sessions/SR.
  • FREQ-AXIS uses internal SR=48000 regardless of project 44100 (spacing 11.713). This reconciles "rwin tables at 48k" even when rendering 44.1k projects.

Files saved (handoff/)

  • rtwin_freq_44100.npy — WIN_freq (8193 f32): 0.5 -> 1.0 (this is live 0x540658 window)
  • rtfreqaxis_48000_internal.npy — freq-axis (2048 f32, 0..23988.3, spacing 11.713)
  • rtwa_596.npy — [03] 0.596->0.126
  • rtwb_404.npy — [04] 0.404->0.874
  • rtwc_043.npy — [05]
  • rtwd_956.npy — [06]
  • Full raw snapshot: /tmp/snap_all.bin (318MB, entries {lo,sz,bytes}), registry.txt list.

Method notes (repro)

  • rtsnap_fast.py: spawn reaper render_long, find host (soothe2 in maps, not reaper), sleep 6s (tables built), pread ALL readable maps chunked 8MB -> snap_all.bin.
  • pread of large anon regions can EIO -> MUST chunk (8MB); whole-region pread loses data.
  • Scan ~0.1s for 318MB once chunked; far cheaper than object-base scan.
  • Earlier vptr-based (rtobj/rtdump2/rtall) and 44100-marker scans all failed because the DSP object has NO static vptr match in a fresh render (host dies / fields live only during audio) and ctor field +0x24 != 44100 live. The registry run is the reliable beacon.

Remaining (for twin IIR attack/release per-bin)

  • twin state A/B (342 double per-bin IIR states) still not uniquely located live; short renders keep them ~0. They are NOT the registry tables.
  • Next: render_long + capture at t=10-20s into sustain, then locate the per-bin attack/release smoothing coefficients (0x540888/88c set, converted via ln(10)/20) inside the arena near registry.