Showing the changes to python (5 of 5 files). Show all
Unified · Split
| @@ -1,5 +1,6 @@ | ||
| 1 | 1 | Here you will find some examples of python scripts and some evaluation |
| 2 | 2 | routines. The python interface for libaubio is generated using Swig. |
| 3 | 3 | |
| 4 | −To have it working before installation, set LD_LIBRARY_PATH as: | |
| 5 | −LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib:../src/.libs | |
| 4 | +To have it working before installation, you will need to set LD_LIBRARY_PATH | |
| 5 | +# export LD_LIBRARY_PATH=../src/.libs:../ext/.libs | |
| 6 | +for instance, to run the python script from within aubio/python/. | |
| @@ -73,7 +73,7 @@ class peakpick: · 72 unmodified lines | ||
| 73 | 73 | |
| 74 | 74 | class onsetpick: |
| 75 | 75 | """ superclass for aubio_pvoc + aubio_onsetdetection + aubio_peakpicker """ |
| 76 | − def __init__(self,bufsize,hopsize,channels,myvec,threshold,mode='dual'): | |
| 76 | + def __init__(self,bufsize,hopsize,channels,myvec,threshold,mode='dual',derivate=False): | |
| 77 | 77 | self.myfft = cvec(bufsize,channels) |
| 78 | 78 | self.pv = pvoc(bufsize,hopsize,channels) |
| 79 | 79 | if mode in [complexdomain,hfc,phase,energy,specdiff] : |
| @@ -86,6 +86,8 @@ class onsetpick: · 6 unmodified lines | ||
| 86 | 86 | self.myonset2 = fvec(1,channels) |
| 87 | 87 | self.mode = mode |
| 88 | 88 | self.pp = peakpick(float(threshold)) |
| 89 | + self.derivate = derivate | |
| 90 | + self.oldval = 0. | |
| 89 | 91 | |
| 90 | 92 | def do(self,myvec): |
| 91 | 93 | self.pv.do(myvec,self.myfft) |
| @@ -93,15 +95,23 @@ class onsetpick: · 1 unmodified line | ||
| 93 | 95 | if self.mode == 'dual': |
| 94 | 96 | self.myod2.do(self.myfft,self.myonset2) |
| 95 | 97 | self.myonset.set(self.myonset.get(0,0)*self.myonset2.get(0,0),0,0) |
| 98 | + if self.derivate: | |
| 99 | + val = self.myonset.get(0,0) | |
| 100 | + dval = val - self.oldval | |
| 101 | + self.oldval = val | |
| 102 | + if dval > 0: self.myonset.set(dval,0,0) | |
| 103 | + else: self.myonset.set(0.,0,0) | |
| 96 | 104 | return self.pp.do(self.myonset),self.myonset.get(0,0) |
| 97 | 105 | |
| 98 | −def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,mode='dual',localmin=False,storefunc=False): | |
| 106 | +def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512, | |
| 107 | + mode='dual',localmin=False,storefunc=False,derivate=False): | |
| 99 | 108 | frameread = 0 |
| 100 | 109 | filei = sndfile(filein) |
| 101 | 110 | channels = filei.channels() |
| 102 | 111 | myvec = fvec(hopsize,channels) |
| 103 | 112 | readsize = filei.read(hopsize,myvec) |
| 104 | − opick = onsetpick(bufsize,hopsize,channels,myvec,threshold,mode=mode) | |
| 113 | + opick = onsetpick(bufsize,hopsize,channels,myvec,threshold, | |
| 114 | + mode=mode,derivate=derivate) | |
| 105 | 115 | mylist = list() |
| 106 | 116 | if localmin: |
| 107 | 117 | ovalist = [0., 0., 0., 0., 0.] |
| @@ -113,7 +123,8 @@ def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,mode='d · 5 unmodified lines | ||
| 113 | 123 | if (aubio_silence_detection(myvec(),silence)): |
| 114 | 124 | isonset=0 |
| 115 | 125 | if localmin: |
| 116 | − ovalist.append(val) | |
| 126 | + if val > 0: ovalist.append(val) | |
| 127 | + else: ovalist.append(0) | |
| 117 | 128 | ovalist.pop(0) |
| 118 | 129 | if storefunc: |
| 119 | 130 | ofunclist.append(val) |
| @@ -135,7 +146,7 @@ def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,mode='d · 15 unmodified lines | ||
| 135 | 146 | if storefunc: return mylist, ofunclist |
| 136 | 147 | else: return mylist |
| 137 | 148 | |
| 138 | −def cutfile(filein,slicetimes,zerothres=0.002,bufsize=1024,hopsize=512): | |
| 149 | +def cutfile(filein,slicetimes,zerothres=0.008,bufsize=1024,hopsize=512): | |
| 139 | 150 | frameread = 0 |
| 140 | 151 | readsize = hopsize |
| 141 | 152 | filei = sndfile(filein) |
| @@ -153,18 +164,18 @@ def cutfile(filein,slicetimes,zerothres=0.002,bufsize=1024,hopsize=512): · 11 unmodified lines | ||
| 153 | 164 | # write up to 1st zero crossing |
| 154 | 165 | zerocross = 0 |
| 155 | 166 | while ( abs( myvec.get(zerocross,0) ) > zerothres ): |
| 156 | − zerocross += 1 | |
| 167 | + zerocross += 1 | |
| 157 | 168 | writesize = fileo.write(zerocross,myvec) |
| 158 | 169 | fromcross = 0 |
| 159 | 170 | while (zerocross < readsize): |
| 160 | − for i in range(channels): | |
| 161 | − mycopy.set(myvec.get(zerocross,i),fromcross,i) | |
| 162 | − fromcross += 1 | |
| 163 | − zerocross += 1 | |
| 171 | + for i in range(channels): | |
| 172 | + mycopy.set(myvec.get(zerocross,i),fromcross,i) | |
| 173 | + fromcross += 1 | |
| 174 | + zerocross += 1 | |
| 164 | 175 | del fileo |
| 165 | 176 | fileo = sndfile("%s%s%f%s%s" % |
| 166 | − (filein.split(".")[0].split("/")[-1],".", | |
| 167 | − frameread*framestep,".",filein.split(".")[-1]),model=filei) | |
| 177 | + (filein.split(".")[0].split("/")[-1],".", | |
| 178 | + frameread*framestep,".",filein.split(".")[-1]),model=filei) | |
| 168 | 179 | writesize = fileo.write(fromcross,mycopy) |
| 169 | 180 | else: |
| 170 | 181 | writesize = fileo.write(readsize,myvec) |
| @@ -136,10 +136,90 @@ def plot_audio(filenames, fileout=None, start=0, end=None, noaxis=None): · 135 unmodified lines | ||
| 136 | 136 | |
| 137 | 137 | def make_audio_plot(time,data,maxpoints=10000): |
| 138 | 138 | """ create gnuplot plot from an audio file """ |
| 139 | − import numarray | |
| 140 | 139 | length = len(time) |
| 141 | 140 | downsample = length/maxpoints |
| 142 | 141 | if downsample == 0: downsample = 1 |
| 143 | − x = numarray.array(time).resize(length)[0:-1:downsample] | |
| 144 | − y = numarray.array(data).resize(length)[0:-1:downsample] | |
| 142 | + x = array(time).resize(length)[0:-1:downsample] | |
| 143 | + y = array(data).resize(length)[0:-1:downsample] | |
| 145 | 144 | return Gnuplot.Data(x,y,with='lines') |
| 145 | + | |
| 146 | + | |
| 147 | +def plot_onsets(filename, onsets, ofunc, samplerate=44100., hopsize=512, outplot=None): | |
| 148 | + import aubio.txtfile | |
| 149 | + import os.path | |
| 150 | + import numarray | |
| 151 | + from aubio.onsetcompare import onset_roc | |
| 152 | + | |
| 153 | + # onset detection function | |
| 154 | + downtime = (hopsize/samplerate)*numarray.arange(len(ofunc)) | |
| 155 | + d = Gnuplot.Data(downtime,ofunc,with='lines') | |
| 156 | + | |
| 157 | + # detected onsets | |
| 158 | + x1 = (hopsize/samplerate)*numarray.array(onsets) | |
| 159 | + y1 = max(ofunc)*numarray.ones(len(onsets)) | |
| 160 | + e = Gnuplot.Data(x1,-y1,with='impulses') | |
| 161 | + e2= Gnuplot.Data(x1,y1,with='impulses') | |
| 162 | + | |
| 163 | + # check if datafile exists truth | |
| 164 | + datafile = filename.replace('.wav','.txt') | |
| 165 | + if not os.path.isfile(datafile): | |
| 166 | + title = "truth file not found" | |
| 167 | + t = Gnuplot.Data(0,0,with='impulses') | |
| 168 | + else: | |
| 169 | + t_onsets = aubio.txtfile.read_datafile(datafile) | |
| 170 | + y2 = max(ofunc)*numarray.ones(len(t_onsets)) | |
| 171 | + x2 = numarray.array(t_onsets).resize(len(t_onsets)) | |
| 172 | + t = Gnuplot.Data(x2,y2,with='impulses') | |
| 173 | + | |
| 174 | + tol = 0.050 | |
| 175 | + | |
| 176 | + orig, missed, merged, expc, bad, doubled = \ | |
| 177 | + onset_roc(x2,x1,tol) | |
| 178 | + title = "GD %2.3f%% FP %2.3f%%" % \ | |
| 179 | + ((100*float(orig-missed-merged)/(orig)), | |
| 180 | + (100*float(bad+doubled)/(orig))) | |
| 181 | + #print orig, missed, merged, expc, bad, doubled | |
| 182 | + #print "GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)), | |
| 183 | + #print "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) , | |
| 184 | + #print "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) , | |
| 185 | + #print "FP-pruned %2.8f\t" % (100*float(bad)/(orig)) | |
| 186 | + | |
| 187 | + # audio data | |
| 188 | + time,data = audio_to_array(filename) | |
| 189 | + f = make_audio_plot(time,data) | |
| 190 | + | |
| 191 | + # prepare the plot | |
| 192 | + g = Gnuplot.Gnuplot(debug=1, persist=1) | |
| 193 | + if outplot: | |
| 194 | + extension = outplot.split('.')[-1] | |
| 195 | + if extension == 'ps': extension = 'postscript' | |
| 196 | + g('set terminal %s' % extension) | |
| 197 | + g('set output \'%s\'' % outplot) | |
| 198 | + | |
| 199 | + g('set title \'%s %s\'' % (filename,title)) | |
| 200 | + | |
| 201 | + g('set multiplot') | |
| 202 | + | |
| 203 | + # hack to align left axis | |
| 204 | + g('set lmargin 15') | |
| 205 | + | |
| 206 | + # plot waveform and onsets | |
| 207 | + g('set size 1,0.3') | |
| 208 | + g('set origin 0,0.7') | |
| 209 | + g('set xrange [0:%f]' % max(time)) | |
| 210 | + g('set yrange [-1:1]') | |
| 211 | + g.ylabel('amplitude') | |
| 212 | + g.plot(f,e,t) | |
| 213 | + | |
| 214 | + g('unset title') | |
| 215 | + | |
| 216 | + # plot onset detection function | |
| 217 | + g('set size 1,0.7') | |
| 218 | + g('set origin 0,0') | |
| 219 | + g('set xrange [0:%f]' % (hopsize/samplerate*len(ofunc))) | |
| 220 | + g('set yrange [0:%f]' % (max(ofunc)*1.01)) | |
| 221 | + g.xlabel('time') | |
| 222 | + g.ylabel('onset detection value') | |
| 223 | + g.plot(d,e2) | |
| 224 | + | |
| 225 | + g('unset multiplot') | |
| @@ -33,7 +33,7 @@ def parse_args(): · 32 unmodified lines | ||
| 33 | 33 | help="input sound file") |
| 34 | 34 | parser.add_option("-m","--mode", action="callback", |
| 35 | 35 | callback=check_mode, dest="mode", default='dual', |
| 36 | − help="onsetdetection mode [default=dual] \ | |
| 36 | + help="onset detection mode [default=dual] \ | |
| 37 | 37 | complexdomain|hfc|phase|specdiff|energy|dual") |
| 38 | 38 | parser.add_option("-B","--bufsize", |
| 39 | 39 | action="store", dest="bufsize", default=1024, |
| @@ -51,8 +51,9 @@ def parse_args(): · 11 unmodified lines | ||
| 51 | 51 | action="store", dest="mintol", default=0.048, |
| 52 | 52 | help="minimum inter onset interval [default=0.048]") |
| 53 | 53 | parser.add_option("-D","--delay", |
| 54 | − action="store", dest="delay", default=0.022, | |
| 55 | − help="number of seconds to take back [default=0.022]") | |
| 54 | + action="store", dest="delay", | |
| 55 | + help="number of seconds to take back [default=system]\ | |
| 56 | + default system delay is 2*hopsize/samplerate") | |
| 56 | 57 | parser.add_option("-L","--localmin", |
| 57 | 58 | action="store_true", dest="localmin", default=False, |
| 58 | 59 | help="use local minima after peak detection") |
| @@ -60,23 +61,23 @@ def parse_args(): · 1 unmodified line | ||
| 60 | 61 | action="store_true", dest="cut", default=False, |
| 61 | 62 | help="cut input sound file at detected labels \ |
| 62 | 63 | best used with option -L") |
| 64 | + parser.add_option("-d","--derivate", | |
| 65 | + action="store_true", dest="derivate", default=False, | |
| 66 | + help="derivate onset detection function") | |
| 63 | 67 | # to be implemented |
| 64 | − # plotting functions | |
| 65 | − parser.add_option("-d","--derivative", | |
| 66 | − action="store_true", dest="derivative", default=False, | |
| 67 | − help="NOT IMPLEMENTED derivate onset detection function") | |
| 68 | − parser.add_option("-p","--plot", | |
| 69 | − action="store_true", dest="doplot", default=False, | |
| 70 | − help="NOT IMPLEMENTED draw plot") | |
| 71 | − parser.add_option("-O","--outplot", | |
| 72 | − action="store", dest="output-plot", default=None, | |
| 73 | − help="NOT IMPLEMENTED save plot to output.{ps,png}") | |
| 74 | 68 | parser.add_option("-z","--zerocross", |
| 75 | 69 | action="store_true", dest="zerocross", default=False, |
| 76 | 70 | help="NOT IMPLEMENTED zero crossing matching") |
| 77 | 71 | parser.add_option("-b","--beat", |
| 78 | 72 | action="store_true", dest="beat", default=False, |
| 79 | 73 | help="NOT IMPLEMENTED output beat locations") |
| 74 | + # plotting functions | |
| 75 | + parser.add_option("-p","--plot", | |
| 76 | + action="store_true", dest="plot", default=False, | |
| 77 | + help="draw plot") | |
| 78 | + parser.add_option("-O","--outplot", | |
| 79 | + action="store", dest="outplot", default=None, | |
| 80 | + help="save plot to output.{ps,png}") | |
| 80 | 81 | parser.add_option("-v","--verbose", |
| 81 | 82 | action="store_true", dest="verbose", default=False, |
| 82 | 83 | help="make lots of noise [default]") |
| @@ -99,14 +100,22 @@ step = float(samplerate)/float(hopsize) · 16 unmodified lines | ||
| 99 | 100 | threshold = float(options.threshold) |
| 100 | 101 | silence = float(options.silence) |
| 101 | 102 | mintol = float(options.mintol)*step |
| 102 | −delay = float(options.delay) | |
| 103 | +# default take back system delay | |
| 104 | +if options.delay: delay = float(options.delay) | |
| 105 | +else: delay = 2./step | |
| 103 | 106 | |
| 104 | 107 | if options.beat: |
| 105 | 108 | #onsets = getbeats(filename,threshold,silence,mode=options.mode) |
| 106 | 109 | exit("not implemented yet") |
| 110 | +elif options.plot: | |
| 111 | + onsets, ofunc = getonsets(filename,threshold,silence, | |
| 112 | + mode=options.mode,localmin=options.localmin, | |
| 113 | + derivate=options.derivate, | |
| 114 | + bufsize=bufsize,hopsize=hopsize,storefunc=True) | |
| 107 | 115 | else: |
| 108 | 116 | onsets = getonsets(filename,threshold,silence, |
| 109 | 117 | mode=options.mode,localmin=options.localmin, |
| 118 | + derivate=options.derivate, | |
| 110 | 119 | bufsize=bufsize,hopsize=hopsize) |
| 111 | 120 | |
| 112 | 121 | # take back system delay |
| @@ -128,5 +137,10 @@ if mintol > 0: · 15 unmodified lines | ||
| 128 | 137 | if options.verbose: |
| 129 | 138 | for i in onsets: print "%f" % (i/step) |
| 130 | 139 | |
| 140 | +if options.plot: | |
| 141 | + from aubio.gnuplot import plot_onsets | |
| 142 | + plot_onsets(filename, onsets, ofunc, | |
| 143 | + samplerate=samplerate, hopsize=hopsize, outplot=options.outplot) | |
| 144 | + | |
| 131 | 145 | if options.cut: |
| 132 | 146 | cutfile(filename,onsets,bufsize=bufsize,hopsize=hopsize) |
| @@ -1,124 +0,0 @@ | ||
| 1 | −#! /usr/bin/python | |
| 2 | − | |
| 3 | −import sys | |
| 4 | −import numarray | |
| 5 | −import Gnuplot, Gnuplot.funcutils | |
| 6 | −from aubio.aubioclass import * | |
| 7 | −import aubio.gnuplot | |
| 8 | −import aubio.txtfile | |
| 9 | −from aubio.onsetcompare import onset_roc | |
| 10 | − | |
| 11 | − | |
| 12 | −usage = "usage: %s [options] soundfile" % sys.argv[0] | |
| 13 | − | |
| 14 | −def parse_args(): | |
| 15 | − from optparse import OptionParser | |
| 16 | − parser = OptionParser(usage=usage) | |
| 17 | − parser.add_option("-v","--verbose", | |
| 18 | − action="store_true", dest="verbose", default=False, | |
| 19 | − help="make lots of noise") | |
| 20 | − parser.add_option("-q","--quiet", | |
| 21 | − action="store_false", dest="verbose", default=True, | |
| 22 | − help="be quiet [default]") | |
| 23 | − parser.add_option("-t","--threshold", | |
| 24 | − action="store", dest="threshold", default=0.3, | |
| 25 | − help="onset detection threshold [default=0.3]") | |
| 26 | − parser.add_option("-s","--silence", | |
| 27 | − action="store", dest="silence", default=-70, | |
| 28 | − help="silence [default=-70]") | |
| 29 | − def check_mode(option, opt, value, parser): | |
| 30 | − nvalue = parser.rargs[0] | |
| 31 | − if nvalue == 'complexdomain' : setattr(parser.values, option.dest, complexdomain) | |
| 32 | − elif nvalue == 'hfc' : setattr(parser.values, option.dest, hfc) | |
| 33 | − elif nvalue == 'phase' : setattr(parser.values, option.dest, phase) | |
| 34 | − elif nvalue == 'specdiff' : setattr(parser.values, option.dest, specdiff) | |
| 35 | − elif nvalue == 'energy' : setattr(parser.values, option.dest, energy) | |
| 36 | − elif nvalue == 'dual' : setattr(parser.values, option.dest, 'dual') | |
| 37 | − parser.add_option("-m","--mode", | |
| 38 | − action="callback", callback=check_mode, dest="mode", default='dual', | |
| 39 | − help="onsetdetection mode [default=dual]") | |
| 40 | − parser.add_option("-o","--outplot", | |
| 41 | − action="store", dest="outplot", default=None, | |
| 42 | − help="be quiet [default=None]") | |
| 43 | − (options, args) = parser.parse_args() | |
| 44 | − if not len(args): | |
| 45 | − print "no file name given\n", usage | |
| 46 | − sys.exit(1) | |
| 47 | − return options, args | |
| 48 | − | |
| 49 | −options, args = parse_args() | |
| 50 | − | |
| 51 | −filename = args[0] #FIXME should move to optparse | |
| 52 | −threshold = float(options.threshold) | |
| 53 | −silence = float(options.silence) | |
| 54 | − | |
| 55 | −print options.mode | |
| 56 | −onsets, ofunc = getonsetsfunc(filename,threshold,silence,mode=options.mode) | |
| 57 | − | |
| 58 | −g = Gnuplot.Gnuplot(debug=1, persist=1) | |
| 59 | − | |
| 60 | −if options.outplot: | |
| 61 | − extension = options.outplot.split('.')[-1] | |
| 62 | − if extension == 'ps': extension = 'postscript' | |
| 63 | − g('set terminal %s' % extension) | |
| 64 | − g('set output \'%s\'' % options.outplot) | |
| 65 | − | |
| 66 | −g('set multiplot') | |
| 67 | − | |
| 68 | −# onset detection function | |
| 69 | −downtime = (512./44100.)*numarray.arange(len(ofunc)) | |
| 70 | −d = Gnuplot.Data(downtime,ofunc,with='lines') | |
| 71 | − | |
| 72 | −# detected onsets | |
| 73 | −x1 = (512./44100.)*numarray.array(onsets) | |
| 74 | −y1 = max(ofunc)*numarray.ones(len(onsets)) | |
| 75 | −e = Gnuplot.Data(x1,-y1,with='impulses') | |
| 76 | −e2= Gnuplot.Data(x1,y1,with='impulses') | |
| 77 | − | |
| 78 | −# truth | |
| 79 | −import os.path | |
| 80 | −datafile = filename.replace('.wav','.txt') | |
| 81 | −if not os.path.isfile(datafile): | |
| 82 | − print "truth file not found" | |
| 83 | − t = Gnuplot.Data(0,0,with='impulses') | |
| 84 | −else: | |
| 85 | − t_onsets = aubio.txtfile.read_datafile(datafile) | |
| 86 | − y2 = max(ofunc)*numarray.ones(len(t_onsets)) | |
| 87 | − x2 = numarray.array(t_onsets).resize(len(t_onsets)) | |
| 88 | − t = Gnuplot.Data(x2,y2,with='impulses') | |
| 89 | − | |
| 90 | − eps = 4*0.012 | |
| 91 | − | |
| 92 | − orig, missed, merged, expc, bad, doubled = \ | |
| 93 | − onset_roc(x2,x1,eps) | |
| 94 | − print orig, missed, merged, expc, bad, doubled | |
| 95 | − print "GD %2.8f\t" % (100*float(orig-missed-merged)/(orig)), | |
| 96 | − print "FP %2.8f\t" % (100*float(bad+doubled)/(orig)) , | |
| 97 | − print "GD-merged %2.8f\t" % (100*float(orig-missed)/(orig)) , | |
| 98 | − print "FP-pruned %2.8f\t" % (100*float(bad)/(orig)) | |
| 99 | − | |
| 100 | −# audio data | |
| 101 | −time,data = aubio.gnuplot.audio_to_array(filename) | |
| 102 | −f = aubio.gnuplot.make_audio_plot(time,data) | |
| 103 | − | |
| 104 | −# hack to align left axis | |
| 105 | −g('set lmargin 15') | |
| 106 | − | |
| 107 | −g('set size 1,0.3') | |
| 108 | −g('set origin 0,0.7') | |
| 109 | −g('set xrange [0:%f]' % max(time)) | |
| 110 | −g('set yrange [-1:1]') | |
| 111 | −g.ylabel('amplitude') | |
| 112 | −g.plot(f,e,t) | |
| 113 | − | |
| 114 | −g('set size 1,0.7') | |
| 115 | −g('set origin 0,0') | |
| 116 | −g('set xrange [0:%f]' % (512./44100.*len(ofunc))) | |
| 117 | −g('set yrange [0:%f]' % (max(ofunc)*1.01)) | |
| 118 | −g.xlabel('time') | |
| 119 | −g.ylabel('onset detection value') | |
| 120 | − | |
| 121 | −g.plot(d,e2) | |
| 122 | − | |
| 123 | −g('unset multiplot') | |
| 124 | − | |