#!/usr/bin/env python3 import subprocess, os, glob, sys, time, struct, math RPP = "/home/m/soothe-bt/render_short.rpp" OUT = "/home/m/soothe-bt/out_rt.wav" proc = subprocess.Popen(['reaper', '-nosplash', '-renderproject', RPP], stdout=open('/tmp/rttbl.log', 'w'), stderr=subprocess.STDOUT) print('reaper', proc.pid, flush=True) def find_hosts(): out = [] for p in glob.glob('/proc/[0-9]*'): try: pid = int(os.path.basename(p)) m = open(f'/proc/{pid}/maps').read() c = open(f'/proc/{pid}/cmdline', 'rb').read().decode('utf8', 'replace') if 'soothe2' in m and 'yabridge-host.exe' in c: out.append(pid) except Exception: pass return out def out_growth(): try: return os.path.getsize(OUT) except Exception: return 0 t0 = time.time() hosts = None base_sz = out_growth() while time.time() - t0 < 60: hosts = find_hosts() if hosts: break time.sleep(0.2) print('hosts:', hosts, flush=True) grew = 0 while time.time() - t0 < 120: s = out_growth() if s > base_sz: grew = s; break if proc.poll() is not None: print('reaper exited early', flush=True); break time.sleep(0.3) print('out:', grew, flush=True) if not hosts or grew == 0: proc.kill(); sys.exit('fail') time.sleep(0.5) step = 2 * math.pi / 2048 def qsin(k): # sin(k*step) search tolerance 1e-6 (we only need anchor match) return math.sin(k * step) for pid in hosts: mem = os.open(f'/proc/{pid}/mem', os.O_RDONLY) tables = [] maps = open(f'/proc/{pid}/maps').read() for line in maps.splitlines(): p = line.split() lo, hi = (int(x, 16) for x in p[0].split('-')) if 'r' not in p[1]: continue if lo < 0x180000000 or lo >= 0x183000000: try: d = os.pread(mem, hi - lo, lo) except Exception: continue if len(d) < 16: continue q = len(d) // 8 qw = struct.unpack('<%dQ' % q, memoryview(d)[:q * 8]) for o in range(0, q - 4): if qw[o] != 0: continue # candidate anchor: qw[o]==0.0 and qw[o+1] approx sin(step), qw[o+2] approx sin(2step) v1 = struct.unpack('