import sys import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import main as pitch_main from harmonic_pipeline import analyze_harmonic_audio PROJECT_ROOT = Path(__file__).resolve().parents[2] HARMONIC_CASES = [ ( PROJECT_ROOT / "audios-testes" / "4 Acordes básicos para iniciantes! - Leve Violão (128k).mp3", "violao", (80.0, 1200.0), "Am C G D", ), ( PROJECT_ROOT / "audios-testes" / "Stand By Me - Ben E. King (Without Barre Chords) - Leve Violão (128k).mp3", "violao", (80.0, 1200.0), "G Em C D", ), ( PROJECT_ROOT / "audios-testes" / "teste_violao.mp4", "violao", (80.0, 1200.0), "F G Am Em", ), ( PROJECT_ROOT / "audios-testes" / "teste_creeg.ogg", "violao", (80.0, 1200.0), "G B C Cm", ), ( PROJECT_ROOT / "audios-testes" / "teste_teclado.mp4", "teclado", (27.5, 4200.0), "F#m A D C#sus4 C#", ), ( PROJECT_ROOT / "audios-testes" / "teclado_bia.mp4", "teclado", (27.5, 4200.0), "F# G A C# D", ), ( PROJECT_ROOT / "audios-testes" / "teclado_bia_ruido.ogg", "teclado", (27.5, 4200.0), "F# G A C# D", ), ] MELODIC_CASES = [ ( PROJECT_ROOT / "audios-testes" / "teste_sax_alto.ogg", "sax_alto", [ "A", "A", "B", "A", "D", "C#", "A", "A", "B", "A", "E", "D", "D", "F#", "F#", "A", "F#", "D", "C#", "B", "G", "G", "F#", "D", "E", "D", "D", ], ), ( PROJECT_ROOT / "audios-testes" / "sax_alto_bia.mp4", "sax_alto", ["C#", "E", "A", "G#", "F#", "E"], ), ( PROJECT_ROOT / "audios-testes" / "sax_alto_bia_ruido.ogg", "sax_alto", ["C#", "E", "A", "G#", "F#", "E"], ), ] @unittest.skipUnless( all(path.exists() for path, *_rest in HARMONIC_CASES) and all(path.exists() for path, *_rest in MELODIC_CASES), "Clips de regressao nao encontrados", ) class AudioRegressionTests(unittest.TestCase): def assert_progression_overlap( self, actual_progression: str, expected_progression: str, minimum_overlap: int = 2, ) -> None: actual_tokens = [item for item in str(actual_progression or "").split() if item] expected_tokens = [item for item in str(expected_progression or "").split() if item] overlap = len(set(actual_tokens) & set(expected_tokens)) self.assertGreaterEqual( overlap, minimum_overlap, f"sobreposicao insuficiente entre '{actual_progression}' e '{expected_progression}'", ) def test_expected_stage_progressions(self): for path, instrumento, faixa, expected in HARMONIC_CASES: with self.subTest(audio=path.name): result = analyze_harmonic_audio(str(path), instrumento, faixa) self.assertTrue(result["cifra_palco"]) self.assertTrue(result["acorde_atual"]) self.assert_progression_overlap(result["cifra_palco"], expected) def test_expected_sax_phrases(self): for path, instrumento, expected in MELODIC_CASES: with self.subTest(audio=path.name): result = pitch_main.analisar_melodico(path, instrumento) self.assertEqual(result["notas_resumo"], expected) if __name__ == "__main__": unittest.main()