source: python/aubio/tasks.py @ 4f4a8a4

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since 4f4a8a4 was 7c9ad74, checked in by Paul Brossier <piem@altern.org>, 19 years ago

added tasks fot onset, silence and cut
added tasks fot onset, silence and cut

  • Property mode set to 100644
File size: 16.3 KB
RevLine 
[5e491b3b]1from aubioclass import * 
[0029638]2from bench.node import bench
[5e491b3b]3
[7473074]4def get_onset_mode(nvalue):
[5e491b3b]5        """ utility function to convert a string to aubio_onsetdetection_type """
[7473074]6        if   nvalue == 'complexdomain' or nvalue == 'complex' :
7                 return aubio_onset_complex
8        elif nvalue == 'hfc'           :
9                 return aubio_onset_hfc
10        elif nvalue == 'phase'         :
11                 return aubio_onset_phase
12        elif nvalue == 'specdiff'      :
13                 return aubio_onset_specdiff
14        elif nvalue == 'energy'        :
15                 return aubio_onset_energy
16        elif nvalue == 'kl'            :
17                 return aubio_onset_kl
18        elif nvalue == 'mkl'           :
19                 return aubio_onset_mkl
20        elif nvalue == 'dual'          :
21                 return 'dual'
22        else:
23                 import sys
24                 print "unknown onset detection function selected"
25                 sys.exit(1)
26
[0029638]27def get_pitch_mode(nvalue):
28        """ utility function to convert a string to aubio_pitchdetection_type """
29        if   nvalue == 'mcomb'  :
30                 return aubio_pitch_mcomb
31        elif nvalue == 'yin'    :
32                 return aubio_pitch_yin
33        elif nvalue == 'fcomb'  :
34                 return aubio_pitch_fcomb
35        elif nvalue == 'schmitt':
36                 return aubio_pitch_schmitt
37        else:
38                 import sys
39                 print "error: unknown pitch detection function selected"
40                 sys.exit(1)
41
[7473074]42def check_onset_mode(option, opt, value, parser):
43        """ wrapper function to convert a list of modes to
44                aubio_onsetdetection_type """
[5e491b3b]45        nvalues = parser.rargs[0].split(',')
46        val =  []
47        for nvalue in nvalues:
[7473074]48                val.append(get_onset_mode(nvalue))
[5e491b3b]49                setattr(parser.values, option.dest, val)
50
51def check_pitch_mode(option, opt, value, parser):
52        """ utility function to convert a string to aubio_pitchdetection_type"""
53        nvalues = parser.rargs[0].split(',')
54        val = []
55        for nvalue in nvalues:
[0029638]56                val.append(get_pitch_mode(nvalue))
[5e491b3b]57                setattr(parser.values, option.dest, val)
58
59def check_pitchm_mode(option, opt, value, parser):
60        """ utility function to convert a string to aubio_pitchdetection_mode """
61        nvalue = parser.rargs[0]
62        if   nvalue == 'freq'  :
63                 setattr(parser.values, option.dest, aubio_pitchm_freq)
64        elif nvalue == 'midi'  :
65                 setattr(parser.values, option.dest, aubio_pitchm_midi)
66        elif nvalue == 'cent'  :
67                 setattr(parser.values, option.dest, aubio_pitchm_cent)
68        elif nvalue == 'bin'   :
69                 setattr(parser.values, option.dest, aubio_pitchm_bin)
70        else:
71                 import sys
72                 print "error: unknown pitch detection output selected"
73                 sys.exit(1)
74
75
76def getonsets(filein,threshold=0.2,silence=-70.,bufsize=1024,hopsize=512,
77                mode='dual',localmin=False,storefunc=False,derivate=False):
78        frameread = 0
79        filei     = sndfile(filein)
80        channels  = filei.channels()
81        myvec     = fvec(hopsize,channels)
82        readsize  = filei.read(hopsize,myvec)
83        opick     = onsetpick(bufsize,hopsize,channels,myvec,threshold,
84                         mode=mode,derivate=derivate)
85        mylist    = list()
86        if localmin:
87                ovalist   = [0., 0., 0., 0., 0.]
88        ofunclist = []
89        while(readsize):
90                readsize = filei.read(hopsize,myvec)
91                isonset,val = opick.do(myvec)
92                if (aubio_silence_detection(myvec(),silence)):
93                        isonset=0
94                if localmin:
95                        if val > 0: ovalist.append(val)
96                        else: ovalist.append(0)
97                        ovalist.pop(0)
98                if storefunc:
99                        ofunclist.append(val)
100                if (isonset == 1):
101                        if localmin:
102                                i=len(ovalist)-1
103                                # find local minima before peak
104                                while ovalist[i-1] < ovalist[i] and i > 0:
105                                        i -= 1
106                                now = (frameread+1-i)
107                        else:
108                                now = frameread
109                        if now > 0 :
110                                mylist.append(now)
111                        else:
112                                now = 0
113                                mylist.append(now)
114                frameread += 1
115        return mylist, ofunclist
116
117def cutfile(filein,slicetimes,zerothres=0.008,bufsize=1024,hopsize=512):
118    frameread = 0
119    readsize  = hopsize
120    filei     = sndfile(filein)
121    framestep = hopsize/(filei.samplerate()+0.)
122    channels  = filei.channels()
123    newname   = "%s%s%09.5f%s%s" % (filein.split(".")[0].split("/")[-1],".",
124                frameread*framestep,".",filein.split(".")[-1])
125    fileo     = sndfile(newname,model=filei)
126    myvec     = fvec(hopsize,channels)
127    mycopy    = fvec(hopsize,channels)
128    while(readsize==hopsize):
129        readsize = filei.read(hopsize,myvec)
130        # write to current file
131        if len(slicetimes) and frameread >= slicetimes[0]:
132            slicetimes.pop(0)
133            # write up to 1st zero crossing
134            zerocross = 0
135            while ( abs( myvec.get(zerocross,0) ) > zerothres ):
136                zerocross += 1
137            writesize = fileo.write(zerocross,myvec)
138            fromcross = 0
139            while (zerocross < readsize):
140                for i in range(channels):
141                    mycopy.set(myvec.get(zerocross,i),fromcross,i)
142                    fromcross += 1
143                    zerocross += 1
144            del fileo
145            fileo = sndfile("%s%s%09.5f%s%s" % 
146                (filein.split(".")[0].split("/")[-1],".",
147                frameread*framestep,".",filein.split(".")[-1]),model=filei)
148            writesize = fileo.write(fromcross,mycopy)
149        else:
150            writesize = fileo.write(readsize,myvec)
151        frameread += 1
152    del fileo
153
154
155def getsilences(filein,hopsize=512,silence=-70):
156    frameread = 0
157    filei     = sndfile(filein)
158    srate     = filei.samplerate()
159    channels  = filei.channels()
160    myvec     = fvec(hopsize,channels)
161    readsize  = filei.read(hopsize,myvec)
162    mylist    = []
163    wassilence = 0
164    while(readsize==hopsize):
165        readsize = filei.read(hopsize,myvec)
166        if (aubio_silence_detection(myvec(),silence)==1):
167            if wassilence == 0:
168                mylist.append(frameread)
169                wassilence == 1
170        else: wassilence = 0
171        frameread += 1
172    return mylist
173
[0029638]174
[5e491b3b]175def getpitch(filein,mode=aubio_pitch_mcomb,bufsize=1024,hopsize=512,omode=aubio_pitchm_freq,
176        samplerate=44100.,silence=-70):
177    frameread = 0
178    filei     = sndfile(filein)
179    srate     = filei.samplerate()
180    channels  = filei.channels()
181    myvec     = fvec(hopsize,channels)
182    readsize  = filei.read(hopsize,myvec)
183    pitchdet  = pitchdetection(mode=mode,bufsize=bufsize,hopsize=hopsize,
184                         channels=channels,samplerate=srate,omode=omode)
185    mylist    = []
186    while(readsize==hopsize):
187        readsize = filei.read(hopsize,myvec)
188        freq = pitchdet(myvec)
189        #print "%.3f     %.2f" % (now,freq)
190        if (aubio_silence_detection(myvec(),silence)!=1):
191                mylist.append(freq)
192        else: 
193                mylist.append(-1.)
194        frameread += 1
195    return mylist
196
[0029638]197
198class taskparams:
199        """ default parameters for task classes """
200        def __init__(self,input=None,output=None):
201                self.silence = -70
202                self.derivate = False
203                self.localmin = False
[7c9ad74]204                self.storefunc = False
[0029638]205                self.bufsize = 512
206                self.hopsize = 256
207                self.samplerate = 44100
208                self.tol = 0.05
209                self.step = float(self.hopsize)/float(self.samplerate)
210                self.threshold = 0.1
[7c9ad74]211                self.onsetmode = 'dual'
212                self.pitchmode = 'yin'
[0029638]213                self.omode = aubio_pitchm_freq
214
215class task(taskparams):
[7c9ad74]216        """ default template class to apply tasks on a stream """
[0029638]217        def __init__(self,input,output=None,params=None):
[7c9ad74]218                """ open the input file and initialize default argument
219                parameters should be set *before* calling this method.
220                """
[0029638]221                if params == None: self.params = taskparams()
222                else: self.params = params
[7c9ad74]223                self.frameread = 0
224                self.readsize  = self.params.hopsize
[0029638]225                self.input     = input
226                self.filei     = sndfile(self.input)
227                self.srate     = self.filei.samplerate()
228                self.channels  = self.filei.channels()
[7c9ad74]229                self.step      = float(self.srate)/float(self.params.hopsize)
230                self.myvec     = fvec(self.params.hopsize,self.channels)
[0029638]231                self.output    = output
[7c9ad74]232        def __call__(self):
233                self.readsize = self.filei.read(self.params.hopsize,self.myvec)
234                self.frameread += 1
235               
[0029638]236        def compute_all(self):
237                """ Compute data """
238                mylist    = []
239                while(self.readsize==self.params.hopsize):
[7c9ad74]240                        tmp = self()
241                        if tmp: mylist.append(tmp)
[0029638]242                return mylist
243
244        def eval(self,results):
245                """ Eval data """
246                pass
247
248        def plot(self):
249                """ Plot data """
250                pass
251
[7c9ad74]252class tasksilence(task):
253        wassilence = 1
254        issilence  = 1
255        def __call__(self):
256                task.__call__(self)
257                if (aubio_silence_detection(self.myvec(),self.params.silence)==1):
258                        if self.wassilence == 1: self.issilence = 1
259                        else: self.issilence = 2
260                        self.wassilence = 1
261                else: 
262                        if self.wassilence <= 0: self.issilence = 0
263                        else: self.issilence = -1 
264                        self.wassilence = 0
265                if self.issilence == -1:
266                        return -1, self.frameread
267                elif self.issilence == 2:
268                        return 2, self.frameread
269
[0029638]270class taskpitch(task):
271        def __init__(self,input,params=None):
272                task.__init__(self,input,params=params)
[7c9ad74]273                self.pitchdet  = pitchdetection(mode=get_pitch_mode(self.params.pitchmode),
[0029638]274                        bufsize=self.params.bufsize,
275                        hopsize=self.params.hopsize,
276                        channels=self.channels,
277                        samplerate=self.srate,
278                        omode=self.params.omode)
279
280        def __call__(self):
281                #print "%.3f     %.2f" % (now,freq)
[7c9ad74]282                task.__call__(self)
283                freq = self.pitchdet(self.myvec)
[0029638]284                if (aubio_silence_detection(self.myvec(),self.params.silence)!=1):
285                        return freq
286                else: 
287                        return -1.
288
289        def gettruth(self):
[7c9ad74]290                """ big hack to extract midi note from /path/to/file.<midinote>.wav """
[0029638]291                return float(self.input.split('.')[-2])
292               
293
294        def eval(self,results):
295                from median import short_find
296                self.truth = self.gettruth()
297                num = 0
298                sum = 0
299                res = []
300                for i in results:
301                        if i == -1: pass
302                        else: 
303                                res.append(i)
304                                sum += i
305                                num += 1
[7c9ad74]306                if num == 0: 
307                        avg = 0; med = 0
308                else:
309                        avg = aubio_freqtomidi(sum / float(num))
310                        med = aubio_freqtomidi(short_find(res,len(res)/2))
[0029638]311                avgdist = self.truth - avg
312                meddist = self.truth - med
313                return avgdist, meddist
314
315        def plot(self):
316                from aubio.gnuplot import plot_pitch
317                plot_pitch(self.input, 
318                        pitch, 
319                        samplerate=samplerate, 
320                        hopsize=self.params.hopsize, 
321                        outplot=options.outplot)
322
323
[7c9ad74]324class taskonset(task):
325        def __init__(self,input,output=None,params=None):
326                """ open the input file and initialize arguments
327                parameters should be set *before* calling this method.
328                """
329                task.__init__(self,input,params=params)
330                self.opick = onsetpick(self.params.bufsize,
331                        self.params.hopsize,
332                        self.channels,
333                        self.myvec,
334                        self.params.threshold,
335                        mode=get_onset_mode(self.params.onsetmode),
336                        derivate=self.params.derivate)
337                self.olist = [] 
338                self.ofunc = []
339                self.d,self.d2 = [],[]
340                self.maxofunc = 0
341                if self.params.localmin:
342                        ovalist   = [0., 0., 0., 0., 0.]
343
344        def __call__(self):
345                task.__call__(self)
346                isonset,val = self.opick.do(self.myvec)
347                if (aubio_silence_detection(self.myvec(),self.params.silence)):
348                        isonset=0
349                if self.params.storefunc:
350                        self.ofunc.append(val)
351                if self.params.localmin:
352                        if val > 0: ovalist.append(val)
353                        else: ovalist.append(0)
354                        ovalist.pop(0)
355                if (isonset == 1):
356                        if self.params.localmin:
357                                i=len(self.ovalist)-1
358                                # find local minima before peak
359                                while self.ovalist[i-1] < self.ovalist[i] and i > 0:
360                                        i -= 1
361                                now = (self.frameread+1-i)
362                        else:
363                                now = self.frameread
364                        if now < 0 :
365                                now = 0
366                        return now, val
367
368        def eval(self,lres):
369                from txtfile import read_datafile
370                from onsetcompare import onset_roc
371                amode = 'roc'
372                vmode = 'verbose'
373                vmode = ''
374                for i in range(len(lres)): lres[i] = lres[i][0]*self.params.step
375                ltru = read_datafile(self.input.replace('.wav','.txt'),depth=0)
376                if vmode=='verbose':
377                        print "Running with mode %s" % self.params.mode, 
378                        print " and threshold %f" % self.params.threshold, 
379                        print " on file", input
380                #print ltru; print lres
381                if amode == 'localisation':
382                        l = onset_diffs(ltru,lres,self.params.tol)
383                        mean = 0
384                        for i in l: mean += i
385                        if len(l): print "%.3f" % (mean/len(l))
386                        else: print "?0"
387                elif amode == 'roc':
388                        self.orig, self.missed, self.merged, \
389                                self.expc, self.bad, self.doubled = \
390                                onset_roc(ltru,lres,self.params.tol)
391
392        def plot(self,onsets,ofunc):
393                import Gnuplot, Gnuplot.funcutils
394                import aubio.txtfile
395                import os.path
396                import numarray
397                from aubio.onsetcompare import onset_roc
398
399                self.lenofunc = len(ofunc) 
400                self.maxofunc = max(max(ofunc), self.maxofunc)
401                # onset detection function
402                downtime = numarray.arange(len(ofunc))/self.step
403                self.d.append(Gnuplot.Data(downtime,ofunc,with='lines'))
404
405                # detected onsets
406                x1 = numarray.array(onsets)/self.step
407                y1 = self.maxofunc*numarray.ones(len(onsets))
408                self.d.append(Gnuplot.Data(x1,y1,with='impulses'))
409                self.d2.append(Gnuplot.Data(x1,-y1,with='impulses'))
410
411                # check if datafile exists truth
412                datafile = self.input.replace('.wav','.txt')
413                if datafile == self.input: datafile = ""
414                if not os.path.isfile(datafile):
415                        self.title = "truth file not found"
416                        t = Gnuplot.Data(0,0,with='impulses') 
417                else:
418                        t_onsets = aubio.txtfile.read_datafile(datafile)
419                        y2 = self.maxofunc*numarray.ones(len(t_onsets))
420                        x2 = numarray.array(t_onsets).resize(len(t_onsets))
421                        self.d2.append(Gnuplot.Data(x2,y2,with='impulses'))
422                       
423                        tol = 0.050 
[0029638]424
[7c9ad74]425                        orig, missed, merged, expc, bad, doubled = \
426                                onset_roc(x2,x1,tol)
427                        self.title = "GD %2.3f%% FP %2.3f%%" % \
428                                ((100*float(orig-missed-merged)/(orig)),
429                                 (100*float(bad+doubled)/(orig)))
430
431
432        def plotplot(self,outplot=None):
433                from aubio.gnuplot import gnuplot_init, audio_to_array, make_audio_plot
434                import re
435                # audio data
436                time,data = audio_to_array(self.input)
437                self.d2.append(make_audio_plot(time,data))
438                # prepare the plot
439                g = gnuplot_init(outplot)
440
441                g('set title \'%s %s\'' % (re.sub('.*/','',self.input),self.title))
442
443                g('set multiplot')
444
445                # hack to align left axis
446                g('set lmargin 15')
447
448                # plot waveform and onsets
449                g('set size 1,0.3')
450                g('set origin 0,0.7')
451                g('set xrange [0:%f]' % max(time)) 
452                g('set yrange [-1:1]') 
453                g.ylabel('amplitude')
454                g.plot(*self.d2)
455               
456                g('unset title')
457
458                # plot onset detection function
459                g('set size 1,0.7')
460                g('set origin 0,0')
461                g('set xrange [0:%f]' % (self.lenofunc/self.step))
462                g('set yrange [0:%f]' % (self.maxofunc*1.01))
463                g.xlabel('time')
464                g.ylabel('onset detection value')
465                g.plot(*self.d)
466
467                g('unset multiplot')
468
469class taskcut(task):
470        def __init__(self,input,slicetimes,params=None,output=None):
471                """ open the input file and initialize arguments
472                parameters should be set *before* calling this method.
473                """
474                task.__init__(self,input,output=None,params=params)
475                self.newname   = "%s%s%09.5f%s%s" % (self.input.split(".")[0].split("/")[-1],".",
476                                        self.frameread/self.step,".",self.input.split(".")[-1])
477                self.fileo       = sndfile(self.newname,model=self.filei)
478                self.myvec       = fvec(self.params.hopsize,self.channels)
479                self.mycopy     = fvec(self.params.hopsize,self.channels)
480                self.slicetimes = slicetimes
481
482        def __call__(self):
483                task.__call__(self)
484                # write to current file
485                if len(self.slicetimes) and self.frameread >= self.slicetimes[0]:
486                        self.slicetimes.pop(0)
487                        # write up to 1st zero crossing
488                        zerocross = 0
489                        while ( abs( self.myvec.get(zerocross,0) ) > self.params.zerothres ):
490                                zerocross += 1
491                        writesize = self.fileo.write(zerocross,self.myvec)
492                        fromcross = 0
493                        while (zerocross < self.readsize):
494                                for i in range(self.channels):
495                                        self.mycopy.set(self.myvec.get(zerocross,i),fromcross,i)
496                                        fromcross += 1
497                                        zerocross += 1
498                        del self.fileo
499                        self.fileo = sndfile("%s%s%09.5f%s%s" % 
500                                (self.input.split(".")[0].split("/")[-1],".",
501                                self.frameread/self.step,".",self.input.split(".")[-1]),model=self.filei)
502                        writesize = self.fileo.write(fromcross,self.mycopy)
503                else:
504                        writesize = self.fileo.write(self.readsize,self.myvec)
Note: See TracBrowser for help on using the repository browser.