diff --git a/handoff/NOTES_CAPTURE.md b/handoff/NOTES_CAPTURE.md index 81af2bc..f7011b4 100644 --- a/handoff/NOTES_CAPTURE.md +++ b/handoff/NOTES_CAPTURE.md @@ -63,3 +63,16 @@ - 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. + +## 2026-08-19b (two-point snapshots t1=8s, t2=40s of render_long 180s) +- rtsnap2.py: TWO snapshots of the SAME 180s render at t1/t2; each 318MB/547regs ~0.2s. +- Registry tables byte-identical between t1/t2 (stable per-band coeffs; confirmed authoritative). +- Diff of arbitrary 342-double windows = pure audio-buffer noise (21981 phantom matches; twin + per-band state is NOT a 342-dbl array a level away). Real twin kernel state per NOTES_TWIN:64 + is {double A[3], double B[3]} per band (6 doubles), seeded in build_twin_coeff FUN_180533ec0. +- Conclusion: live per-note-band twin state not usefully separable via full-heap diff; the + attack/release input coeffs live in the DSP ctx scalars: 0x540888/0x54088c = expf(p*0.11513) + (static-derived), registry holds the per-bin WEIGHT tables (already captured). Twin kernels + themselves validated statically (twin_check max|err|=1.27e-5). => Step C goal (window + axes + + weights + kernel parity) is effectively CLOSED; only scalar A/R params remain, derived from RPP + params, no live capture needed. diff --git a/rtsnap2.py b/rtsnap2.py new file mode 100644 index 0000000..0d9d783 --- /dev/null +++ b/rtsnap2.py @@ -0,0 +1,43 @@ +import subprocess, os, glob, time, struct +def mem_open(pid): return os.open(f'/proc/{pid}/mem', os.O_RDONLY) +def find_hosts(): + hosts=[] + for p in glob.glob('/proc/[0-9]*'): + pid=int(os.path.basename(p)) + try: + cmd=open(f'/proc/{pid}/cmdline','rb').read().replace(b'\0',b' ').decode('utf8','replace') + maps=open(f'/proc/{pid}/maps').read() + except Exception: continue + if 'soothe2' in maps and 'reaper' not in cmd: + hosts.append(pid) + return hosts +os.system("pkill -9 -x reaper 2>/dev/null; pkill -9 -f '[y]abridge' 2>/dev/null; sleep 1") +proc=subprocess.Popen(['/usr/bin/reaper','-nosplash','-ignoreerrors','-renderproject','/home/m/soothe-bt/render_long.rpp'], + stdout=open('/dev/null','w'),stderr=subprocess.STDOUT) +t0=time.time(); host=None +while time.time()-t0<60 and not host: + hs=find_hosts(); host=hs[0] if hs else None; time.sleep(0.2) +print('host',host, flush=True) +fd=mem_open(host) +def snap(tag): + out=open('/tmp/snap_%s.bin'%tag,'wb'); idx=open('/tmp/snap_%s.idx'%tag,'wb') + t0=time.time(); nreg=0; nb=0 + for line in open(f'/proc/{host}/maps').read().splitlines(): + p=line.split(); lo,hi=(int(x,16) for x in p[0].split('-')) + if 'r' not in p[1]: continue + a=lo + while a