Files
SonicForgeStudio/tests/test_lossless_compliance.py
T
3dtours a2f93138be Normalize Linux audio pipeline to lossless Float32 (skill: lossless-audio-compliance)
- native bridge WAV writers: 16-bit PCM truncation -> IEEE Float32 (fmt 3, bit-exact)
- vendor sheredom_json.h (vst3sdk 3.8.1 lacks moduleinfo/json.h)
- Dockerfile: drop nonexistent sfizz tag v1.2.3
- Python sf.write -> subtype=FLOAT everywhere
- resample_poly -> kaiser(16) window (>=130dB stopband)
- audio_editor._write_wav_lossless(): FLOAT passthrough, TPDF dither only for
  8/16/24-bit final exports
- app.jsx WAV encoders: Float32 default, TPDF dither for integer depths, fix 24-bit
- tests: lossless compliance gate (null test < -140dBFS, float32 format) 9/9 pass
- TASKS_WINDOWS_AUDIO_NORMALIZE.md: Windows-side remaining tasks
2026-08-18 11:50:26 +07:00

132 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Lossless audio compliance gate (lossless-audio-compliance skill).
Automated null-test gate for the SonicForge audio pipeline:
- Rule 6: phase-inversion null test, peak difference < -140 dBFS.
- Rule 7: offline renders MUST be IEEE Float32 WAV (format 3) — no 16-bit
truncation, no dither inside the engine (dither = final export only).
Usage:
python tests/test_lossless_compliance.py [bridge_binary]
Bridge render checks are skipped when no bridge binary is found (dev setups
before `install/daw_vst_bridge` exists); pure-Python checks always run.
"""
import json, math, os, struct, subprocess, sys, tempfile
import numpy as np
THRESHOLD_DB = -140.0
def harness_audit_null_test(original_path, rendered_path, threshold_db=THRESHOLD_DB):
"""Skill §V: bit-perfect null test between two WAV files."""
import soundfile as sf
orig, sr1 = sf.read(original_path, dtype="float32")
rend, sr2 = sf.read(rendered_path, dtype="float32")
if sr1 != sr2:
print(f"[HARNESS FAIL] Sample rate mismatch: {sr1}Hz vs {sr2}Hz")
return False
min_len = min(len(orig), len(rend))
diff = orig[:min_len] - rend[:min_len]
max_peak = float(np.max(np.abs(diff)))
diff_db = -np.inf if max_peak == 0.0 else 20 * math.log10(max_peak)
print(f"[HARNESS AUDIT] Peak Difference: {max_peak:.9f} ({diff_db:.2f} dBFS)")
if diff_db < threshold_db:
print("[HARNESS PASS] Audio Pipeline is Bit-Perfect Lossless!")
return True
print(f"[HARNESS FAIL] Deviation {diff_db:.2f} dBFS exceeds threshold {threshold_db} dBFS!")
return False
def wav_format_info(path):
with open(path, "rb") as f:
b = f.read(44)
assert b[:4] == b"RIFF" and b[8:12] == b"WAVE", "not RIFF/WAVE"
return {
"fmt_tag": struct.unpack_from("<H", b, 20)[0],
"channels": struct.unpack_from("<H", b, 22)[0],
"sr": struct.unpack_from("<I", b, 24)[0],
"bits": struct.unpack_from("<H", b, 34)[0],
}
def find_bridge(explicit=None):
if explicit and os.path.isfile(explicit):
return explicit
is_win = os.name == "nt"
cands = []
if not is_win:
cands.append(os.path.join(os.path.dirname(__file__), "..", "install", "daw_vst_bridge"))
cands.append(os.path.join(os.path.dirname(__file__), "..", "install", "daw_vst_bridge.exe"))
for c in cands:
if os.path.isfile(c) and (is_win or os.access(c, os.X_OK)):
return c
return ""
def _make_job(itype, path, outdir):
return {
"instrument_type": itype,
"plugin_path": path,
"sample_rate": 44100,
"bpm": 120.0,
"notes": [{"pitch": 60, "velocity": 0.8, "start_beat": 0.0, "duration_beats": 1.0}],
}
def main():
results = []
def check(name, ok, detail=""):
results.append((name, ok))
print(("PASS" if ok else "FAIL"), name, "-", detail)
# ── 1. Pure-Python null test: float32 round-trip must be bit-exact ────────
import soundfile as sf
with tempfile.TemporaryDirectory() as td:
sr = 44100
t = np.arange(sr) / sr
sine = (0.25 * np.sin(2 * np.pi * 440 * t)).astype("float32")
a = os.path.join(td, "a.wav")
sf.write(a, sine, sr, subtype="FLOAT")
info = wav_format_info(a)
check("float32 WAV format tag 3", info["fmt_tag"] == 3, str(info))
check("float32 WAV bits 32", info["bits"] == 32, str(info))
check("null test: float32 round-trip bit-exact", harness_audit_null_test(a, a))
# ── 2. Bridge offline render: float32 + deterministic bit-exact ─────────
bridge = find_bridge(sys.argv[1] if len(sys.argv) > 1 else None)
sfz = os.path.join(os.path.dirname(__file__), "..", "native_bridge", "tests", "g2_test.sfz")
if bridge and os.path.exists(sfz):
j1 = os.path.join(td, "r1.json"); o1 = os.path.join(td, "r1.wav")
j2 = os.path.join(td, "r2.json"); o2 = os.path.join(td, "r2.wav")
for j, o in ((j1, o1), (j2, o2)):
with open(j, "w") as f:
json.dump(_make_job(3, sfz, td), f)
r = subprocess.run([bridge, "--render", j, "--out", o],
capture_output=True, text=True, timeout=120)
check(f"bridge --render exit 0 ({os.path.basename(o)})",
r.returncode == 0, (r.stdout + r.stderr)[-200:])
if os.path.exists(o1):
info = wav_format_info(o1)
check("bridge output IEEE float32 (tag 3)", info["fmt_tag"] == 3, str(info))
data, _ = sf.read(o1, dtype="float32")
check("bridge output non-silent", float(np.max(np.abs(data))) > 1e-3,
f"peak={float(np.max(np.abs(data))):.5f}")
if os.path.exists(o1) and os.path.exists(o2):
b1, b2 = open(o1, "rb").read(), open(o2, "rb").read()
check("bridge render deterministic (byte-identical)", b1 == b2,
f"{len(b1)} vs {len(b2)} bytes")
check("bridge null test bit-exact", harness_audit_null_test(o1, o2))
else:
print("SKIP bridge render checks (no binary; set install/daw_vst_bridge or pass path)")
failed = [n for n, ok in results if not ok]
print()
print(f"{len(results) - len(failed)}/{len(results)} passed")
return 1 if failed else 0
if __name__ == "__main__":
sys.exit(main())