File size: 2,438 Bytes
ca78147
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import io
import wave

import numpy as np
import pytest

from server.audio import (
    AudioValidationError,
    normalize_to_mono_16k,
    validate_reference_clip,
    write_wav_bytes,
)


def _make_wav_bytes(samples: np.ndarray, sample_rate: int, channels: int = 1) -> bytes:
    buf = io.BytesIO()
    with wave.open(buf, "wb") as w:
        w.setnchannels(channels)
        w.setsampwidth(2)
        w.setframerate(sample_rate)
        pcm = (samples * 32767).clip(-32768, 32767).astype(np.int16)
        if channels > 1:
            pcm = np.repeat(pcm[:, None], channels, axis=1).flatten()
        w.writeframes(pcm.tobytes())
    return buf.getvalue()


def test_write_wav_bytes_roundtrip():
    samples = np.sin(np.linspace(0, 6.28, 24000)).astype(np.float32)
    wav_bytes = write_wav_bytes(samples, sample_rate=24000)
    assert wav_bytes[:4] == b"RIFF"
    with wave.open(io.BytesIO(wav_bytes)) as w:
        assert w.getnchannels() == 1
        assert w.getframerate() == 24000


def test_validate_accepts_valid_clip():
    samples = np.zeros(48000, dtype=np.float32)  # 2s at 24kHz
    wav = _make_wav_bytes(samples, 24000)
    info = validate_reference_clip(wav)
    assert info.duration_s == pytest.approx(2.0, rel=1e-3)
    assert info.sample_rate == 24000


def test_validate_rejects_too_short():
    samples = np.zeros(2400, dtype=np.float32)  # 0.1s
    wav = _make_wav_bytes(samples, 24000)
    with pytest.raises(AudioValidationError, match="too short"):
        validate_reference_clip(wav)


def test_validate_rejects_too_long():
    samples = np.zeros(24000 * 70, dtype=np.float32)  # 70s
    wav = _make_wav_bytes(samples, 24000)
    with pytest.raises(AudioValidationError, match="too long"):
        validate_reference_clip(wav)


def test_validate_rejects_low_sample_rate():
    samples = np.zeros(8000, dtype=np.float32)  # 1s at 8kHz
    wav = _make_wav_bytes(samples, 8000)
    with pytest.raises(AudioValidationError, match="sample rate"):
        validate_reference_clip(wav)


def test_validate_rejects_non_wav_bytes():
    with pytest.raises(AudioValidationError, match="format"):
        validate_reference_clip(b"not a wav")


def test_normalize_downmixes_stereo_and_resamples():
    samples = np.zeros((48000, 2), dtype=np.float32)  # 1s stereo at 48kHz
    out, sr = normalize_to_mono_16k(samples, original_sr=48000)
    assert out.ndim == 1
    assert sr == 16000
    assert out.shape[0] == 16000