voice-detection-api / app /audio_utils.py
bakshia's picture
Cleanup: Remove debug prints, improve logging, and refactor comments
476d044
Raw
History Blame Contribute Delete
2.34 kB
"""
Audio Utilities - Shared audio loading functions with MP3 support
"""
import os
from typing import Tuple
import numpy as np
import soundfile as sf
from scipy import signal
import logging
logger = logging.getLogger(__name__)
try:
import torch
TORCH_AVAILABLE = True
except ImportError:
TORCH_AVAILABLE = False
def load_audio(audio_path: str, target_sr: int = 16000) -> Tuple[np.ndarray, int]:
"""
Load audio file with MP3 support using soundfile.
Returns: Tuple of (audio_array, sample_rate)
"""
samples, sr = sf.read(audio_path, dtype='float32')
if len(samples.shape) > 1:
samples = samples.mean(axis=1)
if sr != target_sr:
samples = resample_audio(samples, sr, target_sr)
return samples, target_sr
def resample_audio(samples: np.ndarray, orig_sr: int, target_sr: int) -> np.ndarray:
"""Resample audio using scipy"""
if orig_sr == target_sr:
return samples
duration = len(samples) / orig_sr
new_length = int(duration * target_sr)
resampled = signal.resample(samples, new_length)
return resampled.astype(np.float32)
def load_audio_torch(audio_path: str, target_sr: int = 16000) -> "torch.Tensor":
"""Load audio and return as torch tensor"""
samples, sr = load_audio(audio_path, target_sr)
if TORCH_AVAILABLE:
return torch.from_numpy(samples).float()
else:
raise ImportError("PyTorch is required for load_audio_torch")
def extract_advanced_features(audio_path: str, sample_rate: int = 16000) -> dict:
"""Extract advanced features using librosa (Flux, MFCC)"""
import librosa
try:
# Load short segment for speed (max 10s)
y, sr = librosa.load(audio_path, duration=10, sr=sample_rate)
# Spectral Flux (Change in spectrum over time)
onset_env = librosa.onset.onset_strength(y=y, sr=sr)
flux = float(np.mean(onset_env))
# MFCC Variance (Timbre complexity)
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
mfcc_var = float(np.mean(np.var(mfcc, axis=1)))
return {"spectral_flux": flux, "mfcc_variance": mfcc_var}
except Exception as e:
logger.error(f"Error extracting advanced features: {e}")
return {"spectral_flux": 0.0, "mfcc_variance": 0.0}