File size: 1,922 Bytes
24e7fa4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import soundfile as sf
import numpy as np
import soxr

def resample(samples: np.ndarray, orig_sr: int, target_sr: int) -> np.ndarray:
    """
    Resamples a mono float array to target_sr with soxr (anti-aliased, HQ).
    Returns the input unchanged when the rates already match.
    """
    if orig_sr == target_sr:
        return samples
    return soxr.resample(samples, orig_sr, target_sr, quality="HQ").astype(np.float32)

def condition_audio(samples: np.ndarray, sample_rate: int = 16000, pad_s: float = 0.2,
                    target_peak: float = 0.9, max_gain: float = 10.0) -> np.ndarray:
    """
    Prepares a mono clip for the model: removes DC offset, scales the peak to
    target_peak (gain capped at max_gain so near-silence is not blown up), and
    pads pad_s seconds of zeros at both ends. An all-zero clip skips scaling.
    Returns float32, 1-D.
    """
    x = np.asarray(samples, dtype=np.float32).reshape(-1)
    if x.size:
        x = x - np.mean(x, dtype=np.float32)
        peak = float(np.max(np.abs(x)))
        if peak > 0.0:
            x = x * min(target_peak / peak, max_gain)
    pad = np.zeros(int(round(pad_s * sample_rate)), dtype=np.float32)
    return np.concatenate([pad, x.astype(np.float32), pad])

def load_and_resample(file_path: str, target_sr: int = 16000) -> tuple[np.ndarray, float]:
    """
    Loads an audio file, converts stereo to mono if needed,
    and resamples to target_sr using soxr if required.
    Returns:
        samples: np.ndarray (float32, 1D array)
        duration_s: float
    """
    data, sr = sf.read(file_path, dtype="float32")
    
    # If multi-channel, average to mono
    if data.ndim > 1:
        data = np.mean(data, axis=1)
        
    # Resample if sample rate differs
    if sr != target_sr:
        data = resample(data, sr, target_sr)
        sr = target_sr
        
    duration_s = len(data) / float(sr)
    return data, duration_s