"""Unit tests for verify.py — the math QA metrics. Builds synthetic finished tracks (good, silence-collapsed, clipped) as temp WAVs and checks the right metric catches each fault. No model needed.""" import numpy as np import soundfile as sf import verify SR = verify.SR def _stereo(freqs, seconds, amp=0.3): """sum of sine partials -> a richer (non-pure-tone) stereo signal.""" t = np.arange(int(seconds * SR)) / SR y = sum(np.sin(2 * np.pi * f * t) for f in freqs) / len(freqs) L = (amp * y).astype(np.float32) R = (amp * np.roll(y, 13)).astype(np.float32) # slight decorrelation return np.stack([L, R]) def _write(path, audio): sf.write(str(path), audio.T, SR, subtype="PCM_16") def test_relative_keys(): assert "A minor" in verify._relative_keys("C major") assert "C major" in verify._relative_keys("A minor") assert "C major" in verify._relative_keys("C major") def test_good_continuation_passes_health_metrics(tmp_path): chord = [220, 277, 330] # A major-ish triad orig = _stereo(chord, 10) finished = _stereo(chord, 40) # continuous, same content op, fp = tmp_path / "o.wav", tmp_path / "f.wav" _write(op, orig) _write(fp, finished) rep = verify.verify(str(op), str(fp), source_seconds=10) m = rep["metrics"] assert m["no_silence_collapse"]["pass"] assert m["no_clipping"]["pass"] assert m["duration"]["pass"] assert m["loudness_continuity"]["pass"] assert m["spectral_rolloff"]["pass"] def test_silence_collapse_is_caught(tmp_path): chord = [220, 277, 330] orig = _stereo(chord, 10) new = _stereo(chord, 30) new[:, 5 * SR:15 * SR] = 0.0 # a dead 10s stretch mid-tail finished = np.concatenate([_stereo(chord, 10), new], axis=-1) op, fp = tmp_path / "o.wav", tmp_path / "f.wav" _write(op, orig) _write(fp, finished) rep = verify.verify(str(op), str(fp), source_seconds=10) assert not rep["metrics"]["no_silence_collapse"]["pass"] def test_clipping_is_caught(tmp_path): chord = [220, 277, 330] orig = _stereo(chord, 10) finished = _stereo(chord, 30) * 4.0 # drive it hard finished = np.clip(finished, -1.0, 1.0) # …into hard clipping op, fp = tmp_path / "o.wav", tmp_path / "f.wav" _write(op, orig) _write(fp, finished) rep = verify.verify(str(op), str(fp), source_seconds=10) assert not rep["metrics"]["no_clipping"]["pass"] def test_closing_fade_not_flagged_as_collapse(tmp_path): """a real cos^2 closing fade must NOT trip the silence-collapse metric.""" chord = [220, 277, 330] finished = _stereo(chord, 40) fade = int(4.0 * SR) curve = np.cos(np.linspace(0, np.pi / 2, fade)) ** 2 finished[:, -fade:] *= curve orig = _stereo(chord, 10) op, fp = tmp_path / "o.wav", tmp_path / "f.wav" _write(op, orig) _write(fp, finished) rep = verify.verify(str(op), str(fp), source_seconds=10, fade_seconds=4.0) assert rep["metrics"]["no_silence_collapse"]["pass"] def test_report_shape(tmp_path): chord = [220, 277, 330] op, fp = tmp_path / "o.wav", tmp_path / "f.wav" _write(op, _stereo(chord, 10)) _write(fp, _stereo(chord, 30)) rep = verify.verify(str(op), str(fp), source_seconds=10) assert set(["metrics", "passed", "finished", "boundary"]).issubset(rep) assert isinstance(rep["passed"], bool) for name, mtr in rep["metrics"].items(): assert set(["value", "pass", "reason"]).issubset(mtr)