"""audio_problems: silence gap, clipped burst, level jump, clean signal.""" import sys from pathlib import Path import unittest sys.path.insert(0, str(Path(__file__).resolve().parents[1])) from pydub import AudioSegment from pydub.generators import Sine, Square from core.audio import audio_problems SR = 24000 def tone(ms, gain=-20): return Sine(300, sample_rate=SR).to_audio_segment(ms).apply_gain(gain) def kinds(seg): return {p["kind"] for p in audio_problems(seg)} class AudioProblemTests(unittest.TestCase): def test_clean(self): self.assertEqual(audio_problems(tone(4000, -18).set_frame_rate(SR)), []) def test_silence_gap(self): seg = tone(2000) + AudioSegment.silent(2000, frame_rate=SR) + tone(2000) p = [x for x in audio_problems(seg) if x["kind"] == "silence"] self.assertEqual(len(p), 1) self.assertAlmostEqual(p[0]["start_s"], 2.0, delta=0.1) def test_edge_silence_ignored(self): seg = AudioSegment.silent(3000, frame_rate=SR) + tone(2000) + AudioSegment.silent(3000, frame_rate=SR) self.assertNotIn("silence", kinds(seg)) def test_clipping(self): burst = Square(300, sample_rate=SR).to_audio_segment(400).apply_gain(+10) seg = tone(2000) + burst + tone(2000) p = [x for x in audio_problems(seg) if x["kind"] == "clipping"] self.assertTrue(p) self.assertAlmostEqual(p[0]["start_s"], 2.0, delta=0.1) def test_level_jump(self): seg = tone(2000, -40) + tone(2000, -10) p = [x for x in audio_problems(seg) if x["kind"] == "level_jump"] self.assertEqual(len(p), 1) self.assertAlmostEqual(p[0]["start_s"], 2.0, delta=0.1) class VoiceHealthTests(unittest.TestCase): def test_analyze_and_stored(self): import tempfile from core.voice import _voice_health, _validate_voice_meta with tempfile.TemporaryDirectory() as d: wav = Path(d) / "EN_F_test.wav" (tone(2000) + AudioSegment.silent(2000, frame_rate=SR) + tone(2000)).export(str(wav), format="wav") h = _voice_health(wav, meta={}, transcript="hi", duration=6.0, analyze=True) self.assertEqual([p["kind"] for p in h["problems"]], ["silence"]) self.assertIn("Long silence in reference audio", h["warnings"]) stored = _voice_health(wav, meta={"audio_problems": h["problems"]}, transcript="hi", duration=6.0) self.assertEqual(stored["problems"], h["problems"]) self.assertEqual(_voice_health(wav, meta={}, transcript="hi", duration=6.0)["problems"], []) with self.assertRaises(ValueError): _validate_voice_meta({"audio_problems": "x"}) if __name__ == "__main__": unittest.main()