voice-detection-api / src /features /extract_dsp.py
pp22's picture
Upload folder using huggingface_hub
ec06657 verified
Raw
History Blame Contribute Delete
3.59 kB
import os
import pandas as pd
import numpy as np
import librosa
from tqdm import tqdm
import sys
# Add src to path
sys.path.append(os.path.join(os.path.dirname(__file__), '../..'))
from src.config import DATA_DIR, SAMPLE_RATE
def extract_dsp_features(file_path):
try:
y, sr = librosa.load(file_path, sr=SAMPLE_RATE)
features = {}
# 1. MFCC (Mel-frequency cepstral coefficients)
mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
features['mfcc_mean'] = np.mean(mfcc)
features['mfcc_var'] = np.var(mfcc)
# Add individual MFCC stats if needed, but mean/var aggregation is common for baselines
for i in range(1, 14):
features[f'mfcc_{i}_mean'] = np.mean(mfcc[i-1])
features[f'mfcc_{i}_var'] = np.var(mfcc[i-1])
# 2. Spectral Features
spectral_centroid = librosa.feature.spectral_centroid(y=y, sr=sr)
features['spec_cent_mean'] = np.mean(spectral_centroid)
features['spec_cent_var'] = np.var(spectral_centroid)
spectral_flatness = librosa.feature.spectral_flatness(y=y)
features['spec_flat_mean'] = np.mean(spectral_flatness)
features['spec_flat_var'] = np.var(spectral_flatness)
spectral_rolloff = librosa.feature.spectral_rolloff(y=y, sr=sr)
features['spec_roll_mean'] = np.mean(spectral_rolloff)
# 3. Energy / RMS
rms = librosa.feature.rms(y=y)
features['rms_mean'] = np.mean(rms)
features['rms_var'] = np.var(rms)
# 4. Zero Crossing Rate
zcr = librosa.feature.zero_crossing_rate(y)
features['zcr_mean'] = np.mean(zcr)
features['zcr_var'] = np.var(zcr)
# 5. Chroma
chroma = librosa.feature.chroma_stft(y=y, sr=sr)
features['chroma_mean'] = np.mean(chroma)
# 6. Pitch (using simple piptrack)
pitches, magnitudes = librosa.piptrack(y=y, sr=sr)
# Select pitches with high magnitude
pitches_filtered = pitches[magnitudes > np.median(magnitudes)]
if len(pitches_filtered) > 0:
features['pitch_mean'] = np.mean(pitches_filtered)
features['pitch_std'] = np.std(pitches_filtered)
else:
features['pitch_mean'] = 0
features['pitch_std'] = 0
return features
except Exception as e:
print(f"Error extracting features for {file_path}: {e}")
return None
def main():
master_csv = os.path.join(DATA_DIR, 'master_dataset.csv')
if not os.path.exists(master_csv):
print("Master dataset not found. Run preprocessing first.")
return
df = pd.read_csv(master_csv)
feature_list = []
print("Extracting DSP Features...")
for index, row in tqdm(df.iterrows(), total=len(df)):
file_path = row['path']
features = extract_dsp_features(file_path)
if features:
# Combine meta info with features
features['filename'] = row['filename']
features['label'] = row['label'] # Target
feature_list.append(features)
# Save Feature Dataset
feature_df = pd.DataFrame(feature_list)
output_path = os.path.join(DATA_DIR, 'features', 'dsp_features.csv')
feature_df.to_csv(output_path, index=False)
print(f"DSP Feature Extraction Complete! Saved to {output_path}")
if __name__ == "__main__":
main()