"""Tests for the active-section / intro-skip detector.""" from __future__ import annotations import numpy as np import pytest from backend.features import ANALYSIS_WINDOW_S, detect_active_section SR = 22050 def test_short_track_returns_full_range(): y = np.random.randn(int(60 * SR)).astype(np.float32) * 0.5 start, end = detect_active_section(y, SR, target_s=ANALYSIS_WINDOW_S) assert start == 0.0 assert abs(end - 60.0) < 1.0 def test_quiet_intro_is_skipped(): """Intro at 5% amplitude, loud section at 80% — detector must land on the loud part.""" intro = np.random.randn(int(120 * SR)).astype(np.float32) * 0.05 loud = np.random.randn(int(90 * SR)).astype(np.float32) * 0.8 outro = np.random.randn(int(60 * SR)).astype(np.float32) * 0.1 y = np.concatenate([intro, loud, outro]) start, end = detect_active_section(y, SR, target_s=90.0) # Window should overlap heavily with the loud section. assert 100 <= start <= 140, f"start {start} should be near 120s" assert end - start == pytest.approx(90.0, abs=1.0) def test_uniform_energy_returns_a_valid_window(): """No clear energy gradient — any window of the target size is acceptable as long as it sits inside the track and has the right length.""" y = (np.random.randn(int(200 * SR)) * 0.3).astype(np.float32) start, end = detect_active_section(y, SR, target_s=90.0) assert 0.0 <= start <= 200.0 - 90.0 assert end - start == pytest.approx(90.0, abs=1.0) def test_loud_section_at_end(): quiet = np.random.randn(int(180 * SR)).astype(np.float32) * 0.05 loud = np.random.randn(int(90 * SR)).astype(np.float32) * 0.9 y = np.concatenate([quiet, loud]) start, end = detect_active_section(y, SR, target_s=90.0) assert start >= 170, f"expected window near end (~180s), got {start}" def test_zero_signal_returns_first_window(): """Pathological all-zero input should not crash.""" y = np.zeros(int(200 * SR), dtype=np.float32) start, end = detect_active_section(y, SR, target_s=90.0) assert start == 0.0 assert end == pytest.approx(90.0, abs=1.0) def test_target_longer_than_track_returns_full(): y = np.random.randn(int(45 * SR)).astype(np.float32) * 0.4 start, end = detect_active_section(y, SR, target_s=90.0) assert start == 0.0 assert end == pytest.approx(45.0, abs=1.0)