source: python/aubio/task/pitch.py @ cd77c15

feature/autosinkfeature/cnnfeature/cnn_orgfeature/constantqfeature/crepefeature/crepe_orgfeature/pitchshiftfeature/pydocstringsfeature/timestretchfix/ffmpeg5pitchshiftsamplertimestretchyinfft+
Last change on this file since cd77c15 was 3027c6e, checked in by Paul Brossier <piem@piem.org>, 15 years ago

python/aubio: update to latest pitch prototypes

  • Property mode set to 100644
File size: 7.2 KB
RevLine 
[13c3fba]1from aubio.task.task import task
2from aubio.task.silence import tasksilence
3from aubio.task.utils import * 
4from aubio.aubioclass import *
5
6class taskpitch(task):
7        def __init__(self,input,params=None):
8                task.__init__(self,input,params=params)
9                self.shortlist = [0. for i in range(self.params.pitchsmooth)]
[3027c6e]10                if self.params.pitchmode == 'yin':
11                        tolerance = self.params.yinthresh
12                elif self.params.pitchmode == 'yinfft':
13                        tolerance = self.params.yinfftthresh
[650e39b]14                else:
[3027c6e]15                        tolerance = 0.
16                self.pitchdet   = pitchdetection(mode=get_pitch_mode(self.params.pitchmode),
[13c3fba]17                        bufsize=self.params.bufsize,
18                        hopsize=self.params.hopsize,
19                        channels=self.channels,
20                        samplerate=self.srate,
[83376e9]21                        omode=self.params.omode,
[3027c6e]22                        tolerance = tolerance)
[13c3fba]23
24        def __call__(self):
25                from aubio.median import short_find
26                task.__call__(self)
27                if (aubio_silence_detection(self.myvec(),self.params.silence)==1):
28                        freq = -1.
29                else:
30                        freq = self.pitchdet(self.myvec)
31                minpitch = self.params.pitchmin
32                maxpitch = self.params.pitchmax
33                if maxpitch and freq > maxpitch : 
34                        freq = -1.
35                elif minpitch and freq < minpitch :
36                        freq = -1.
37                if self.params.pitchsmooth:
38                        self.shortlist.append(freq)
39                        self.shortlist.pop(0)
40                        smoothfreq = short_find(self.shortlist,
41                                len(self.shortlist)/2)
42                        return smoothfreq
43                else:
44                        return freq
45
46        def compute_all(self):
47                """ Compute data """
48                mylist    = []
49                while(self.readsize==self.params.hopsize):
50                        freq = self()
51                        mylist.append(freq)
52                        if self.params.verbose:
53                                self.fprint("%s\t%s" % (self.frameread*self.params.step,freq))
54                return mylist
55
56        def gettruth(self):
57                """ extract ground truth array in frequency """
58                import os.path
59                """ from wavfile.txt """
60                datafile = self.input.replace('.wav','.txt')
61                if datafile == self.input: datafile = ""
62                """ from file.<midinote>.wav """
63                # FIXME very weak check
64                floatpit = self.input.split('.')[-2]
65                if not os.path.isfile(datafile) and len(self.input.split('.')) < 3:
66                        print "no ground truth "
67                        return False,False
68                elif floatpit:
69                        try:
[5d1c070]70                                self.truth = float(floatpit)
71                                #print "ground truth found in filename:", self.truth
72                                tasksil = tasksilence(self.input,params=self.params)
[13c3fba]73                                time,pitch =[],[]
74                                while(tasksil.readsize==tasksil.params.hopsize):
75                                        tasksil()
[650e39b]76                                        time.append(tasksil.params.step*(tasksil.frameread))
[13c3fba]77                                        if not tasksil.issilence:
78                                                pitch.append(self.truth)
79                                        else:
80                                                pitch.append(-1.)
[4798fdf]81                                return time,pitch
[13c3fba]82                        except ValueError:
83                                # FIXME very weak check
84                                if not os.path.isfile(datafile):
85                                        print "no ground truth found"
86                                        return 0,0
87                                else:
88                                        from aubio.txtfile import read_datafile
89                                        values = read_datafile(datafile)
90                                        time, pitch = [], []
91                                        for i in range(len(values)):
92                                                time.append(values[i][0])
[83376e9]93                                                if values[i][1] == 0.0:
94                                                        pitch.append(-1.)
95                                                else:
96                                                        pitch.append(aubio_freqtomidi(values[i][1]))
[13c3fba]97                                        return time,pitch
98
[5d1c070]99        def oldeval(self,results):
[13c3fba]100                def mmean(l):
101                        return sum(l)/max(float(len(l)),1)
102
103                from aubio.median import percental
104                timet,pitcht = self.gettruth()
105                res = []
106                for i in results:
107                        #print i,self.truth
108                        if i <= 0: pass
109                        else: res.append(self.truth-i)
110                if not res or len(res) < 3: 
111                        avg = self.truth; med = self.truth
112                else:
113                        avg = mmean(res) 
114                        med = percental(res,len(res)/2) 
115                return self.truth, self.truth-med, self.truth-avg
116
[83376e9]117        def eval(self,pitch,tol=0.5):
[13c3fba]118                timet,pitcht = self.gettruth()
[5d1c070]119                pitch = [aubio_freqtomidi(i) for i in pitch]
120                for i in range(len(pitch)):
121                        if pitch[i] == "nan" or pitch[i] == -1:
122                                pitch[i] = -1
[4798fdf]123                time = [ (i+self.params.pitchdelay)*self.params.step for i in range(len(pitch)) ]
[83376e9]124                #print len(timet),len(pitcht)
125                #print len(time),len(pitch)
126                if len(timet) != len(time):
127                        time = time[1:len(timet)+1]
128                        pitch = pitch[1:len(pitcht)+1]
129                        #pitcht = [aubio_freqtomidi(i) for i in pitcht]
130                        for i in range(len(pitcht)):
131                                if pitcht[i] == "nan" or pitcht[i] == "-inf" or pitcht[i] == -1:
132                                        pitcht[i] = -1
133                assert len(timet) == len(time)
[5d1c070]134                assert len(pitcht) == len(pitch)
135                osil, esil, opit, epit, echr = 0, 0, 0, 0, 0
136                for i in range(len(pitcht)):
137                        if pitcht[i] == -1: # currently silent
138                                osil += 1 # count a silence
[83376e9]139                                if pitch[i] <= 0. or pitch[i] == "nan": 
[5d1c070]140                                        esil += 1 # found a silence
141                        else:
142                                opit +=1
143                                if abs(pitcht[i] - pitch[i]) < tol:
144                                        epit += 1
145                                        echr += 1
146                                elif abs(pitcht[i] - pitch[i]) % 12. < tol:
147                                        echr += 1
148                                #else:
149                                #       print timet[i], pitcht[i], time[i], pitch[i]
150                #print "origsilence", "foundsilence", "origpitch", "foundpitch", "orig pitchroma", "found pitchchroma"
151                #print 100.*esil/float(osil), 100.*epit/float(opit), 100.*echr/float(opit)
152                return osil, esil, opit, epit, echr
[13c3fba]153
[fb8bde7]154        def plot(self,pitch,wplot,oplots,titles,outplot=None):
[13c3fba]155                import Gnuplot
156
[4798fdf]157                time = [ (i+self.params.pitchdelay)*self.params.step for i in range(len(pitch)) ]
[83376e9]158                pitch = [aubio_freqtomidi(i) for i in pitch]
[5f23f66]159                oplots.append(Gnuplot.Data(time,pitch,with_='lines',
[13c3fba]160                        title=self.params.pitchmode))
[fb8bde7]161                titles.append(self.params.pitchmode)
[13c3fba]162
163                       
[470a772]164        def plotplot(self,wplot,oplots,titles,outplot=None,extension=None,xsize=1.,ysize=1.,multiplot = 1, midi = 1, truth = 1):
165                from aubio.gnuplot import gnuplot_create , audio_to_array, make_audio_plot
[13c3fba]166                import re
167                import Gnuplot
168
169                # check if ground truth exists
[fb8bde7]170                if truth:
171                        timet,pitcht = self.gettruth()
172                        if timet and pitcht:
[5f23f66]173                                oplots = [Gnuplot.Data(timet,pitcht,with_='lines',
[fb8bde7]174                                        title='ground truth')] + oplots
[13c3fba]175
[470a772]176                g = gnuplot_create(outplot=outplot, extension=extension)
[13c3fba]177                g('set title \'%s\'' % (re.sub('.*/','',self.input)))
[470a772]178                g('set size %f,%f' % (xsize,ysize) )
[13c3fba]179                g('set multiplot')
180                # hack to align left axis
[fb8bde7]181                g('set lmargin 4')
182                g('set rmargin 4')
[470a772]183    # plot waveform
184                time,data = audio_to_array(self.input)
185                wplot = [make_audio_plot(time,data)]
186                g('set origin 0,%f' % (0.7*ysize) )
187                g('set size %f,%f' % (xsize,0.3*ysize))
188                #g('set format y "%1f"')
[13c3fba]189                g('set xrange [0:%f]' % max(time)) 
190                g('set yrange [-1:1]') 
[fb8bde7]191                g('set noytics')
192                g('set y2tics -1,1')
[470a772]193                g.xlabel('time (s)',offset=(0,0.7))
[13c3fba]194                g.ylabel('amplitude')
[470a772]195                g.plot(*wplot)
[13c3fba]196
[470a772]197                # default settings for next plots
198                g('unset title')
199                g('set format x ""')
200                g('set format y "%3e"')
201                g('set tmargin 0')
202                g.xlabel('')
203                g('set noclip one') 
[13c3fba]204
[83376e9]205                if not midi:
206                        g('set log y')
207                        #g.xlabel('time (s)')
208                        g.ylabel('f0 (Hz)')
209                        g('set yrange [100:%f]' % self.params.pitchmax) 
210                else: 
[4798fdf]211                        g.ylabel('midi')
[650e39b]212                        g('set yrange [%f:%f]' % (aubio_freqtomidi(self.params.pitchmin), aubio_freqtomidi(self.params.pitchmax)))
[fb8bde7]213                        g('set y2tics %f,%f' % (round(aubio_freqtomidi(self.params.pitchmin)+.5),12))
[470a772]214               
[13c3fba]215                if multiplot:
[470a772]216                        N = len(oplots)
217                        y = 0.7*ysize # the vertical proportion of the plot taken by onset functions
218                        delta = 0.035 # the constant part of y taken by last plot label and data
219                        for i in range(N):
220                                # plot pitch detection functions
221                                g('set size %f,%f' % ( xsize, (y-delta)/N))
222                                g('set origin 0,%f' % ((N-i-1)*(y-delta)/N + delta ))
[fb8bde7]223                                g('set nokey')
[470a772]224                                g('set xrange [0:%f]' % max(time))
[fb8bde7]225                                g.ylabel(titles[i])
[470a772]226                                if i == N-1:
227                                        g('set size %f,%f' % (xsize, (y-delta)/N + delta ) )
228                                        g('set origin 0,0')
229                                        g.xlabel('time (s)', offset=(0,0.7))
230                                        g('set format x')
[13c3fba]231                                g.plot(oplots[i])
232                else:
[470a772]233                        g('set key right top')
[13c3fba]234                        g.plot(*oplots)
235                g('unset multiplot')
236
Note: See TracBrowser for help on using the repository browser.