Files
soothe2-re/scripts/pairfit22q.py
T

76 lines
3.0 KiB
Python

#!/usr/bin/env python3
"""pairfit22q.py — collect (model lvl_raw, real cut_dB) pairs across corpus."""
import sys, os, subprocess, numpy as np
sys.path.insert(0, "/home/m/re-tools/scripts")
sys.path.insert(0, "/home/m/re-tools/handoff")
import corpus
from render_parity import load, FS
RB = "/home/m/re-tools/dsp/build/render48k"
ENVBASE = {"RT_LUT_OFF": "1", "RT_IIR12": "0", "RT_NOWARP": "1",
"RT_NOBLEND": "1", "RT_NOIIR3": "1", "RT_POOL": "0",
"RT_SCALE_M": "1.0", "RT_FLOOR": "0",
"RT_DUMP_BIN": "/tmp/opencode/tract_pair.txt",
"RT_DUMP_FRAME": "120"}
def amp(p, f):
a = load(p)
seg = np.mean(a[:min(len(a), int(3.5*FS))][-int(0.75*FS):], axis=1)
n = len(seg); tt = np.arange(n)/FS
return 2*np.abs(np.dot(seg, np.exp(-2j*np.pi*f*tt)))/n
def bin_of(f):
return int(round(f/48000*4096))
def main():
e = {**os.environ, **ENVBASE}
pairs = []
seen_render = {}
cases = corpus.build_cases()
# unique renders first (input,args): dump tract once, remember lvl per freq
uniq = {}
for name, inp, args, ref, f in cases:
key = (inp, ",".join(args) if isinstance(args, list) else args)
uniq.setdefault(key, []).append((name, ref, f))
n_done = 0
for (inp, argstr), items in sorted(uniq.items()):
out_wav = "/tmp/opencode/pf_model.wav"
env = {**e}
bands = argstr.split(",") if "," in argstr else [argstr]
nbands = max(1, len(bands)//3)
env["RT_DUMP_FRAME"] = str(120 * nbands - 1) # land mid-frame of last band
r = subprocess.run([RB, inp, out_wav] + ([argstr] if "," in argstr else [" ".join([])]),
capture_output=True, text=True, env=env, cwd="/home/m/re-tools")
if not os.path.exists("/tmp/opencode/tract_pair.txt"):
print("no tract for", argstr); continue
try:
d = np.loadtxt("/tmp/opencode/tract_pair.txt")
except Exception as ex:
print("load fail", ex); continue
if d.ndim == 1: continue
k, am, res, lvl = d.T[0], d.T[1], d.T[2], d.T[3]
for name, ref, f in items:
b = bin_of(f)
if b >= len(lvl): continue
lv = float(lvl[b])
i_db = 20*np.log10(max(amp(inp, f), 1e-12))
r_db = 20*np.log10(max(amp(ref, f), 1e-12))
cut = i_db - r_db
pairs.append((name, f, lv, cut))
n_done += 1
os.remove("/tmp/opencode/tract_pair.txt")
print("collected %d pairs from %d renders" % (len(pairs), n_done))
with open("/tmp/opencode/pairs.csv", "w") as fh:
fh.write("case,freq,lvl,cut_db\n")
for nm, f, lv, c in pairs:
fh.write("%s,%.1f,%.4f,%.3f\n" % (nm, f, lv, c))
arr = np.array([(lv, c) for _, _, lv, c in pairs])
o = np.argsort(arr[:, 0]); s = arr[o]
print("lvl -> cut samples:")
step = max(1, len(s)//18)
for i in range(0, len(s), step):
print(" %8.3f -> %+8.2f dB" % tuple(s[i]))
if __name__ == "__main__":
main()