CNN_space / ml_features.py
shiko217's picture
refactor
c942b33 unverified
Raw
History Blame Contribute Delete
3.18 kB
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