-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathpreprocess.py
139 lines (101 loc) · 3.8 KB
/
preprocess.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
import os.path
import math
import shutil
import sys
import time
import librosa
import numpy
import joblib
from . import urbansound8k, features, common
# TS,PS1 and PS1 from SalomonBello2016
def augmentations(audio, sr):
ts = [ 0.81, 0.93, 1.07, 1.23]
ps = [ -2, -1, 1, 2, -3.5, -2.5, 2.5, 3.5 ]
out = {}
for stretch in ts:
name = 'ts{:.2f}'.format(stretch)
out[name] = librosa.effects.time_stretch(audio, stretch)
for shift in ps:
name = 'ps{:.2f}'.format(shift)
out[name] = librosa.effects.pitch_shift(audio, sr, shift)
return out
def compute(inp, outp, settings, force):
sr = settings['samplerate']
_lazy_y = None
def load():
nonlocal _lazy_y
if _lazy_y is None:
_lazy_y, _sr = librosa.load(inp, sr=sr)
assert _sr == sr, _sr
return _lazy_y
exists = os.path.exists(outp)
size = 0
if exists:
#print(os.stat(outp))
size = os.stat(outp).st_size
valid = exists and size > 0
if not valid or force:
start_time = time.time()
y = load()
loaded_time = time.time()
f = features.compute_mels(y, settings)
computed_time = time.time()
numpy.savez(outp, f)
saved_time = time.time()
#import pandas
#times = pandas.Series([start_time, loaded_time, computed_time, saved_time])
#print(times.diff(1))
if settings['augmentations']:
paths = [ outp.replace('.npz', '.aug{}.npz'.format(aug)) for aug in range(12) ]
exists = [ os.path.exists(p) for p in paths ]
if not all(exists) or force:
y = load()
augmented = augmentations(y, sr).values()
assert settings['augmentations'] == 12
assert len(augmented) == settings['augmentations'], len(augmented)
for aug, (augdata, path) in enumerate(zip(augmented, paths)):
f = features.compute_mels(augdata, settings)
numpy.savez(path, f)
return outp
def precompute(samples, settings, out_dir, n_jobs=8, verbose=1, force=False):
out_folder = out_dir
def job_spec(sample):
path = urbansound8k.sample_path(sample)
out_path = features.feature_path(sample, out_folder)
# ensure output folder exists
f = os.path.split(out_path)[0]
if not os.path.exists(f):
os.makedirs(f)
return path, out_path, settings, force
jobs = [joblib.delayed(compute)(*job_spec(sample)) for _, sample in samples.iterrows()]
feature_files = joblib.Parallel(n_jobs=n_jobs, verbose=verbose)(jobs)
def parse():
import argparse
parser = argparse.ArgumentParser(description='Preprocess audio into features')
common.add_arguments(parser)
a = parser.add_argument
a('--archive', dest='archive_dir', default='',
help='')
a('--jobs', type=int, default=8,
help='Number of parallel jobs')
a('--force', type=bool, default=False,
help='Always recompute features')
parsed = parser.parse_args()
return parsed
def main():
args = parse()
archive = args.archive_dir
urbansound8k.default_path = os.path.join(args.datasets_dir, 'UrbanSound8K/')
urbansound8k.maybe_download_dataset(args.datasets_dir)
data = urbansound8k.load_dataset()
settings = common.load_settings_path(args.settings_path)
settings = features.settings(settings)
features_path = os.path.join(args.features_dir, features.settings_id(settings))
common.ensure_directories(features_path)
precompute(data, settings, out_dir=features_path,
verbose=2, force=args.force, n_jobs=args.jobs)
if archive:
print('Archiving as {}.zip'.format(features_path))
shutil.make_archive(archive_path, 'zip', features_path)
if __name__ == '__main__':
main()