Spaces:
Running
Running
| from __future__ import annotations | |
| import numpy as np | |
| import tempfile | |
| from scipy.io import wavfile | |
| from audio_qa.checks.noise import estimate_snr, check_noise | |
| from audio_qa.checks.clipping import check_clipping | |
| from audio_qa.checks.silence import check_silence | |
| from audio_qa.checks.duration import check_duration | |
| from audio_qa.checks.sample_rate import check_sample_rate | |
| from audio_qa.checks.loudness import check_loudness | |
| from audio_qa.checks.upsampling import check_upsampling | |
| from audio_qa.checks.transcript_ratio import check_transcript_ratio | |
| from audio_qa.checks.channel import check_channel | |
| from audio_qa.pipeline import check_file | |
| def test_clean_has_high_snr(clean_speech): | |
| audio, sr = clean_speech | |
| snr = estimate_snr(audio, sr) | |
| assert snr > 8 | |
| def test_noisy_has_low_snr(noisy_signal): | |
| audio, sr = noisy_signal | |
| snr = estimate_snr(audio, sr) | |
| assert snr < 20 | |
| def test_check_noise_clean(clean_speech): | |
| audio, sr = clean_speech | |
| result = check_noise(audio, sr, snr_threshold=5) | |
| assert result["passed"] | |
| def test_no_clipping_clean(clean_speech): | |
| audio, sr = clean_speech | |
| result = check_clipping(audio, sr) | |
| assert result["passed"] | |
| def test_detects_clipping(clipped_signal): | |
| audio, sr = clipped_signal | |
| result = check_clipping(audio, sr) | |
| assert not result["passed"] or result["clip_regions"] > 0 | |
| def test_clean_no_silence_issues(clean_speech): | |
| audio, sr = clean_speech | |
| result = check_silence(audio, sr) | |
| assert result["passed"] | |
| def test_silent_signal_flagged(silent_signal): | |
| audio, sr = silent_signal | |
| result = check_silence(audio, sr) | |
| assert result["leading_silence_s"] > 1.0 or result["trailing_silence_s"] > 1.0 | |
| def test_duration_in_range(): | |
| result = check_duration(22050 * 5, 22050, min_seconds=1.0, max_seconds=30.0) | |
| assert result["passed"] | |
| def test_duration_too_short(): | |
| result = check_duration(22050, 22050 * 10, min_seconds=1.0) | |
| assert not result["passed"] | |
| def test_sample_rate_standard(): | |
| result = check_sample_rate(22050) | |
| assert result["passed"] | |
| def test_sample_rate_nonstandard(): | |
| result = check_sample_rate(11025) | |
| assert not result["passed"] | |
| def test_upsampling_clean(clean_speech): | |
| audio, sr = clean_speech | |
| result = check_upsampling(audio, sr) | |
| assert result["passed"] | |
| def test_transcript_ratio_normal(): | |
| result = check_transcript_ratio(5.0, "This is a normal sentence for testing purposes.") | |
| assert result["passed"] | |
| def test_transcript_ratio_too_fast(): | |
| result = check_transcript_ratio(0.5, "This is way too much text for half a second of audio really.") | |
| assert not result["passed"] | |
| def test_channel_mono(): | |
| sr = 22050 | |
| audio = np.random.randn(sr * 2).astype(np.float32) * 0.3 | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f: | |
| wavfile.write(f.name, sr, (audio * 32767).astype(np.int16)) | |
| result = check_channel(f.name) | |
| assert result["passed"] | |
| def test_check_file_runs(): | |
| sr = 22050 | |
| n = int(sr * 3.0) | |
| f0_drift = np.cumsum(np.random.randn(n) * 0.05) | |
| f0_curve = 150 + np.clip(f0_drift - np.mean(f0_drift), -40, 40) | |
| phase = np.cumsum(2 * np.pi * f0_curve / sr) | |
| audio = 0.3 * np.sin(phase) + 0.02 * np.random.randn(n) | |
| audio = audio / np.max(np.abs(audio)) * 0.5 | |
| audio_16 = (audio * 32767).astype(np.int16) | |
| with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as f: | |
| wavfile.write(f.name, sr, audio_16) | |
| result = check_file(f.name) | |
| assert result["num_checks"] >= 10 | |
| assert "checks" in result | |
| assert "quality_score" in result | |
| assert "grade" in result | |
| assert 0 <= result["quality_score"] <= 10 | |
| assert result["grade"] in ("A", "B", "C", "D", "F") | |
| def test_nonexistent_file(): | |
| result = check_file("/nonexistent.wav") | |
| assert "error" in result | |
| def test_quality_score_perfect(): | |
| from audio_qa.checks.quality_score import compute_quality_score | |
| checks = [ | |
| {"check": "background_noise", "passed": True, "snr_db": 40}, | |
| {"check": "clipping", "passed": True, "clip_ratio": 0}, | |
| {"check": "silence", "passed": True, "leading_silence_s": 0.1, "trailing_silence_s": 0.1, "max_internal_silence_s": 0}, | |
| {"check": "loudness", "passed": True, "deviation_db": 1}, | |
| {"check": "tts_metallic", "passed": True, "metallic_frame_ratio": 0.02}, | |
| {"check": "upsampling", "passed": True}, | |
| {"check": "channel", "passed": True, "issues": []}, | |
| {"check": "duration", "passed": True}, | |
| ] | |
| result = compute_quality_score(checks) | |
| assert result["quality_score"] >= 8.0 | |
| assert result["grade"] in ("A", "B") | |
| def test_quality_score_bad(): | |
| from audio_qa.checks.quality_score import compute_quality_score | |
| checks = [ | |
| {"check": "background_noise", "passed": False, "snr_db": 3}, | |
| {"check": "clipping", "passed": False, "clip_ratio": 0.05}, | |
| {"check": "silence", "passed": False, "leading_silence_s": 3, "trailing_silence_s": 3, "max_internal_silence_s": 5}, | |
| {"check": "loudness", "passed": False, "deviation_db": 15}, | |
| {"check": "tts_metallic", "passed": False, "metallic_frame_ratio": 0.8}, | |
| {"check": "upsampling", "passed": False}, | |
| {"check": "channel", "passed": False, "issues": ["stereo", "silent left", "phase inverted"]}, | |
| {"check": "duration", "passed": False}, | |
| ] | |
| result = compute_quality_score(checks) | |
| assert result["quality_score"] <= 3.0 | |
| assert result["grade"] in ("D", "F") | |