-
Notifications
You must be signed in to change notification settings - Fork 0
/
AudioFeatures.py
115 lines (90 loc) · 4.1 KB
/
AudioFeatures.py
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import os
import numpy as np
import librosa
from tqdm import tqdm
import sklearn.preprocessing as preprocessing
class AudioFeatures:
"""
Compute stft of audio file inside the directory ( <path> ) passed as parameter (recursive).
Put the stfts in in a sub folder inside <path> named <featType>-<n_fft>: all file in the same folder!!!
"""
def __init__(self, feature='stft', n_fft=2048, win_len=1024, hop=1024, path='samples', extension='.wav', channels=20, s_rate=None, free_disk=False, norm=False):
self.n_fft = n_fft
self.feature = feature
self.win_len = win_len
self.hop = hop
self.path = path
self.channels = channels
self.extension = extension
self.s_rate = s_rate
self.free_disk = free_disk
self.normalize = norm
def __str__(self):
values = [
"Settings",
"Feature: " + str(self.feature),
"FFT Points: " + str(self.n_fft),
"win_len: " + str(self.win_len),
"hop: " + str(self.hop),
"path: " + str(self.path),
"extension: " + str(self.extension)
]
return values
def scan_folder(self):
samples = []
print('Scanning path {}'.format(os.path.join('./', self.path)))
if not os.path.isdir('./' + self.path):
print("This is not a directory!")
else:
for root, dirnames, filenames in os.walk('./' + self.path):
for file in filenames:
ext = os.path.splitext(file)[-1].lower()
if ext == self.extension:
samples.append(os.path.join(root, file))
if len(samples) == 0:
print("NO FILES FOUND!")
else:
print("I've found " + str(len(samples)) + " files")
return samples
def feat_extract(self):
samples_list = AudioFeatures.scan_folder(self)
feat_fold_name = os.path.join(self.path, self.feature + "-" + str(self.n_fft))
if not os.path.isdir(feat_fold_name):
os.makedirs(feat_fold_name)
for filename in tqdm(samples_list):
feat_name = os.path.basename(filename)[0:-4] + ".npy"
print("Extracting feature " + self.feature + " from file: " + filename)
if os.path.isfile(os.path.join(feat_fold_name, feat_name)):
print("This file exists. Skipping!")
else:
audio, sample_rate = librosa.core.load(filename, sr=self.s_rate, dtype=np.float32) # stereo sound to mono
if self.normalize:
scaler = preprocessing.MinMaxScaler(feature_range=(-1, 1))
audio = scaler.fit_transform(audio)
if self.feature == 'stft':
y = librosa.core.stft(y=audio, n_fft=self.n_fft, hop_length=self.hop)
np.save(os.path.join(feat_fold_name, feat_name), y)
if self.feature == 'mfcc':
y = np.abs(librosa.feature.mfcc(y=audio, sr=sample_rate, hop_length=self.hop, n_fft=self.n_fft, n_mfcc=self.channels))
np.save(os.path.join(feat_fold_name, feat_name), y)
if self.free_disk:
try:
os.remove(filename)
print('file {0} removed'.format(filename))
except Exception as e:
print('failed to remove file {0}'.format(filename))
print(e)
pass
def feat_extract_from_npy(self):
feat_fold_name = os.path.join(os.path.splitext(self.path)[0], self.feature + "-" + str(self.n_fft))
if not os.path.isdir(feat_fold_name):
os.makedirs(feat_fold_name)
data = np.load(self.path)
feat_name = 000
print ("\nThis file contains " + str(len(data)) + " sequences. Extracting!")
for note in tqdm(data):
audio = note[0]
if self.feature == 'stft':
y = librosa.core.stft(y=audio, n_fft=self.n_fft, hop_length=self.hop)
np.save(os.path.join(feat_fold_name, str(feat_name)), y)
feat_name += 1