File size: 3,304 Bytes
2b50d6d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
import numpy as np
import os
import logging
import soundfile as sf
import librosa
import traceback
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
def extract_features(file_path):
"""Extract audio features from a file."""
try:
logger.info(f"Starting feature extraction for: {file_path}")
# Verify file exists
if not os.path.exists(file_path):
logger.error(f"File does not exist: {file_path}")
return None
# Verify file format
try:
with sf.SoundFile(file_path) as sf_file:
logger.info(f"Audio file info: {sf_file.samplerate}Hz, {sf_file.channels} channels")
except Exception as e:
logger.error(f"Error reading audio file with soundfile: {str(e)}\n{traceback.format_exc()}")
return None
# Load audio file with error handling
try:
logger.info("Loading audio file...")
y, sr = librosa.load(file_path, duration=30, sr=None)
if len(y) == 0:
logger.error("Audio file is empty")
return None
logger.info(f"Successfully loaded audio: {len(y)} samples, {sr}Hz sample rate")
except Exception as e:
logger.error(f"Error loading audio: {str(e)}\n{traceback.format_exc()}")
return None
# Ensure minimum duration
duration = len(y) / sr
logger.info(f"Audio duration: {duration:.2f} seconds")
if duration < 1.0:
logger.error("Audio file is too short (less than 1 second)")
return None
features_dict = {}
try:
# 1. MFCC (13 features x 2 = 26)
logger.info("Extracting MFCC features...")
mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13)
features_dict['mfccs_mean'] = np.mean(mfccs, axis=1)
features_dict['mfccs_var'] = np.var(mfccs, axis=1)
logger.info(f"MFCC features shape: {mfccs.shape}")
except Exception as e:
logger.error(f"Error extracting MFCC: {str(e)}\n{traceback.format_exc()}")
return None
try:
# 2. Chroma Features
logger.info("Extracting chroma features...")
chroma = librosa.feature.chroma_stft(y=y, sr=sr)
features_dict['chroma'] = np.mean(chroma, axis=1)
logger.info(f"Chroma features shape: {chroma.shape}")
except Exception as e:
logger.error(f"Error extracting chroma features: {str(e)}\n{traceback.format_exc()}")
return None
# Combine all features
try:
logger.info("Combining features...")
features = np.concatenate([
features_dict['mfccs_mean'],
features_dict['mfccs_var'],
features_dict['chroma']
])
logger.info(f"Final feature vector shape: {features.shape}")
return features
except Exception as e:
logger.error(f"Error combining features: {str(e)}\n{traceback.format_exc()}")
return None
except Exception as e:
logger.error(f"Unexpected error in feature extraction: {str(e)}\n{traceback.format_exc()}")
return None
|