In short I followed the procedure in link 5.
Frame the signal into short frames. For each frame calculate the periodogram estimate of the power spectrum. Apply the mel filterbank to the power spectra, sum the energy in each filter. Take the logarithm of all filterbank energies. Take the DCT of the log filterbank energies. Keep DCT coefficients 2-13, discard the rest.
For step 1&2: I compute the STFT (Complex STFT matrix (numFrames x NFFT)) and then abs(magnitude) square yields periodogram estimate of the power spectrum.
for step 3: I used the numpy.fft.fftfreq which is where I am a little skeptical. The frequencies (Frequency axis values in Hz (NFFT) )to get the MEL scale were the ones which I got from the numpy.fft.fftfreq.
Are these frequencies right?
I somehow feel the MFCC values are incorrect because they are in a cycle.
Here are the first five columns of the 12 rows (since I consider the 12 coefficients)
Since, I cannot post the entire code, I will post the important parts:
part 1 of the code is with the wave file:
self.samples, sampleRate= loadWAV(fileName, mono=True, startSec=None, endSec=None)
self.X, self.freqHz, timeSec = stft(self.samples)
where X: (2D ndarray) Complex STFT matrix (numFrames x NFFT) timeVec: (ndarray) Time axis values in seconds (numFrames) freqHz: (ndarray) Frequency axis values in Hz (NFFT)
self.mfccFeature2 = run(self.X, self.freqHz)
where run leads to this :
def run(self, mag, freq, nFilters=26, nCoeff=12): mag = mag**2 # create filterbank for given frequency axis filterBank = melFilterbankLinFreq(freq, nFilters=26) """change 1 : since there is a mismatch of operands, the * function is changed to dot """ # filter original magnitude spectrogram (original) magFilt = np.tile(mag, (nFilters, 1)) * filterBank.T **New version where I think the problem exists:** magFilt_1 = np.tile(mag, (nFilters, 1)) magFilt = np.dot(magFilt_1, filterBank.T) # accumulate energy values over filterbanks fbEnergyLog = np.log(np.sum(magFilt, axis=1)+.0000001) # perform DCT and keep only first nCoeff coefficients # DCT can work only on real values and the values are complex 128 instead of float return dct(fbEnergyLog.real)[1:nCoeff+1]