- Инфраструктура: 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 порядок).
50 lines
2.4 KiB
Python
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() |