105 lines
3.3 KiB
Python
105 lines
3.3 KiB
Python
import pytest
|
|
import numpy as np
|
|
import os
|
|
import app.api.v1.user_config as user_config
|
|
user_config.DATA_FILE = os.path.join(os.path.dirname(__file__), "user_configs_test.json")
|
|
|
|
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
|