Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import librosa | |
| from scipy import stats as scipy_stats | |
| import warnings | |
| warnings.filterwarnings('ignore') | |
| # ========================================== | |
| # CONFIGURATION | |
| # ========================================== | |
| TARGET_SR = 48000 | |
| TARGET_DURATION = 10.0 | |
| TARGET_LENGTH = int(TARGET_SR * TARGET_DURATION) | |
| TRIM_TOP_DB = 20 | |
| N_MFCC = 20 | |
| # ========================================== | |
| # PREPROCESSING | |
| # ========================================== | |
| def preprocess_audio(file_path): | |
| y, sr = librosa.load(file_path, sr=TARGET_SR) | |
| # Trim silence | |
| y_trimmed, _ = librosa.effects.trim(y, top_db=TRIM_TOP_DB) | |
| if len(y_trimmed) == 0: | |
| y_trimmed = y | |
| # DC offset removal | |
| y_centered = y_trimmed - np.mean(y_trimmed) | |
| # Z-score normalization | |
| std = np.std(y_centered) | |
| if std > 1e-8: | |
| y_norm = y_centered / std | |
| else: | |
| y_norm = y_centered | |
| # Fixed length | |
| if len(y_norm) < TARGET_LENGTH: | |
| y_norm = np.pad(y_norm, (0, TARGET_LENGTH - len(y_norm)), mode='constant') | |
| else: | |
| y_norm = y_norm[:TARGET_LENGTH] | |
| return y_norm | |
| # ========================================== | |
| # FEATURE EXTRACTION | |
| # ========================================== | |
| def compute_stats(feature_array, prefix): | |
| result = {} | |
| if feature_array.ndim == 1: | |
| feature_array = feature_array.reshape(1, -1) | |
| for i in range(feature_array.shape[0]): | |
| row = feature_array[i] | |
| suffix = f"_{i}" if feature_array.shape[0] > 1 else "" | |
| result[f"{prefix}{suffix}_mean"] = np.mean(row) | |
| result[f"{prefix}{suffix}_std"] = np.std(row) | |
| result[f"{prefix}{suffix}_min"] = np.min(row) | |
| result[f"{prefix}{suffix}_max"] = np.max(row) | |
| return result | |
| def extract_ml_features(y, sr=TARGET_SR, n_mfcc=N_MFCC): | |
| features = {} | |
| # 1. MFCCs (20 × 4 = 80) | |
| mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=n_mfcc) | |
| features.update(compute_stats(mfccs, "mfcc")) | |
| # 2. Spectral Centroid (4) | |
| features.update(compute_stats(librosa.feature.spectral_centroid(y=y, sr=sr), "spectral_centroid")) | |
| # 3. Spectral Flatness (4) | |
| features.update(compute_stats(librosa.feature.spectral_flatness(y=y), "spectral_flatness")) | |
| # 4. Zero-Crossing Rate (4) | |
| features.update(compute_stats(librosa.feature.zero_crossing_rate(y), "zcr")) | |
| # 5. RMS Energy (4) | |
| features.update(compute_stats(librosa.feature.rms(y=y), "rms")) | |
| # 6. Spectral Rolloff at 85% (4) | |
| features.update(compute_stats(librosa.feature.spectral_rolloff(y=y, sr=sr, roll_percent=0.85), "spectral_rolloff")) | |
| # 7. Spectral Bandwidth (4) | |
| features.update(compute_stats(librosa.feature.spectral_bandwidth(y=y, sr=sr), "spectral_bandwidth")) | |
| # 8. Spectral Contrast (7 bands × 4 = 28) | |
| features.update(compute_stats(librosa.feature.spectral_contrast(y=y, sr=sr, n_bands=6), "spectral_contrast")) | |
| # 9. Chroma STFT (12 × 4 = 48) | |
| features.update(compute_stats(librosa.feature.chroma_stft(y=y, sr=sr), "chroma")) | |
| # 10. Spectral Kurtosis (1) | |
| S = np.abs(librosa.stft(y)) | |
| features["spectral_kurtosis"] = float(scipy_stats.kurtosis(np.mean(S, axis=1))) | |
| return features | |