Spaces:
Sleeping
Sleeping
Download audio_processing.py from Woodiee/URDU-EMOTION-API: direct link, hf CLI and curl.
- Browser
- Download file 2.73 kB
-
https://huggingface.co/spaces/Woodiee/URDU-EMOTION-API/resolve/main/audio_processing.py
- Command line
-
hf download hf://spaces/Woodiee/URDU-EMOTION-API/audio_processing.py
-
curl -L -o audio_processing.py https://huggingface.co/spaces/Woodiee/URDU-EMOTION-API/resolve/main/audio_processing.py
2.73 kB
| """ | |
| Audio preprocessing and feature extraction pipeline. | |
| Mirrors the exact training-time pipeline to ensure consistent predictions. | |
| """ | |
| import numpy as np | |
| import librosa | |
| import noisereduce as nr | |
| # ββ Feature extraction config (must match training exactly) ββββββββββββββ | |
| TARGET_SR = 22050 | |
| N_MFCC = 20 | |
| HOP_LENGTH = 512 | |
| TARGET_DURATION = 3.0 | |
| MAX_FRAMES = int(np.ceil(TARGET_SR * TARGET_DURATION / HOP_LENGTH)) | |
| def preprocess_audio(y: np.ndarray, sr: int) -> np.ndarray: | |
| """Silence removal, peak normalisation, and noise reduction.""" | |
| # Remove silence | |
| intervals = librosa.effects.split(y, top_db=20) | |
| if len(intervals) > 0: | |
| y = np.concatenate([y[start:end] for start, end in intervals]) | |
| # Peak normalisation | |
| peak = np.max(np.abs(y)) | |
| if peak > 0: | |
| y = y / peak | |
| # Noise reduction | |
| try: | |
| y = nr.reduce_noise(y=y, sr=sr, prop_decrease=0.8) | |
| except Exception: | |
| pass | |
| return y | |
| def extract_and_scale_features(file_path: str, scaler) -> np.ndarray: | |
| """ | |
| Extract MFCC + delta + delta-delta + spectral contrast features, | |
| pad/truncate to MAX_FRAMES, and scale using the saved training scaler. | |
| Returns a float32 array of shape (MAX_FRAMES, 80). | |
| """ | |
| y, sr = librosa.load(file_path, sr=TARGET_SR, mono=True) | |
| y = preprocess_audio(y, sr) | |
| # MFCCs + derivatives | |
| mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=N_MFCC, hop_length=HOP_LENGTH) | |
| delta1 = librosa.feature.delta(mfcc) | |
| delta2 = librosa.feature.delta(mfcc, order=2) | |
| # Spectral contrast (7 bands β pad/trim to N_MFCC rows) | |
| spec_contrast = librosa.feature.spectral_contrast( | |
| y=y, sr=sr, hop_length=HOP_LENGTH | |
| ) | |
| if spec_contrast.shape[0] < N_MFCC: | |
| spec_contrast = np.pad( | |
| spec_contrast, | |
| ((0, N_MFCC - spec_contrast.shape[0]), (0, 0)), | |
| mode="edge", | |
| ) | |
| else: | |
| spec_contrast = spec_contrast[:N_MFCC, :] | |
| # Stack β (time, features) | |
| features = np.vstack([mfcc, delta1, delta2, spec_contrast]).T | |
| # Pad or truncate to fixed length | |
| if features.shape[0] < MAX_FRAMES: | |
| pad_width = MAX_FRAMES - features.shape[0] | |
| features = np.pad( | |
| features, ((0, pad_width), (0, 0)), mode="constant", constant_values=0 | |
| ) | |
| else: | |
| features = features[:MAX_FRAMES, :] | |
| # Scale using the saved training scaler | |
| n_features = features.shape[1] | |
| features_scaled = scaler.transform(features.reshape(-1, n_features)) | |
| features_scaled = features_scaled.reshape(features.shape) | |
| return features_scaled.astype("float32") | |