ref: e5cc1eafadbaf49141d07daa7d7dd56140ada974
dir: /python/aubio/task/onset.py/
from aubio.task.task import task
from aubio.task.utils import *
from aubio.aubioclass import *
class taskonset(task):
def __init__(self,input,output=None,params=None):
""" open the input file and initialize arguments
parameters should be set *before* calling this method.
"""
task.__init__(self,input,params=params)
self.opick = onsetpick(self.params.bufsize,
self.params.hopsize,
self.channels,
self.myvec,
self.params.threshold,
mode=get_onset_mode(self.params.onsetmode),
dcthreshold=self.params.dcthreshold,
derivate=self.params.derivate)
self.olist = []
self.ofunc = []
self.maxofunc = 0
self.last = 0
if self.params.localmin:
self.ovalist = [0., 0., 0., 0., 0.]
def __call__(self):
task.__call__(self)
isonset,val = self.opick.do(self.myvec)
if (aubio_silence_detection(self.myvec(),self.params.silence)):
isonset=0
if self.params.storefunc:
self.ofunc.append(val)
if self.params.localmin:
if val > 0: self.ovalist.append(val)
else: self.ovalist.append(0)
self.ovalist.pop(0)
if (isonset == 1):
if self.params.localmin:
# find local minima before peak
i=len(self.ovalist)-1
while self.ovalist[i-1] < self.ovalist[i] and i > 0:
i -= 1
now = (self.frameread+1-i)
else:
now = self.frameread
# take back delay
if self.params.delay != 0.: now -= self.params.delay
if now < 0 :
now = 0
if self.params.mintol:
# prune doubled
if (now - self.last) > self.params.mintol:
self.last = now
return now, val
else:
return now, val
def fprint(self,foo):
print self.params.step*foo[0]
def eval(self,inputdata,ftru,mode='roc',vmode=''):
from aubio.txtfile import read_datafile
from aubio.onsetcompare import onset_roc, onset_diffs, onset_rocloc
ltru = read_datafile(ftru,depth=0)
lres = []
for i in range(len(inputdata)): lres.append(inputdata[i][0]*self.params.step)
if vmode=='verbose':
print "Running with mode %s" % self.params.onsetmode,
print " and threshold %f" % self.params.threshold,
print " on file", self.input
#print ltru; print lres
if mode == 'local':
l = onset_diffs(ltru,lres,self.params.tol)
mean = 0
for i in l: mean += i
if len(l): mean = "%.3f" % (mean/len(l))
else: mean = "?0"
return l, mean
elif mode == 'roc':
self.orig, self.missed, self.merged, \
self.expc, self.bad, self.doubled = \
onset_roc(ltru,lres,self.params.tol)
elif mode == 'rocloc':
self.v = {}
self.v['orig'], self.v['missed'], self.v['Tm'], \
self.v['expc'], self.v['bad'], self.v['Td'], \
self.v['l'], self.v['labs'] = \
onset_rocloc(ltru,lres,self.params.tol)
def plot(self,onsets,ofunc,wplot,oplots,nplot=False):
import Gnuplot, Gnuplot.funcutils
import aubio.txtfile
import os.path
import numarray
from aubio.onsetcompare import onset_roc
x1,y1,y1p = [],[],[]
oplot = []
if self.params.onsetmode in ('mkl','kl'): ofunc[0:10] = [0] * 10
self.lenofunc = len(ofunc)
self.maxofunc = max(ofunc)
# onset detection function
downtime = numarray.arange(len(ofunc))*self.params.step
oplot.append(Gnuplot.Data(downtime,ofunc,with='lines',title=self.params.onsetmode))
# detected onsets
if not nplot:
for i in onsets:
x1.append(i[0]*self.params.step)
y1.append(self.maxofunc)
y1p.append(-self.maxofunc)
#x1 = numarray.array(onsets)*self.params.step
#y1 = self.maxofunc*numarray.ones(len(onsets))
if x1:
oplot.append(Gnuplot.Data(x1,y1,with='impulses'))
wplot.append(Gnuplot.Data(x1,y1p,with='impulses'))
oplots.append((oplot,self.params.onsetmode,self.maxofunc))
# check if ground truth datafile exists
datafile = self.input.replace('.wav','.txt')
if datafile == self.input: datafile = ""
if not os.path.isfile(datafile):
self.title = "" #"(no ground truth)"
else:
t_onsets = aubio.txtfile.read_datafile(datafile)
x2 = numarray.array(t_onsets).resize(len(t_onsets))
y2 = self.maxofunc*numarray.ones(len(t_onsets))
wplot.append(Gnuplot.Data(x2,y2,with='impulses'))
tol = 0.050
orig, missed, merged, expc, bad, doubled = \
onset_roc(x2,x1,tol)
self.title = "GD %2.3f%% FP %2.3f%%" % \
((100*float(orig-missed-merged)/(orig)),
(100*float(bad+doubled)/(orig)))
def plotplot(self,wplot,oplots,outplot=None,extension=None,xsize=1.,ysize=1.,spectro=False):
from aubio.gnuplot import gnuplot_create, audio_to_array, make_audio_plot, audio_to_spec
import re
# prepare the plot
g = gnuplot_create(outplot=outplot, extension=extension)
g('set title \'%s\'' % (re.sub('.*/','',self.input)))
if spectro:
g('set size %f,%f' % (xsize,1.3*ysize) )
else:
g('set size %f,%f' % (xsize,ysize) )
g('set multiplot')
# hack to align left axis
g('set lmargin 3')
g('set rmargin 6')
if spectro:
import Gnuplot
minf = 50
maxf = 500
data,time,freq = audio_to_spec(self.input,minf=minf,maxf=maxf)
g('set size %f,%f' % (1.24*xsize , 0.34*ysize) )
g('set origin %f,%f' % (-0.12,0.65*ysize))
g('set xrange [0.:%f]' % time[-1])
g('set yrange [%f:%f]' % (minf,maxf))
g('set pm3d map')
g('unset colorbox')
g('set lmargin 0')
g('set rmargin 0')
g('set tmargin 0')
g('set palette rgbformulae -25,-24,-32')
g.xlabel('time (s)',offset=(0,1.))
g.ylabel('freq (Hz)')
g('set origin 0,%f' % (1.0*ysize) )
g('set format x "%1.1f"')
#if log:
# g('set yrange [%f:%f]' % (max(10,minf),maxf))
# g('set log y')
g.splot(Gnuplot.GridData(data,time,freq, binary=1, title=''))
else:
# plot waveform and onsets
time,data = audio_to_array(self.input)
wplot = [make_audio_plot(time,data)] + wplot
g('set origin 0,%f' % (0.7*ysize) )
g('set size %f,%f' % (xsize,0.3*ysize))
g('set format y "%1f"')
g('set xrange [0:%f]' % max(time))
g('set yrange [-1:1]')
g('set noytics')
g('set y2tics -1,1')
g.xlabel('time (s)',offset=(0,0.7))
g.ylabel('amplitude')
g.plot(*wplot)
# default settings for next plots
g('unset title')
g('set format x ""')
g('set format y "%3e"')
g('set tmargin 0')
g.xlabel('')
N = len(oplots)
y = 0.7*ysize # the vertical proportion of the plot taken by onset functions
delta = 0.035 # the constant part of y taken by last plot label and data
for i in range(N):
# plot onset detection functions
g('set size %f,%f' % ( xsize, (y-delta)/N))
g('set origin 0,%f' % ((N-i-1)*(y-delta)/N + delta ))
g('set nokey')
g('set xrange [0:%f]' % (self.lenofunc*self.params.step))
g('set yrange [0:%f]' % (1.1*oplots[i][2]))
g('set y2tics ("0" 0, "%d" %d)' % (round(oplots[i][2]),round(oplots[i][2])))
g.ylabel(oplots[i][1])
if i == N-1:
g('set size %f,%f' % ( xsize, (y-delta)/N + delta ) )
g('set origin 0,0')
g.xlabel('time (s)', offset=(0,0.7))
g('set format x')
g.plot(*oplots[i][0])
g('unset multiplot')