Files
soothe2-re/verify_sim.py
T
Matiq 25cf786c54 Initial commit: soothe2 RE workspace + roadmap
- Инфраструктура: RTTI-дампы (rtti_dsp/full.json), декомпиляции DSP-классов (decomp_*.txt),
  Ghidra-скрипты (Dump*.java, ImportRtti*.java, Diag.java), depthcurve/curve_fits LUT.
- Поведенческая модель sim_v5.py + sim.py (RMSE ~0.3dB), утилиты (measure, tt_sweep, patchparam,
  sweep, harness_*, verify_sim).
- summary.md + roadmap.md (контракт из manual M1-M12, топология пайплайна из OCR, фазы A-C).
- pipeline_ocr.txt: OCR диаграммы Appendix A (mid/side ручка, trim/mix/bypass порядок).
2026-08-16 18:54:40 +03:00

50 lines
2.4 KiB
Python

#!/usr/bin/env python3
"""Верификация симулятора: сравнение трассы 500Hz mag (sim vs реальный рендер).
Использует тот же metric, что measure.py (rfft 10ms окно, mag@500).
RMSE по оси reduction (dB) на окне burst; выводит attack-установку, settled, RMSE.
"""
import argparse, sys, os
sys.path.insert(0, '/home/m/re-tools')
import numpy as np
import sim
from measure import mag_at
def trace(path):
return mag_at(sim.read_wav(path), 500, 44100)
def main():
ap = argparse.ArgumentParser()
ap.add_argument('fx_wav', help='реальный светлый рендер (burst500L_b1.wav)')
ap.add_argument('--dry', default='/home/m/soothe-bt/burst500L_byp.wav')
ap.add_argument('--inp', default='/home/m/soothe-bt/burst500L.wav')
ap.add_argument('--burst', nargs=2, type=float, default=[0.5, 1.5])
ap.add_argument('--params', default='', help='depth=0.864 sens=12 sharp=10 sel=10 mode=1 attack=0 release=0')
a = ap.parse_args()
p = dict(depth=0.864, sens=12.0, sharp=10.0, sel=10.0, mode=1, attack=0.0, release=0.0)
for kv in a.params.split():
k, v = kv.split('=')
p[k] = float(v)
dry = sim.read_wav(a.dry)
x = sim.read_wav(a.inp)
y = sim.simulate(x, fc=500, **{k: p.get(k, d) for k, d in
dict(depth=0.864, sens=12, sharp=10, sel=10, mode=1,
attack=0, release=0, mix=100).items()})
real = trace(a.fx_wav)
mdl = mag_at(y, 500, 44100)
tw = np.arange(min(real.size, mdl.size)) * 0.010 + 0.005
red_real = -20 * np.log10(np.maximum(real[:tw.size], 1e-9) / np.maximum(mag_at(dry, 500, 44100)[:tw.size], 1e-9))
red_mdl = -20 * np.log10(np.maximum(mdl[:tw.size], 1e-9) / np.maximum(mag_at(dry, 500, 44100)[:tw.size], 1e-9))
b0, b1 = a.burst
seg = (tw >= b0 + 0.15) & (tw <= b1 - 0.05)
rmse = np.sqrt(np.mean((red_mdl[seg] - red_real[seg]) ** 2))
print(f"params {a.params or '(default)'}")
print(f" settled real={red_real[seg].mean():7.2f}dB sim={red_mdl[seg].mean():7.2f}dB")
print(f" RMSE(reduction dB, burst steady) = {rmse:.3f}")
for t in [b0 + 0.02, b0 + 0.05, b0 + 0.1, b0 + 0.2, b0 + 0.5]:
i = int(t / 0.010)
print(f" t={t:.2f}s real={red_real[i]:6.2f} sim={red_mdl[i]:6.2f}")
if __name__ == '__main__':
main()