import pytest import numpy as np from fastapi.testclient import TestClient from app.main import app from app.core.ai_dsp_engine import AIDSPEngine from app.core.python_tools_engine import PythonToolsEngine client = TestClient(app) def test_find_exact_zero_crossing(): # Create sine wave audio signal: 441 Hz at 44100 Hz sample rate (100 samples per cycle) sr = 44100 t = np.linspace(0, 1.0, sr, endpoint=False) y = np.sin(2 * np.pi * 441 * t) # Target time = 0.052 seconds target_time = 0.052 z_time = AIDSPEngine.find_exact_zero_crossing(y, sr, target_time, window_ms=50.0) # Verify zero crossing condition: y[sample] * y[sample+1] <= 0 sample_idx = int(z_time * sr) if sample_idx < len(y) - 1: assert y[sample_idx] * y[sample_idx + 1] <= 0 or abs(y[sample_idx]) < 1e-3 def test_scan_best_loop_regions(): sr = 44100 t = np.linspace(0, 5.0, sr * 5, endpoint=False) y = np.sin(2 * np.pi * 440 * t) loops = AIDSPEngine.scan_best_loop_regions(y, sr, min_duration=2.0, max_duration=4.0) assert len(loops) > 0 assert "start_time" in loops[0] assert "end_time" in loops[0] assert loops[0]["end_time"] > loops[0]["start_time"] def test_slice_and_copy_with_zero_crossing(): sr = 44100 t = np.linspace(0, 4.0, sr * 4, endpoint=False) y = np.sin(2 * np.pi * 440 * t) sliced, z_start, z_end = AIDSPEngine.slice_and_copy_with_zero_crossing(y, sr, 1.0, 3.0) assert len(sliced) > 0 assert z_end > z_start def test_python_tools_engine(): sr = 44100 y = np.array([0.1, -0.5, 0.8, -0.2], dtype=np.float32) # 1. Normalize norm = PythonToolsEngine.normalize_peak(y, target_db=0.0) assert pytest.approx(np.max(np.abs(norm)), rel=1e-3) == 1.0 # 2. Phase Invert inv = PythonToolsEngine.invert_phase(y) assert np.allclose(inv, -y) # 3. Swap Channels stereo = np.array([[0.1, 0.2], [0.8, 0.9]]) swapped = PythonToolsEngine.swap_channels(stereo) assert np.allclose(swapped[0], stereo[1]) # 4. Synth Wave Generator sine = PythonToolsEngine.generate_synth_wave("sine", 440.0, 1.0, sr) assert len(sine) == sr def test_api_ai_scan(): res = client.post('/api/v1/audio/ai-scan', json={ "track_id": "1", "min_loop_duration": 2.0, "max_loop_duration": 6.0 }) assert res.status_code == 200 data = res.json() assert data["success"] is True assert len(data["suggested_loops"]) > 0 def test_api_ai_cut(): res = client.post('/api/v1/audio/ai-cut', json={ "source_track_id": "1", "selection_start": 1.0, "selection_end": 3.0 }) assert res.status_code == 200 data = res.json() assert data["success"] is True assert "aligned_start" in data assert "aligned_end" in data def test_api_user_ai_config(): # GET res_get = client.get('/api/v1/user/config/ai') assert res_get.status_code == 200 providers = res_get.json()["providers"] assert len(providers) > 0 # POST providers[0]["api_key"] = "test-sk-key-123" res_post = client.post('/api/v1/user/config/ai', json={"providers": providers}) assert res_post.status_code == 200 assert res_post.json()["success"] is True