Mercurial > hg > smacpy
comparison MFCC.py @ 1:d5d4981b58f1
import MFCC code by Gyorgy Fazekas
author | Dan Stowell <danstowell@users.sourceforge.net> |
---|---|
date | Wed, 14 Nov 2012 13:15:15 +0000 |
parents | |
children | 7a20cff05bd6 |
comparison
equal
deleted
inserted
replaced
0:33a9f41169fc | 1:d5d4981b58f1 |
---|---|
1 '''MFCC.py | |
2 | |
3 Calculation of MFCC coefficients from frequency-domain data | |
4 | |
5 Adapted from the Vampy example plugin "PyMFCC" by Gyorgy Fazekas | |
6 http://code.soundsoftware.ac.uk/projects/vampy/repository/entry/Example%20VamPy%20plugins/PyMFCC.py | |
7 | |
8 Centre for Digital Music, Queen Mary University of London. | |
9 Copyright (C) 2009 Gyorgy Fazekas, QMUL. | |
10 ''' | |
11 | |
12 import sys,numpy | |
13 from numpy import abs,log,exp,floor,sum,sqrt,cos,hstack | |
14 from numpy.fft import * | |
15 | |
16 class melScaling(object): | |
17 | |
18 def __init__(self,sampleRate,inputSize,numBands,minHz = 0,maxHz = None): | |
19 '''Initialise frequency warping and DCT matrix. | |
20 Parameters: | |
21 sampleRate: audio sample rate | |
22 inputSize: length of magnitude spectrum (half of FFT size assumed) | |
23 numBands: number of mel Bands (MFCCs) | |
24 minHz: lower bound of warping (default = DC) | |
25 maxHz: higher bound of warping (default = Nyquist frequency) | |
26 ''' | |
27 self.sampleRate = sampleRate | |
28 self.NqHz = sampleRate / 2.0 | |
29 self.minHz = minHz | |
30 if maxHz is None : maxHz = self.NqHz | |
31 self.maxHz = maxHz | |
32 self.inputSize = inputSize | |
33 self.numBands = numBands | |
34 self.valid = False | |
35 self.updated = False | |
36 | |
37 def update(self): | |
38 # make sure this will run only once | |
39 # if called from a vamp process | |
40 if self.updated: return self.valid | |
41 self.updated = True | |
42 self.valid = False | |
43 print 'Updating parameters and recalculating filters: ' | |
44 print 'Nyquist: ',self.NqHz | |
45 | |
46 if self.maxHz > self.NqHz : | |
47 raise Exception('Maximum frequency must be smaller than the Nyquist frequency') | |
48 | |
49 self.maxMel = 1000*log(1+self.maxHz/700.0)/log(1+1000.0/700.0) | |
50 self.minMel = 1000*log(1+self.minHz/700.0)/log(1+1000.0/700.0) | |
51 print 'minHz:%s\nmaxHz:%s\nminMel:%s\nmaxMel:%s\n' \ | |
52 %(self.minHz,self.maxHz,self.minMel,self.maxMel) | |
53 self.filterMatrix = self.getFilterMatrix(self.inputSize,self.numBands) | |
54 self.DCTMatrix = self.getDCTMatrix(self.numBands) | |
55 self.filterIter = self.filterMatrix.__iter__() | |
56 self.valid = True | |
57 return self.valid | |
58 | |
59 def getFilterCentres(self,inputSize,numBands): | |
60 '''Calculate Mel filter centres around FFT bins. | |
61 This function calculates two extra bands at the edges for | |
62 finding the starting and end point of the first and last | |
63 actual filters.''' | |
64 centresMel = numpy.array(xrange(numBands+2)) * (self.maxMel-self.minMel)/(numBands+1) + self.minMel | |
65 centresBin = numpy.floor(0.5 + 700.0*inputSize*(exp(centresMel*log(1+1000.0/700.0)/1000.0)-1)/self.NqHz) | |
66 return numpy.array(centresBin,int) | |
67 | |
68 def getFilterMatrix(self,inputSize,numBands): | |
69 '''Compose the Mel scaling matrix.''' | |
70 filterMatrix = numpy.zeros((numBands,inputSize)) | |
71 self.filterCentres = self.getFilterCentres(inputSize,numBands) | |
72 for i in xrange(numBands) : | |
73 start,centre,end = self.filterCentres[i:i+3] | |
74 self.setFilter(filterMatrix[i],start,centre,end) | |
75 return filterMatrix.transpose() | |
76 | |
77 def setFilter(self,filt,filterStart,filterCentre,filterEnd): | |
78 '''Calculate a single Mel filter.''' | |
79 k1 = numpy.float32(filterCentre-filterStart) | |
80 k2 = numpy.float32(filterEnd-filterCentre) | |
81 up = (numpy.array(xrange(filterStart,filterCentre))-filterStart)/k1 | |
82 dn = (filterEnd-numpy.array(xrange(filterCentre,filterEnd)))/k2 | |
83 filt[filterStart:filterCentre] = up | |
84 filt[filterCentre:filterEnd] = dn | |
85 | |
86 def warpSpectrum(self,magnitudeSpectrum): | |
87 '''Compute the Mel scaled spectrum.''' | |
88 return numpy.dot(magnitudeSpectrum,self.filterMatrix) | |
89 | |
90 def getDCTMatrix(self,size): | |
91 '''Calculate the square DCT transform matrix. Results are | |
92 equivalent to Matlab dctmtx(n) with 64 bit precision.''' | |
93 DCTmx = numpy.array(xrange(size),numpy.float64).repeat(size).reshape(size,size) | |
94 DCTmxT = numpy.pi * (DCTmx.transpose()+0.5) / size | |
95 DCTmxT = (1.0/sqrt( size / 2.0)) * cos(DCTmx * DCTmxT) | |
96 DCTmxT[0] = DCTmxT[0] * (sqrt(2.0)/2.0) | |
97 return DCTmxT | |
98 | |
99 def dct(self,data_matrix): | |
100 '''Compute DCT of input matrix.''' | |
101 return numpy.dot(self.DCTMatrix,data_matrix) | |
102 | |
103 def getMFCCs(self,warpedSpectrum,cn=True): | |
104 '''Compute MFCC coefficients from Mel warped magnitude spectrum.''' | |
105 mfccs=self.dct(numpy.log(warpedSpectrum)) | |
106 if cn is False : mfccs[0] = 0.0 | |
107 return mfccs | |
108 |