add dsp/ with FFT, filters, detector, stereo support
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
#!/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('<d', struct.pack('<Q', qw[o + 1]))[0]
|
||||
v2 = struct.unpack('<d', struct.pack('<Q', qw[o + 2]))[0]
|
||||
e1, e2 = qsin(1), qsin(2)
|
||||
if abs(v1 - e1) < 1e-8 and abs(v2 - e2) < 1e-8:
|
||||
# count how many follow match sin(k*step) to confirm length
|
||||
cnt = 0
|
||||
for k in range(1, 900):
|
||||
v = struct.unpack('<d', struct.pack('<Q', qw[o + k]))[0]
|
||||
if abs(v - qsin(k % 1024)) < 1e-6 and k <= 300:
|
||||
cnt = k
|
||||
else:
|
||||
break
|
||||
tables.append((lo + o * 8, cnt))
|
||||
# limit scanning to a sane budget
|
||||
print('PID', pid, 'tables:', tables[:10], flush=True)
|
||||
for t, cnt in tables[:3]:
|
||||
off = t
|
||||
vals = []
|
||||
mem2 = os.open(f'/proc/{pid}/mem', os.O_RDONLY)
|
||||
try:
|
||||
d = os.pread(mem2, 1024 * 8, t)
|
||||
vals = struct.unpack('<1024d', d)
|
||||
except Exception as e:
|
||||
print('read err', e, flush=True)
|
||||
os.close(mem2)
|
||||
with open('twiddle_2048_ref.f64', 'wb') as f:
|
||||
for v in vals:
|
||||
f.write(struct.pack('<d', v))
|
||||
print(' ', hex(t), 'len~', cnt, 'first', ' '.join('%.9g' % v for v in vals[:5]),
|
||||
'idx256', vals[256], flush=True)
|
||||
print(' saved twiddle_2048_ref.f64', flush=True)
|
||||
break
|
||||
os.close(mem)
|
||||
proc.kill()
|
||||
print('done', flush=True)
|
||||
Reference in New Issue
Block a user