ref: 80c0417c84d6f98064b7aa2ac5d9b22c496e68df
parent: 588a09fa4d36af3351c7cea81922379b904a4a34
author: Paul Brossier <piem@altern.org>
date: Mon May 30 00:44:52 EDT 2005
merged aubioplot-onsets into aubiocut, added some more options
--- a/python/README
+++ b/python/README
@@ -1,5 +1,6 @@
Here you will find some examples of python scripts and some evaluation
routines. The python interface for libaubio is generated using Swig.
-To have it working before installation, set LD_LIBRARY_PATH as:
-LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib:../src/.libs
+To have it working before installation, you will need to set LD_LIBRARY_PATH
+# export LD_LIBRARY_PATH=../src/.libs:../ext/.libs
+for instance, to run the python script from within aubio/python/.
--- a/python/aubio/aubioclass.py
+++ b/python/aubio/aubioclass.py
@@ -73,7 +73,7 @@
class onsetpick:
""" superclass for aubio_pvoc + aubio_onsetdetection + aubio_peakpicker """
- def __init__(self,bufsize,hopsize,channels,myvec,threshold,mode='dual'):
+ def __init__(self,bufsize,hopsize,channels,myvec,threshold,mode='dual',derivate=False):
self.myfft = cvec(bufsize,channels)
self.pv = pvoc(bufsize,hopsize,channels)
if mode in [complexdomain,hfc,phase,energy,specdiff] :
@@ -86,6 +86,8 @@
self.myonset2 = fvec(1,channels)
self.mode = mode
self.pp = peakpick(float(threshold))
+ self.derivate = derivate
+ self.oldval = 0.
def do(self,myvec):
self.pv.do(myvec,self.myfft)
@@ -93,15 +95,23 @@
if self.mode == 'dual':
self.myod2.do(self.myfft,self.myonset2)
self.myonset.set(self.myonset.get(0,0)*self.myonset2.get(0,0),0,0)
+ if self.derivate:
+ val = self.myonset.get(0,0)
+ dval = val - self.oldval
+ self.oldval = val
+ if dval > 0: self.myonset.set(dval,0,0)
+ else: self.myonset.set(0.,0,0)
return self.pp.do(self.myonset),self.myonset.get(0,0)
-def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,mode='dual',localmin=False,storefunc=False):
+def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,
+ mode='dual',localmin=False,storefunc=False,derivate=False):
frameread = 0
filei = sndfile(filein)
channels = filei.channels()
myvec = fvec(hopsize,channels)
readsize = filei.read(hopsize,myvec)
- opick = onsetpick(bufsize,hopsize,channels,myvec,threshold,mode=mode)
+ opick = onsetpick(bufsize,hopsize,channels,myvec,threshold,
+ mode=mode,derivate=derivate)
mylist = list()
if localmin:
ovalist = [0., 0., 0., 0., 0.]
@@ -113,7 +123,8 @@
if (aubio_silence_detection(myvec(),silence)):
isonset=0
if localmin:
- ovalist.append(val)
+ if val > 0: ovalist.append(val)
+ else: ovalist.append(0)
ovalist.pop(0)
if storefunc:
ofunclist.append(val)
@@ -135,7 +146,7 @@
if storefunc: return mylist, ofunclist
else: return mylist
-def cutfile(filein,slicetimes,zerothres=0.002,bufsize=1024,hopsize=512):
+def cutfile(filein,slicetimes,zerothres=0.008,bufsize=1024,hopsize=512):
frameread = 0
readsize = hopsize
filei = sndfile(filein)
@@ -153,18 +164,18 @@
# write up to 1st zero crossing
zerocross = 0
while ( abs( myvec.get(zerocross,0) ) > zerothres ):
- zerocross += 1
+ zerocross += 1
writesize = fileo.write(zerocross,myvec)
fromcross = 0
while (zerocross < readsize):
- for i in range(channels):
- mycopy.set(myvec.get(zerocross,i),fromcross,i)
- fromcross += 1
- zerocross += 1
+ for i in range(channels):
+ mycopy.set(myvec.get(zerocross,i),fromcross,i)
+ fromcross += 1
+ zerocross += 1
del fileo
fileo = sndfile("%s%s%f%s%s" %
- (filein.split(".")[0].split("/")[-1],".",
- frameread*framestep,".",filein.split(".")[-1]),model=filei)
+ (filein.split(".")[0].split("/")[-1],".",
+ frameread*framestep,".",filein.split(".")[-1]),model=filei)
writesize = fileo.write(fromcross,mycopy)
else:
writesize = fileo.write(readsize,myvec)
--- a/python/aubio/gnuplot.py
+++ b/python/aubio/gnuplot.py
@@ -136,10 +136,90 @@
def make_audio_plot(time,data,maxpoints=10000):
""" create gnuplot plot from an audio file """
- import numarray
length = len(time)
downsample = length/maxpoints
if downsample == 0: downsample = 1
- x = numarray.array(time).resize(length)[0:-1:downsample]
- y = numarray.array(data).resize(length)[0:-1:downsample]
+ x = array(time).resize(length)[0:-1:downsample]
+ y = array(data).resize(length)[0:-1:downsample]
return Gnuplot.Data(x,y,with='lines')
+
+
+def plot_onsets(filename, onsets, ofunc, samplerate=44100., hopsize=512, outplot=None):
+ import aubio.txtfile
+ import os.path
+ import numarray
+ from aubio.onsetcompare import onset_roc
+
+ # onset detection function
+ downtime = (hopsize/samplerate)*numarray.arange(len(ofunc))
+ d = Gnuplot.Data(downtime,ofunc,with='lines')
+
+ # detected onsets
+ x1 = (hopsize/samplerate)*numarray.array(onsets)
+ y1 = max(ofunc)*numarray.ones(len(onsets))
+ e = Gnuplot.Data(x1,-y1,with='impulses')
+ e2= Gnuplot.Data(x1,y1,with='impulses')
+
+ # check if datafile exists truth
+ datafile = filename.replace('.wav','.txt')
+ if not os.path.isfile(datafile):
+ title = "truth file not found"
+ t = Gnuplot.Data(0,0,with='impulses')
+ else:
+ t_onsets = aubio.txtfile.read_datafile(datafile)
+ y2 = max(ofunc)*numarray.ones(len(t_onsets))
+ x2 = numarray.array(t_onsets).resize(len(t_onsets))
+ t = Gnuplot.Data(x2,y2,with='impulses')
+
+ tol = 0.050
+
+ orig, missed, merged, expc, bad, doubled = \
+ onset_roc(x2,x1,tol)
+ title = "GD %2.3f%% FP %2.3f%%" % \
+ ((100*float(orig-missed-merged)/(orig)),
+ (100*float(bad+doubled)/(orig)))
+ #print orig, missed, merged, expc, bad, doubled
+ #print "GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)),
+ #print "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) ,
+ #print "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) ,
+ #print "FP-pruned %2.8f\t" % (100*float(bad)/(orig))
+
+ # audio data
+ time,data = audio_to_array(filename)
+ f = make_audio_plot(time,data)
+
+ # prepare the plot
+ g = Gnuplot.Gnuplot(debug=1, persist=1)
+ if outplot:
+ extension = outplot.split('.')[-1]
+ if extension == 'ps': extension = 'postscript'
+ g('set terminal %s' % extension)
+ g('set output \'%s\'' % outplot)
+
+ g('set title \'%s %s\'' % (filename,title))
+
+ g('set multiplot')
+
+ # hack to align left axis
+ g('set lmargin 15')
+
+ # plot waveform and onsets
+ g('set size 1,0.3')
+ g('set origin 0,0.7')
+ g('set xrange [0:%f]' % max(time))
+ g('set yrange [-1:1]')
+ g.ylabel('amplitude')
+ g.plot(f,e,t)
+
+ g('unset title')
+
+ # plot onset detection function
+ g('set size 1,0.7')
+ g('set origin 0,0')
+ g('set xrange [0:%f]' % (hopsize/samplerate*len(ofunc)))
+ g('set yrange [0:%f]' % (max(ofunc)*1.01))
+ g.xlabel('time')
+ g.ylabel('onset detection value')
+ g.plot(d,e2)
+
+ g('unset multiplot')
--- a/python/aubiocut
+++ b/python/aubiocut
@@ -33,7 +33,7 @@
help="input sound file")
parser.add_option("-m","--mode", action="callback",
callback=check_mode, dest="mode", default='dual',
- help="onsetdetection mode [default=dual] \
+ help="onset detection mode [default=dual] \
complexdomain|hfc|phase|specdiff|energy|dual")
parser.add_option("-B","--bufsize",
action="store", dest="bufsize", default=1024,
@@ -51,8 +51,9 @@
action="store", dest="mintol", default=0.048,
help="minimum inter onset interval [default=0.048]")
parser.add_option("-D","--delay",
- action="store", dest="delay", default=0.022,
- help="number of seconds to take back [default=0.022]")
+ action="store", dest="delay",
+ help="number of seconds to take back [default=system]\
+ default system delay is 2*hopsize/samplerate")
parser.add_option("-L","--localmin",
action="store_true", dest="localmin", default=False,
help="use local minima after peak detection")
@@ -60,17 +61,10 @@
action="store_true", dest="cut", default=False,
help="cut input sound file at detected labels \
best used with option -L")
+ parser.add_option("-d","--derivate",
+ action="store_true", dest="derivate", default=False,
+ help="derivate onset detection function")
# to be implemented
- # plotting functions
- parser.add_option("-d","--derivative",
- action="store_true", dest="derivative", default=False,
- help="NOT IMPLEMENTED derivate onset detection function")
- parser.add_option("-p","--plot",
- action="store_true", dest="doplot", default=False,
- help="NOT IMPLEMENTED draw plot")
- parser.add_option("-O","--outplot",
- action="store", dest="output-plot", default=None,
- help="NOT IMPLEMENTED save plot to output.{ps,png}")
parser.add_option("-z","--zerocross",
action="store_true", dest="zerocross", default=False,
help="NOT IMPLEMENTED zero crossing matching")
@@ -77,6 +71,13 @@
parser.add_option("-b","--beat",
action="store_true", dest="beat", default=False,
help="NOT IMPLEMENTED output beat locations")
+ # plotting functions
+ parser.add_option("-p","--plot",
+ action="store_true", dest="plot", default=False,
+ help="draw plot")
+ parser.add_option("-O","--outplot",
+ action="store", dest="outplot", default=None,
+ help="save plot to output.{ps,png}")
parser.add_option("-v","--verbose",
action="store_true", dest="verbose", default=False,
help="make lots of noise [default]")
@@ -99,14 +100,22 @@
threshold = float(options.threshold)
silence = float(options.silence)
mintol = float(options.mintol)*step
-delay = float(options.delay)
+# default take back system delay
+if options.delay: delay = float(options.delay)
+else: delay = 2./step
if options.beat:
#onsets = getbeats(filename,threshold,silence,mode=options.mode)
exit("not implemented yet")
+elif options.plot:
+ onsets, ofunc = getonsets(filename,threshold,silence,
+ mode=options.mode,localmin=options.localmin,
+ derivate=options.derivate,
+ bufsize=bufsize,hopsize=hopsize,storefunc=True)
else:
onsets = getonsets(filename,threshold,silence,
mode=options.mode,localmin=options.localmin,
+ derivate=options.derivate,
bufsize=bufsize,hopsize=hopsize)
# take back system delay
@@ -127,6 +136,11 @@
# print times in second
if options.verbose:
for i in onsets: print "%f" % (i/step)
+
+if options.plot:
+ from aubio.gnuplot import plot_onsets
+ plot_onsets(filename, onsets, ofunc,
+ samplerate=samplerate, hopsize=hopsize, outplot=options.outplot)
if options.cut:
cutfile(filename,onsets,bufsize=bufsize,hopsize=hopsize)
--- a/python/aubioplot-onset
+++ /dev/null
@@ -1,124 +1,0 @@
-#! /usr/bin/python
-
-import sys
-import numarray
-import Gnuplot, Gnuplot.funcutils
-from aubio.aubioclass import *
-import aubio.gnuplot
-import aubio.txtfile
-from aubio.onsetcompare import onset_roc
-
-
-usage = "usage: %s [options] soundfile" % sys.argv[0]
-
-def parse_args():
- from optparse import OptionParser
- parser = OptionParser(usage=usage)
- parser.add_option("-v","--verbose",
- action="store_true", dest="verbose", default=False,
- help="make lots of noise")
- parser.add_option("-q","--quiet",
- action="store_false", dest="verbose", default=True,
- help="be quiet [default]")
- parser.add_option("-t","--threshold",
- action="store", dest="threshold", default=0.3,
- help="onset detection threshold [default=0.3]")
- parser.add_option("-s","--silence",
- action="store", dest="silence", default=-70,
- help="silence [default=-70]")
- def check_mode(option, opt, value, parser):
- nvalue = parser.rargs[0]
- if nvalue == 'complexdomain' : setattr(parser.values, option.dest, complexdomain)
- elif nvalue == 'hfc' : setattr(parser.values, option.dest, hfc)
- elif nvalue == 'phase' : setattr(parser.values, option.dest, phase)
- elif nvalue == 'specdiff' : setattr(parser.values, option.dest, specdiff)
- elif nvalue == 'energy' : setattr(parser.values, option.dest, energy)
- elif nvalue == 'dual' : setattr(parser.values, option.dest, 'dual')
- parser.add_option("-m","--mode",
- action="callback", callback=check_mode, dest="mode", default='dual',
- help="onsetdetection mode [default=dual]")
- parser.add_option("-o","--outplot",
- action="store", dest="outplot", default=None,
- help="be quiet [default=None]")
- (options, args) = parser.parse_args()
- if not len(args):
- print "no file name given\n", usage
- sys.exit(1)
- return options, args
-
-options, args = parse_args()
-
-filename = args[0] #FIXME should move to optparse
-threshold = float(options.threshold)
-silence = float(options.silence)
-
-print options.mode
-onsets, ofunc = getonsetsfunc(filename,threshold,silence,mode=options.mode)
-
-g = Gnuplot.Gnuplot(debug=1, persist=1)
-
-if options.outplot:
- extension = options.outplot.split('.')[-1]
- if extension == 'ps': extension = 'postscript'
- g('set terminal %s' % extension)
- g('set output \'%s\'' % options.outplot)
-
-g('set multiplot')
-
-# onset detection function
-downtime = (512./44100.)*numarray.arange(len(ofunc))
-d = Gnuplot.Data(downtime,ofunc,with='lines')
-
-# detected onsets
-x1 = (512./44100.)*numarray.array(onsets)
-y1 = max(ofunc)*numarray.ones(len(onsets))
-e = Gnuplot.Data(x1,-y1,with='impulses')
-e2= Gnuplot.Data(x1,y1,with='impulses')
-
-# truth
-import os.path
-datafile = filename.replace('.wav','.txt')
-if not os.path.isfile(datafile):
- print "truth file not found"
- t = Gnuplot.Data(0,0,with='impulses')
-else:
- t_onsets = aubio.txtfile.read_datafile(datafile)
- y2 = max(ofunc)*numarray.ones(len(t_onsets))
- x2 = numarray.array(t_onsets).resize(len(t_onsets))
- t = Gnuplot.Data(x2,y2,with='impulses')
-
- eps = 4*0.012
-
- orig, missed, merged, expc, bad, doubled = \
- onset_roc(x2,x1,eps)
- print orig, missed, merged, expc, bad, doubled
- print "GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)),
- print "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) ,
- print "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) ,
- print "FP-pruned %2.8f\t" % (100*float(bad)/(orig))
-
-# audio data
-time,data = aubio.gnuplot.audio_to_array(filename)
-f = aubio.gnuplot.make_audio_plot(time,data)
-
-# hack to align left axis
-g('set lmargin 15')
-
-g('set size 1,0.3')
-g('set origin 0,0.7')
-g('set xrange [0:%f]' % max(time))
-g('set yrange [-1:1]')
-g.ylabel('amplitude')
-g.plot(f,e,t)
-
-g('set size 1,0.7')
-g('set origin 0,0')
-g('set xrange [0:%f]' % (512./44100.*len(ofunc)))
-g('set yrange [0:%f]' % (max(ofunc)*1.01))
-g.xlabel('time')
-g.ylabel('onset detection value')
-
-g.plot(d,e2)
-
-g('unset multiplot')
-