File size: 3,821 Bytes
a0fcd39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184639f
a0fcd39
 
 
 
 
 
184639f
a0fcd39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
"""Tests for audio processor service."""

import pytest
import numpy as np
from backend.services.audio_processor import (
    shift_and_stretch_single,
    process_all_stems,
    mix_stems,
)
from backend.models.session import StemData


def test_pitch_shift_up_2(sample_stems):
    """Pitch shifting up 2 semitones should not crash and should return audio."""
    stems, sr = sample_stems
    for name, audio in stems.items():
        result = shift_and_stretch_single(
            audio, sr, semitones=2, tempo_ratio=1.0, stem_type=name
        )
        assert isinstance(result, np.ndarray)
        assert len(result) > 0
        # Duration should be approximately the same (no time stretch)
        assert abs(len(result) - len(audio)) / sr < 0.1  # within 100ms


def test_pitch_shift_down_4(sample_stems):
    """Pitch shifting down 4 semitones should work."""
    stems, sr = sample_stems
    audio = stems["guitar"]
    result = shift_and_stretch_single(
        audio, sr, semitones=-4, tempo_ratio=1.0, stem_type="guitar"
    )
    assert len(result) > 0


def test_time_stretch_faster(sample_stems):
    """Speeding up by 20% should produce shorter audio."""
    stems, sr = sample_stems
    audio = stems["bass"]
    result = shift_and_stretch_single(
        audio, sr, semitones=0, tempo_ratio=1.2, stem_type="bass"
    )
    expected_length = len(audio) / 1.2
    assert abs(len(result) - expected_length) / sr < 0.2  # within 200ms


def test_time_stretch_slower(sample_stems):
    """Slowing down by 20% should produce longer audio."""
    stems, sr = sample_stems
    audio = stems["bass"]
    result = shift_and_stretch_single(
        audio, sr, semitones=0, tempo_ratio=0.8, stem_type="bass"
    )
    expected_length = len(audio) / 0.8
    assert abs(len(result) - expected_length) / sr < 0.2


def test_combined_shift_and_stretch(sample_stems):
    """Combined pitch+tempo should work in single pass."""
    stems, sr = sample_stems
    audio = stems["guitar"]
    result = shift_and_stretch_single(
        audio, sr, semitones=3, tempo_ratio=1.15, stem_type="guitar"
    )
    assert len(result) > 0


def test_no_change_passthrough(sample_stems):
    """Zero semitones + 1.0 ratio should return unchanged audio."""
    stems, sr = sample_stems
    audio = stems["bass"]
    result = shift_and_stretch_single(
        audio, sr, semitones=0, tempo_ratio=1.0, stem_type="bass"
    )
    np.testing.assert_array_almost_equal(result, audio, decimal=5)


def test_process_all_stems_parallel(sample_stems):
    """Processing all stems in parallel should return all stems."""
    stems_dict, sr = sample_stems
    stem_data = {
        name: StemData(name=name, audio=audio, sample_rate=sr)
        for name, audio in stems_dict.items()
    }
    results = process_all_stems(stem_data, semitones=2, tempo_ratio=1.1)
    assert set(results.keys()) == set(stems_dict.keys())


def test_mix_stems(sample_stems):
    """Mixing stems should produce audio without clipping."""
    stems, sr = sample_stems
    mixed = mix_stems(stems, sr)
    assert np.max(np.abs(mixed)) <= 1.0
    assert len(mixed) == max(len(a) for a in stems.values())


def test_mix_stems_empty():
    """Mixing empty stems dict should return empty array."""
    mixed = mix_stems({}, sample_rate=48000)
    assert len(mixed) == 0


def test_process_all_stems_no_change(sample_stems):
    """Processing with no changes should return copies."""
    stems_dict, sr = sample_stems
    stem_data = {
        name: StemData(name=name, audio=audio, sample_rate=sr)
        for name, audio in stems_dict.items()
    }
    results = process_all_stems(stem_data, semitones=0, tempo_ratio=1.0)

    for name in stems_dict:
        np.testing.assert_array_almost_equal(
            results[name].audio, stem_data[name].audio, decimal=5
        )