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