fazekasgy@52
|
1 '''PyMFCC_legacy.py - This example Vampy plugin demonstrates
|
fazekasgy@52
|
2 how to return sprectrogram-like features.
|
fazekasgy@52
|
3
|
fazekasgy@52
|
4 This plugin has frequency domain input and is using
|
fazekasgy@52
|
5 the legacy input interface: the frequency samples are
|
fazekasgy@52
|
6 passed as python list of complex numbers.
|
fazekasgy@52
|
7
|
fazekasgy@52
|
8 Note: This is not the adviced way of writing plugins,
|
fazekasgy@52
|
9 since the input interfaces provided for Numpy such as the
|
fazekasgy@52
|
10 Numpy Array interface (flag: vf_ARRAY) are much faster.
|
fazekasgy@52
|
11
|
fazekasgy@52
|
12 This plugin is using Numpy, but it does not rely on Vampy's
|
fazekasgy@52
|
13 capability of passing Numpy arrays to the process directly.
|
fazekasgy@52
|
14 However, it returns Numpy arrays from the process.
|
fazekasgy@52
|
15
|
fazekasgy@52
|
16 Centre for Digital Music, Queen Mary University of London.
|
fazekasgy@52
|
17 Copyright 2006 Gyorgy Fazekas, QMUL.
|
fazekasgy@52
|
18 (See Vamp API for licence information.)
|
fazekasgy@52
|
19
|
fazekasgy@52
|
20 Constants for Mel frequency conversion and filter
|
fazekasgy@52
|
21 centre calculation are taken from the GNU GPL licenced
|
fazekasgy@52
|
22 Freespeech library. Copyright (C) 1999 Jean-Marc Valin
|
fazekasgy@52
|
23 '''
|
fazekasgy@52
|
24
|
fazekasgy@52
|
25 import sys,numpy
|
fazekasgy@52
|
26 from numpy import log,exp,floor,sum
|
fazekasgy@52
|
27 from numpy import *
|
fazekasgy@52
|
28 from numpy.fft import *
|
fazekasgy@52
|
29 import vampy
|
fazekasgy@52
|
30 from vampy import *
|
fazekasgy@52
|
31
|
fazekasgy@52
|
32
|
fazekasgy@52
|
33 class melScaling(object):
|
fazekasgy@52
|
34
|
fazekasgy@52
|
35 def __init__(self,sampleRate,inputSize,numBands,minHz = 0,maxHz = None):
|
fazekasgy@52
|
36 '''Initialise frequency warping and DCT matrix.
|
fazekasgy@52
|
37 Parameters:
|
fazekasgy@52
|
38 sampleRate: audio sample rate
|
fazekasgy@52
|
39 inputSize: length of magnitude spectrum (half of FFT size assumed)
|
fazekasgy@52
|
40 numBands: number of mel Bands (MFCCs)
|
fazekasgy@52
|
41 minHz: lower bound of warping (default = DC)
|
fazekasgy@52
|
42 maxHz: higher bound of warping (default = Nyquist frequency)
|
fazekasgy@52
|
43 '''
|
fazekasgy@52
|
44 self.sampleRate = sampleRate
|
fazekasgy@52
|
45 self.NqHz = sampleRate / 2.0
|
fazekasgy@52
|
46 self.minHz = minHz
|
fazekasgy@52
|
47 if maxHz is None : maxHz = self.NqHz
|
fazekasgy@52
|
48 self.maxHz = maxHz
|
fazekasgy@52
|
49 self.inputSize = inputSize
|
fazekasgy@52
|
50 self.numBands = numBands
|
fazekasgy@52
|
51 self.valid = False
|
fazekasgy@52
|
52 self.updated = False
|
fazekasgy@52
|
53
|
fazekasgy@52
|
54
|
fazekasgy@52
|
55 def update(self):
|
fazekasgy@52
|
56 # make sure this will run only once if called from a vamp process
|
fazekasgy@52
|
57
|
fazekasgy@52
|
58 if self.updated: return self.valid
|
fazekasgy@52
|
59 self.updated = True
|
fazekasgy@52
|
60 self.valid = False
|
fazekasgy@52
|
61 print 'Updating parameters and recalculating filters: '
|
fazekasgy@52
|
62 print 'Nyquist: ',self.NqHz
|
fazekasgy@52
|
63
|
fazekasgy@52
|
64 if self.maxHz > self.NqHz :
|
fazekasgy@52
|
65 raise Exception('Maximum frequency must be smaller than the Nyquist frequency')
|
fazekasgy@52
|
66
|
fazekasgy@52
|
67 self.maxMel = 1000*log(1+self.maxHz/700.0)/log(1+1000.0/700.0)
|
fazekasgy@52
|
68 self.minMel = 1000*log(1+self.minHz/700.0)/log(1+1000.0/700.0)
|
fazekasgy@52
|
69 print 'minHz:%s\nmaxHz:%s\nminMel:%s\nmaxMel:%s\n' %(self.minHz,self.maxHz,self.minMel,self.maxMel)
|
fazekasgy@52
|
70 self.filterMatrix = self.getFilterMatrix(self.inputSize,self.numBands)
|
fazekasgy@52
|
71 self.DCTMatrix = self.getDCTMatrix(self.numBands)
|
fazekasgy@52
|
72 self.filterIter = self.filterMatrix.__iter__()
|
fazekasgy@52
|
73 self.valid = True
|
fazekasgy@52
|
74 return self.valid
|
fazekasgy@52
|
75
|
fazekasgy@52
|
76 # try :
|
fazekasgy@52
|
77 # self.maxMel = 1000*log(1+self.maxHz/700.0)/log(1+1000.0/700.0)
|
fazekasgy@52
|
78 # self.minMel = 1000*log(1+self.minHz/700.0)/log(1+1000.0/700.0)
|
fazekasgy@52
|
79 # self.filterMatrix = self.getFilterMatrix(self.inputSize,self.numBands)
|
fazekasgy@52
|
80 # self.DCTMatrix = self.getDCTMatrix(self.numBands)
|
fazekasgy@52
|
81 # self.filterIter = self.filterMatrix.__iter__()
|
fazekasgy@52
|
82 # self.valid = True
|
fazekasgy@52
|
83 # return True
|
fazekasgy@52
|
84 # except :
|
fazekasgy@52
|
85 # print "Invalid parameter setting encountered in MelScaling class."
|
fazekasgy@52
|
86 # return False
|
fazekasgy@52
|
87 # return True
|
fazekasgy@52
|
88
|
fazekasgy@52
|
89 def getFilterCentres(self,inputSize,numBands):
|
fazekasgy@52
|
90 '''Calculate Mel filter centres around FFT bins.
|
fazekasgy@52
|
91 This function calculates two extra bands at the edges for
|
fazekasgy@52
|
92 finding the starting and end point of the first and last
|
fazekasgy@52
|
93 actual filters.'''
|
fazekasgy@52
|
94 centresMel = numpy.array(xrange(numBands+2)) * (self.maxMel-self.minMel)/(numBands+1) + self.minMel
|
fazekasgy@52
|
95 centresBin = numpy.floor(0.5 + 700.0*inputSize*(exp(centresMel*log(1+1000.0/700.0)/1000.0)-1)/self.NqHz)
|
fazekasgy@52
|
96 return numpy.array(centresBin,int)
|
fazekasgy@52
|
97
|
fazekasgy@52
|
98 def getFilterMatrix(self,inputSize,numBands):
|
fazekasgy@52
|
99 '''Compose the Mel scaling matrix.'''
|
fazekasgy@52
|
100 filterMatrix = numpy.zeros((numBands,inputSize))
|
fazekasgy@52
|
101 self.filterCentres = self.getFilterCentres(inputSize,numBands)
|
fazekasgy@52
|
102 for i in xrange(numBands) :
|
fazekasgy@52
|
103 start,centre,end = self.filterCentres[i:i+3]
|
fazekasgy@52
|
104 self.setFilter(filterMatrix[i],start,centre,end)
|
fazekasgy@52
|
105 return filterMatrix.transpose()
|
fazekasgy@52
|
106
|
fazekasgy@52
|
107 def setFilter(self,filt,filterStart,filterCentre,filterEnd):
|
fazekasgy@52
|
108 '''Calculate a single Mel filter.'''
|
fazekasgy@52
|
109 k1 = numpy.float32(filterCentre-filterStart)
|
fazekasgy@52
|
110 k2 = numpy.float32(filterEnd-filterCentre)
|
fazekasgy@52
|
111 up = (numpy.array(xrange(filterStart,filterCentre))-filterStart)/k1
|
fazekasgy@52
|
112 dn = (filterEnd-numpy.array(xrange(filterCentre,filterEnd)))/k2
|
fazekasgy@52
|
113 filt[filterStart:filterCentre] = up
|
fazekasgy@52
|
114 filt[filterCentre:filterEnd] = dn
|
fazekasgy@52
|
115
|
fazekasgy@52
|
116 def warpSpectrum(self,magnitudeSpectrum):
|
fazekasgy@52
|
117 '''Compute the Mel scaled spectrum.'''
|
fazekasgy@52
|
118 return numpy.dot(magnitudeSpectrum,self.filterMatrix)
|
fazekasgy@52
|
119
|
fazekasgy@52
|
120 def getDCTMatrix(self,size):
|
fazekasgy@52
|
121 '''Calculate the square DCT transform matrix. Results are
|
fazekasgy@52
|
122 equivalent to Matlab dctmtx(n) but with 64 bit precision.'''
|
fazekasgy@52
|
123 DCTmx = numpy.array(xrange(size),numpy.float64).repeat(size).reshape(size,size)
|
fazekasgy@52
|
124 DCTmxT = numpy.pi * (DCTmx.transpose()+0.5) / size
|
fazekasgy@52
|
125 DCTmxT = (1.0/sqrt( size / 2.0)) * cos(DCTmx * DCTmxT)
|
fazekasgy@52
|
126 DCTmxT[0] = DCTmxT[0] * (sqrt(2.0)/2.0)
|
fazekasgy@52
|
127 return DCTmxT
|
fazekasgy@52
|
128
|
fazekasgy@52
|
129 def dct(self,data_matrix):
|
fazekasgy@52
|
130 '''Compute DCT of input matrix.'''
|
fazekasgy@52
|
131 return numpy.dot(self.DCTMatrix,data_matrix)
|
fazekasgy@52
|
132
|
fazekasgy@52
|
133 def getMFCCs(self,warpedSpectrum,cn=True):
|
fazekasgy@52
|
134 '''Compute MFCC coefficients from Mel warped magnitude spectrum.'''
|
fazekasgy@52
|
135 mfccs=self.dct(numpy.log(warpedSpectrum))
|
fazekasgy@52
|
136 if cn is False : mfccs[0] = 0.0
|
fazekasgy@52
|
137 return mfccs
|
fazekasgy@52
|
138
|
fazekasgy@52
|
139
|
fazekasgy@52
|
140 class PyMFCC_legacy(melScaling):
|
fazekasgy@52
|
141
|
fazekasgy@52
|
142 def __init__(self,inputSampleRate):
|
fazekasgy@52
|
143
|
fazekasgy@52
|
144 # flags for setting some Vampy options
|
fazekasgy@52
|
145 self.vampy_flags = vf_DEBUG | vf_REALTIME
|
fazekasgy@52
|
146
|
fazekasgy@52
|
147 self.m_inputSampleRate = int(inputSampleRate)
|
fazekasgy@52
|
148 self.m_stepSize = 512
|
fazekasgy@52
|
149 self.m_blockSize = 2048
|
fazekasgy@52
|
150 self.m_channels = 1
|
fazekasgy@52
|
151 self.numBands = 40
|
fazekasgy@52
|
152 self.cnull = 1
|
fazekasgy@52
|
153 self.two_ch = False
|
fazekasgy@52
|
154 melScaling.__init__(self,int(self.m_inputSampleRate),self.m_blockSize/2,self.numBands)
|
fazekasgy@52
|
155
|
fazekasgy@52
|
156 def initialise(self,channels,stepSize,blockSize):
|
fazekasgy@52
|
157 self.m_channels = channels
|
fazekasgy@52
|
158 self.m_stepSize = stepSize
|
fazekasgy@52
|
159 self.m_blockSize = blockSize
|
fazekasgy@52
|
160 self.window = numpy.hamming(blockSize)
|
fazekasgy@52
|
161 melScaling.__init__(self,int(self.m_inputSampleRate),self.m_blockSize/2,self.numBands)
|
fazekasgy@52
|
162 return True
|
fazekasgy@52
|
163
|
fazekasgy@52
|
164 def getMaker(self):
|
fazekasgy@52
|
165 return 'Vampy Test Plugins'
|
fazekasgy@52
|
166
|
fazekasgy@52
|
167 def getCopyright(self):
|
fazekasgy@52
|
168 return 'Plugin By George Fazekas'
|
fazekasgy@52
|
169
|
fazekasgy@52
|
170 def getName(self):
|
fazekasgy@52
|
171 return 'Vampy Legacy FrequencyDomain MFCC Plugin'
|
fazekasgy@52
|
172
|
fazekasgy@52
|
173 def getIdentifier(self):
|
fazekasgy@52
|
174 return 'vampy-mfcc-test-legacy'
|
fazekasgy@52
|
175
|
fazekasgy@52
|
176 def getDescription(self):
|
fazekasgy@52
|
177 return 'Vampy FrequencyDomain MFCC Plugin using the Legacy interface.'
|
fazekasgy@52
|
178
|
fazekasgy@52
|
179 def getMaxChannelCount(self):
|
fazekasgy@52
|
180 return 2
|
fazekasgy@52
|
181
|
fazekasgy@52
|
182 def getInputDomain(self):
|
fazekasgy@52
|
183 return FrequencyDomain
|
fazekasgy@52
|
184
|
fazekasgy@52
|
185 def getPreferredBlockSize(self):
|
fazekasgy@52
|
186 return 2048
|
fazekasgy@52
|
187
|
fazekasgy@52
|
188 def getPreferredStepSize(self):
|
fazekasgy@52
|
189 return 512
|
fazekasgy@52
|
190
|
fazekasgy@52
|
191 def getOutputDescriptors(self):
|
fazekasgy@52
|
192
|
fazekasgy@52
|
193 Generic = OutputDescriptor()
|
fazekasgy@52
|
194 Generic.hasFixedBinCount=True
|
fazekasgy@52
|
195 Generic.binCount=int(self.numBands)-self.cnull
|
fazekasgy@52
|
196 Generic.hasKnownExtents=False
|
fazekasgy@52
|
197 Generic.isQuantized=True
|
fazekasgy@52
|
198 Generic.sampleType = OneSamplePerStep
|
fazekasgy@52
|
199
|
fazekasgy@52
|
200 # note the inheritance of attributes (use is optional)
|
fazekasgy@52
|
201 MFCC = OutputDescriptor(Generic)
|
fazekasgy@52
|
202 MFCC.identifier = 'mfccs'
|
fazekasgy@52
|
203 MFCC.name = 'MFCCs'
|
fazekasgy@52
|
204 MFCC.description = 'MFCC Coefficients'
|
fazekasgy@52
|
205 MFCC.binNames=map(lambda x: 'C '+str(x),range(self.cnull,int(self.numBands)))
|
fazekasgy@52
|
206 MFCC.unit = None
|
fazekasgy@52
|
207 if self.two_ch and self.m_channels == 2 :
|
fazekasgy@52
|
208 MFCC.binCount = self.m_channels * (int(self.numBands)-self.cnull)
|
fazekasgy@52
|
209 else :
|
fazekasgy@52
|
210 MFCC.binCount = self.numBands-self.cnull
|
fazekasgy@52
|
211
|
fazekasgy@52
|
212 warpedSpectrum = OutputDescriptor(Generic)
|
fazekasgy@52
|
213 warpedSpectrum.identifier='warped-fft'
|
fazekasgy@52
|
214 warpedSpectrum.name='Mel Scaled Spectrum'
|
fazekasgy@52
|
215 warpedSpectrum.description='Mel Scaled Magnitide Spectrum'
|
fazekasgy@52
|
216 warpedSpectrum.unit='Mel'
|
fazekasgy@52
|
217 if self.two_ch and self.m_channels == 2 :
|
fazekasgy@52
|
218 warpedSpectrum.binCount = self.m_channels * int(self.numBands)
|
fazekasgy@52
|
219 else :
|
fazekasgy@52
|
220 warpedSpectrum.binCount = self.numBands
|
fazekasgy@52
|
221
|
fazekasgy@52
|
222 melFilter = OutputDescriptor(Generic)
|
fazekasgy@52
|
223 melFilter.identifier = 'mel-filter-matrix'
|
fazekasgy@52
|
224 melFilter.sampleType='FixedSampleRate'
|
fazekasgy@52
|
225 melFilter.sampleRate=self.m_inputSampleRate/self.m_stepSize
|
fazekasgy@52
|
226 melFilter.name='Mel Filter Matrix'
|
fazekasgy@52
|
227 melFilter.description='Returns the created filter matrix in getRemainingFeatures.'
|
fazekasgy@52
|
228 melFilter.unit = None
|
fazekasgy@52
|
229
|
fazekasgy@52
|
230 return OutputList(MFCC,warpedSpectrum,melFilter)
|
fazekasgy@52
|
231
|
fazekasgy@52
|
232
|
fazekasgy@52
|
233 def getParameterDescriptors(self):
|
fazekasgy@52
|
234
|
fazekasgy@52
|
235 melbands = ParameterDescriptor()
|
fazekasgy@52
|
236 melbands.identifier='melbands'
|
fazekasgy@52
|
237 melbands.name='Number of bands (coefficients)'
|
fazekasgy@52
|
238 melbands.description='Set the number of coefficients.'
|
fazekasgy@52
|
239 melbands.unit = ''
|
fazekasgy@52
|
240 melbands.minValue = 2
|
fazekasgy@52
|
241 melbands.maxValue = 128
|
fazekasgy@52
|
242 melbands.defaultValue = 40
|
fazekasgy@52
|
243 melbands.isQuantized = True
|
fazekasgy@52
|
244 melbands.quantizeStep = 1
|
fazekasgy@52
|
245
|
fazekasgy@52
|
246 cnull = ParameterDescriptor()
|
fazekasgy@52
|
247 cnull.identifier='cnull'
|
fazekasgy@52
|
248 cnull.name='Return C0'
|
fazekasgy@52
|
249 cnull.description='Select if the DC coefficient is required.'
|
fazekasgy@52
|
250 cnull.unit = None
|
fazekasgy@52
|
251 cnull.minValue = 0
|
fazekasgy@52
|
252 cnull.maxValue = 1
|
fazekasgy@52
|
253 cnull.defaultValue = 0
|
fazekasgy@52
|
254 cnull.isQuantized = True
|
fazekasgy@52
|
255 cnull.quantizeStep = 1
|
fazekasgy@52
|
256
|
fazekasgy@52
|
257 two_ch = ParameterDescriptor(cnull)
|
fazekasgy@52
|
258 two_ch.identifier='two_ch'
|
fazekasgy@52
|
259 two_ch.name='Process channels separately'
|
fazekasgy@52
|
260 two_ch.description='Process two channel files separately.'
|
fazekasgy@52
|
261 two_ch.defaultValue = False
|
fazekasgy@52
|
262
|
fazekasgy@52
|
263 minHz = ParameterDescriptor()
|
fazekasgy@52
|
264 minHz.identifier='minHz'
|
fazekasgy@52
|
265 minHz.name='minimum frequency'
|
fazekasgy@52
|
266 minHz.description='Set the lower frequency bound.'
|
fazekasgy@52
|
267 minHz.unit='Hz'
|
fazekasgy@52
|
268 minHz.minValue = 0
|
fazekasgy@52
|
269 minHz.maxValue = 24000
|
fazekasgy@52
|
270 minHz.defaultValue = 0
|
fazekasgy@52
|
271 minHz.isQuantized = True
|
fazekasgy@52
|
272 minHz.quantizeStep = 1.0
|
fazekasgy@52
|
273
|
fazekasgy@52
|
274 maxHz = ParameterDescriptor()
|
fazekasgy@52
|
275 maxHz.identifier='maxHz'
|
fazekasgy@52
|
276 maxHz.description='Set the upper frequency bound.'
|
fazekasgy@52
|
277 maxHz.name='maximum frequency'
|
fazekasgy@52
|
278 maxHz.unit='Hz'
|
fazekasgy@52
|
279 maxHz.minValue = 100
|
fazekasgy@52
|
280 maxHz.maxValue = 24000
|
fazekasgy@52
|
281 maxHz.defaultValue = 11025
|
fazekasgy@52
|
282 maxHz.isQuantized = True
|
fazekasgy@52
|
283 maxHz.quantizeStep = 100
|
fazekasgy@52
|
284
|
fazekasgy@52
|
285 return ParameterList(melbands,minHz,maxHz,cnull,two_ch)
|
fazekasgy@52
|
286
|
fazekasgy@52
|
287
|
fazekasgy@52
|
288 def setParameter(self,paramid,newval):
|
fazekasgy@52
|
289 self.valid = False
|
fazekasgy@52
|
290 if paramid == 'minHz' :
|
fazekasgy@52
|
291 if newval < self.maxHz and newval < self.NqHz :
|
fazekasgy@52
|
292 self.minHz = float(newval)
|
fazekasgy@52
|
293 print 'minHz: ', self.minHz
|
fazekasgy@52
|
294 if paramid == 'maxHz' :
|
fazekasgy@52
|
295 print 'trying to set maxHz to: ',newval
|
fazekasgy@52
|
296 if newval < self.NqHz and newval > self.minHz+1000 :
|
fazekasgy@52
|
297 self.maxHz = float(newval)
|
fazekasgy@52
|
298 else :
|
fazekasgy@52
|
299 self.maxHz = self.NqHz
|
fazekasgy@52
|
300 print 'set to: ',self.maxHz
|
fazekasgy@52
|
301 if paramid == 'cnull' :
|
fazekasgy@52
|
302 self.cnull = int(not int(newval))
|
fazekasgy@52
|
303 if paramid == 'melbands' :
|
fazekasgy@52
|
304 self.numBands = int(newval)
|
fazekasgy@52
|
305 if paramid == 'two_ch' :
|
fazekasgy@52
|
306 self.two_ch = bool(newval)
|
fazekasgy@52
|
307
|
fazekasgy@52
|
308 return
|
fazekasgy@52
|
309
|
fazekasgy@52
|
310 def getParameter(self,paramid):
|
fazekasgy@52
|
311 if paramid == 'minHz' :
|
fazekasgy@52
|
312 return float(self.minHz)
|
fazekasgy@52
|
313 if paramid == 'maxHz' :
|
fazekasgy@52
|
314 return float(self.maxHz)
|
fazekasgy@52
|
315 if paramid == 'cnull' :
|
fazekasgy@52
|
316 return float(not int(self.cnull))
|
fazekasgy@52
|
317 if paramid == 'melbands' :
|
fazekasgy@52
|
318 return float(self.numBands)
|
fazekasgy@52
|
319 if paramid == 'two_ch' :
|
fazekasgy@52
|
320 return float(self.two_ch)
|
fazekasgy@52
|
321 else:
|
fazekasgy@52
|
322 return 0.0
|
fazekasgy@52
|
323
|
fazekasgy@52
|
324 # set numpy process using the 'use_numpy_interface' flag
|
fazekasgy@52
|
325 def process(self,inputbuffers,timestamp):
|
fazekasgy@52
|
326
|
fazekasgy@52
|
327 if not self.update() : return None
|
fazekasgy@52
|
328
|
fazekasgy@52
|
329 if self.m_channels == 2 and self.two_ch :
|
fazekasgy@52
|
330 return self.process2ch(inputbuffers,timestamp)
|
fazekasgy@52
|
331
|
fazekasgy@52
|
332 fftsize = self.m_blockSize
|
fazekasgy@52
|
333
|
fazekasgy@52
|
334 if self.m_channels > 1 :
|
fazekasgy@52
|
335 # take the mean of the two magnitude spectra
|
fazekasgy@52
|
336 complexSpectrum0 = array(inputbuffers[0])
|
fazekasgy@52
|
337 complexSpectrum1 = array(inputbuffers[1])
|
fazekasgy@52
|
338 magnitudeSpectrum0 = abs(complexSpectrum0)[0:fftsize/2]
|
fazekasgy@52
|
339 magnitudeSpectrum1 = abs(complexSpectrum1)[0:fftsize/2]
|
fazekasgy@52
|
340 magnitudeSpectrum = (magnitudeSpectrum0 + magnitudeSpectrum1) / 2
|
fazekasgy@52
|
341 else :
|
fazekasgy@52
|
342 complexSpectrum = array(inputbuffers[0])
|
fazekasgy@52
|
343 magnitudeSpectrum = abs(complexSpectrum)[0:fftsize/2]
|
fazekasgy@52
|
344
|
fazekasgy@52
|
345 # do the computation
|
fazekasgy@52
|
346 melSpectrum = self.warpSpectrum(magnitudeSpectrum)
|
fazekasgy@52
|
347 melCepstrum = self.getMFCCs(melSpectrum,cn=True)
|
fazekasgy@52
|
348
|
fazekasgy@52
|
349 outputs = FeatureSet()
|
fazekasgy@52
|
350 outputs[0] = Feature(melCepstrum[self.cnull:])
|
fazekasgy@52
|
351 outputs[1] = Feature(melSpectrum)
|
fazekasgy@52
|
352 return outputs
|
fazekasgy@52
|
353
|
fazekasgy@52
|
354
|
fazekasgy@52
|
355 # process channels separately (stack the returned arrays)
|
fazekasgy@52
|
356 def process2ch(self,inputbuffers,timestamp):
|
fazekasgy@52
|
357
|
fazekasgy@52
|
358 fftsize = self.m_blockSize
|
fazekasgy@52
|
359
|
fazekasgy@52
|
360 complexSpectrum0 = array(inputbuffers[0])
|
fazekasgy@52
|
361 complexSpectrum1 = array(inputbuffers[1])
|
fazekasgy@52
|
362
|
fazekasgy@52
|
363 magnitudeSpectrum0 = abs(complexSpectrum0)[0:fftsize/2]
|
fazekasgy@52
|
364 magnitudeSpectrum1 = abs(complexSpectrum1)[0:fftsize/2]
|
fazekasgy@52
|
365
|
fazekasgy@52
|
366 # do the computations
|
fazekasgy@52
|
367 melSpectrum0 = self.warpSpectrum(magnitudeSpectrum0)
|
fazekasgy@52
|
368 melCepstrum0 = self.getMFCCs(melSpectrum0,cn=True)
|
fazekasgy@52
|
369 melSpectrum1 = self.warpSpectrum(magnitudeSpectrum1)
|
fazekasgy@52
|
370 melCepstrum1 = self.getMFCCs(melSpectrum1,cn=True)
|
fazekasgy@52
|
371
|
fazekasgy@52
|
372 outputs = FeatureSet()
|
fazekasgy@52
|
373
|
fazekasgy@52
|
374 outputs[0] = Feature(hstack((melCepstrum1[self.cnull:],melCepstrum0[self.cnull:])))
|
fazekasgy@52
|
375
|
fazekasgy@52
|
376 outputs[1] = Feature(hstack((melSpectrum1,melSpectrum0)))
|
fazekasgy@52
|
377
|
fazekasgy@52
|
378 return outputs
|
fazekasgy@52
|
379
|
fazekasgy@52
|
380
|
fazekasgy@52
|
381 def getRemainingFeatures(self):
|
fazekasgy@52
|
382 if not self.update() : return []
|
fazekasgy@52
|
383 frameSampleStart = 0
|
fazekasgy@52
|
384
|
fazekasgy@52
|
385 output_featureSet = FeatureSet()
|
fazekasgy@52
|
386
|
fazekasgy@52
|
387 # the filter is the third output (index starts from zero)
|
fazekasgy@52
|
388 output_featureSet[2] = flist = FeatureList()
|
fazekasgy@52
|
389
|
fazekasgy@52
|
390 while True:
|
fazekasgy@52
|
391 f = Feature()
|
fazekasgy@52
|
392 f.hasTimestamp = True
|
fazekasgy@52
|
393 f.timestamp = frame2RealTime(frameSampleStart,self.m_inputSampleRate)
|
fazekasgy@52
|
394 try :
|
fazekasgy@52
|
395 f.values = self.filterIter.next()
|
fazekasgy@52
|
396 except StopIteration :
|
fazekasgy@52
|
397 break
|
fazekasgy@52
|
398 flist.append(f)
|
fazekasgy@52
|
399 frameSampleStart += self.m_stepSize
|
fazekasgy@52
|
400
|
fazekasgy@52
|
401 return output_featureSet
|