diff --git a/services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py b/services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py index dc9113c..a5b4b95 100644 --- a/services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py +++ b/services/analysis-engine/src/bandscope_analysis/temporal/analyzer.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging +import warnings from pathlib import Path from typing import Any @@ -35,11 +36,17 @@ def analyze(self, audio_path: str | Path) -> TemporalFeatures: TemporalFeatures containing BPM and beat grids. """ path_str = str(audio_path) + if not Path(audio_path).exists(): + raise FileNotFoundError(f"Audio file not found: {path_str}") + logger.info(f"Loading and decoding audio: {path_str}") try: # Load audio, converting to mono and standardizing sample rate - y, sr = librosa.load(path_str, sr=TARGET_SR, mono=True) + with warnings.catch_warnings(): + warnings.simplefilter("ignore", category=DeprecationWarning) + warnings.simplefilter("ignore", category=FutureWarning) + y, sr = librosa.load(path_str, sr=TARGET_SR, mono=True) # Ensure it's a 1D float array for librosa if not isinstance(y, np.ndarray): diff --git a/services/analysis-engine/tests/test_chord_recognizer.py b/services/analysis-engine/tests/test_chord_recognizer.py index 7033e73..f9676ff 100644 --- a/services/analysis-engine/tests/test_chord_recognizer.py +++ b/services/analysis-engine/tests/test_chord_recognizer.py @@ -29,7 +29,7 @@ def test_chord_recognizer_c_major_chord() -> None: """Test chord recognition with a clear C major chord.""" recognizer = ChordRecognizer() sr = 22050 - t = np.linspace(0, 1.0, sr) + t = np.linspace(0, 3.0, sr * 3, endpoint=False) # C major: C4 (261.63Hz), E4 (329.63Hz), G4 (392.00Hz) y = ( np.sin(2 * np.pi * 261.63 * t) @@ -47,7 +47,7 @@ def test_chord_recognizer_c_major_chord() -> None: def test_chord_recognizer_hpss_exception(): """Test for test_chord_recognizer_hpss_exception.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) with patch("librosa.effects.hpss", side_effect=Exception("HPSS Error")): chords = recognizer.recognize(y, sr=22050) @@ -57,7 +57,7 @@ def test_chord_recognizer_hpss_exception(): def test_chord_recognizer_chroma_cqt_exception(): """Test for test_chord_recognizer_chroma_cqt_exception.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) with patch("librosa.feature.chroma_cqt", side_effect=Exception("CQT Error")): chords = recognizer.recognize(y, sr=22050) @@ -67,7 +67,7 @@ def test_chord_recognizer_chroma_cqt_exception(): def test_chord_recognizer_rms_exception(): """Test for test_chord_recognizer_rms_exception.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) with patch("librosa.feature.rms", side_effect=Exception("RMS Error")): chords = recognizer.recognize(y, sr=22050) @@ -77,7 +77,7 @@ def test_chord_recognizer_rms_exception(): def test_chord_recognizer_rms_padding(): """Test for test_chord_recognizer_rms_padding.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) # Mock RMS to return something shorter than chromagram def mock_rms(*args, **kwargs): @@ -91,7 +91,7 @@ def mock_rms(*args, **kwargs): def test_chord_recognizer_empty_chromagram(): """Test for test_chord_recognizer_empty_chromagram.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) # Mock chroma_cqt to return empty array with patch("librosa.feature.chroma_cqt", return_value=np.array([])): @@ -102,7 +102,7 @@ def test_chord_recognizer_empty_chromagram(): def test_chord_recognizer_rms_longer(): """Test for test_chord_recognizer_rms_longer.""" recognizer = ChordRecognizer() - y = np.random.randn(22050) + y = np.random.randn(22050 * 3) # Mock RMS to return something longer than chromagram def mock_rms(*args, **kwargs): @@ -118,7 +118,7 @@ def test_chord_recognizer_changing_chords(): """Test for test_chord_recognizer_changing_chords.""" recognizer = ChordRecognizer() sr = 22050 - t1 = np.linspace(0, 1.0, sr, endpoint=False) + t1 = np.linspace(0, 3.0, sr * 3, endpoint=False) # C major y1 = ( np.sin(2 * np.pi * 261.63 * t1) @@ -126,7 +126,7 @@ def test_chord_recognizer_changing_chords(): + np.sin(2 * np.pi * 392.00 * t1) ) / 3.0 - t2 = np.linspace(0, 1.0, sr, endpoint=False) + t2 = np.linspace(0, 3.0, sr * 3, endpoint=False) # G major: G4 (392.00Hz), B4 (493.88Hz), D5 (587.33Hz) y2 = ( np.sin(2 * np.pi * 392.00 * t2) diff --git a/services/analysis-engine/tests/test_temporal.py b/services/analysis-engine/tests/test_temporal.py index 28f9586..ed9e4f8 100644 --- a/services/analysis-engine/tests/test_temporal.py +++ b/services/analysis-engine/tests/test_temporal.py @@ -45,7 +45,7 @@ def test_temporal_analyzer_basic(dummy_audio_file: Path) -> None: def test_temporal_analyzer_file_not_found() -> None: """Test that analyzer raises appropriate error for missing files.""" analyzer = TemporalAnalyzer() - with pytest.raises(ValueError, match="Temporal analysis failed"): + with pytest.raises(FileNotFoundError, match="Audio file not found"): analyzer.analyze("nonexistent_file.wav")