In [1]:
import os
In [2]:
import librosa
In [3]:
import mir_eval
In [4]:
from collections import OrderedDict
In [5]:
import pandas as pd
import numpy as np
np.set_printoptions(precision=3)
pd.set_option('precision', 4, "display.max_rows", 999)
In [6]:
def make_onset_corpus(onset_path):
# Beat files
audio = librosa.util.find_files(onset_path, ext='wav')
annotations = [af.replace('.wav', '.onsets') for af in audio]
data = []
for aud, ann in zip(audio, annotations):
if os.path.exists(aud) and os.path.exists(ann):
data.append((aud, ann))
return pd.DataFrame(data=data, columns=['audio', 'annotation'])
In [7]:
def make_output_path(base, outpath):
root = os.path.splitext(base)[0]
output = os.path.join(outpath, os.path.extsep.join([root, 'json']))
return output
In [27]:
def analyze(dframe, outpath='/home/bmcfee/git/librosa_parameters/data/onset'):
index = dframe.index[0]
base = os.path.basename(dframe['audio'][index])
outfile = make_output_path(base, outpath)
if os.path.exists(outfile):
print 'Cached {}'.format(base)
data = pd.read_json(outfile, orient='records')
return data
else:
print 'Processing {}'.format(base)
# Load the truth
ref_times = np.sort(pd.read_table(dframe['annotation'][index], header=None, sep='\s+')[0].values)
# Load the audio
y, sr = librosa.load(dframe['audio'][index])
# Construct the output container
results = []
hop_length = 512
effective_sr = sr // hop_length
# Onset strength parameters
for fmax in [8000, 11025]:
for n_mels in [32, 64, 128]:
S = librosa.feature.melspectrogram(y=y, hop_length=hop_length, sr=sr, fmax=fmax, n_mels=n_mels)
S = librosa.logamplitude(S)
for aggregate in [np.mean, np.median]:
# Compute the onset detection function
oenv = librosa.onset.onset_strength(S=S,
sr=sr,
hop_length=hop_length,
aggregate=aggregate)
for delta in [0.0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10]:
onsets = librosa.onset.onset_detect(onset_envelope=oenv, sr=sr,
delta=delta, hop_length=hop_length)
params = {'aggregate': aggregate.__name__,
'fmax': fmax,
'n_mels': n_mels,
'delta': delta,}
est_times = librosa.frames_to_time(onsets, sr=sr, hop_length=hop_length)
scores = mir_eval.onset.evaluate(ref_times, est_times)
cont = OrderedDict(index=index)
cont.update(params)
cont.update(scores)
results.append(cont)
# Blow away the cache
#librosa.cache.clear()
data = pd.DataFrame.from_dict(results, orient='columns')
data.to_json(outfile, orient='records')
return data
In [28]:
def analyze_corpus(corpus):
results = None
for idx in corpus.index:
new_results = analyze(corpus.loc[[idx]])
if results is None:
results = new_results
else:
results = pd.concat([results, new_results])
return results
In [29]:
from joblib import Parallel, delayed
In [30]:
def p_analyze_corpus(corpus, n_jobs=3):
results = None
dfunc = delayed(analyze)
results = Parallel(n_jobs=n_jobs, verbose=10)(dfunc(corpus.loc[[idx]])
for idx in corpus.index)
return pd.concat(results)
In [31]:
onset_data = make_onset_corpus('/home/bmcfee/data/onsets/clean_data/')
In [32]:
onset_results = p_analyze_corpus(onset_data)
In [33]:
onset_results.to_json('/home/bmcfee/git/librosa_parameters/onset_results.json', orient='records')
In [34]:
onset_results = pd.read_json('/home/bmcfee/git/librosa_parameters/onset_results.json', orient='records')
In [35]:
onset_scores = onset_results.groupby(['aggregate', 'fmax', 'n_mels', 'delta']).mean()
In [36]:
onset_scores['F-measure'].argmax()
Out[36]:
In [37]:
best_f = onset_scores['F-measure'].argmax()
In [38]:
onset_scores.loc[best_f]
Out[38]:
In [39]:
onset_scores
Out[39]:
In [62]:
# Previous configuration
onset_scores.loc[(u'mean', 11025, 128, 0.05)]
Out[62]:
In [64]:
best_f
Out[64]:
In [69]:
onset_scores.loc[(u'mean', 8000, 128, 0.07)]
Out[69]: