Mercurial > hg > batch-feature-extraction-tool
view Source/MFCC.cpp @ 1:e86e9c111b29
Updates stuff that potentially fixes the memory leak and also makes it work on Windows and Linux (Need to test). Still have to fix fftw include for linux in Jucer.
author | David Ronan <d.m.ronan@qmul.ac.uk> |
---|---|
date | Thu, 09 Jul 2015 15:01:32 +0100 |
parents | 25bf17994ef1 |
children | 345acbd06029 |
line wrap: on
line source
/* ============================================================================== MFCC.cpp Created: 2 Sep 2014 3:30:50pm Author: david.ronan ============================================================================== */ #include "MFCC.h" #include <math.h> //#include <windows.h> //----------------------------------------------------------------------------- ComputeMFCC void MFCC::ComputeMFCC(float* magnitude, std::vector<float> &mfccs) { //Apply the Mel Filters to the spectrum magnitude: for(int i=0; i<m_iTotalMFCCFilters; i++) { //Multiply spectrum with spectral mask vDSP_vmul(magnitude, 1, m_ppMFCCFilters[i], 1, m_pfTempMelFilterResult, 1, m_pMFCCFilterLength[i]); //Sum the values of each bins m_fMelFilteredFFT[i] = vDSP_sve(m_pfTempMelFilterResult, 1, m_pMFCCFilterLength[i]); //Log compression float filterOut = log10(m_fMelFilteredFFT[i]*10.f+1.f); m_fMelFilteredFFT[i]=filterOut; } for(int j = 0; j < m_iNumMFCCCoefs; j++) { //Cosine Transform to reduce dimensionality: vDSP_mmul(m_ppMFFC_DCT, 1, m_fMelFilteredFFT, 1, m_pMFCC, 1, m_iNumMFCCCoefs, 1, m_iTotalMFCCFilters); mfccs.push_back(m_pMFCC[j]); } } //----------------------------------------------------------------------------- initMFFCvariables void MFCC::initMFFCvariables(int NCoeffs, int Nfft, float fSampleRate) { m_iNumMFCCCoefs = NCoeffs; m_pMFCC = new float[m_iNumMFCCCoefs]; //Add a value to take into account the 0 coefficient int iStartMfccCoeff = 1; //Mel FilterBank parameters float fLowestFreq = 133.3333f; int iNumLinearFilter = 13; float fLinearSpacing = 66.66666666f; int iNumLogFilters = 27; float fLogSpacing = 1.0711703f; float fFreqPerBin = fSampleRate / (float)(Nfft); m_iTotalMFCCFilters = iNumLinearFilter + iNumLogFilters; m_fMelFilteredFFT = new float[m_iTotalMFCCFilters]; m_pMFCCFilterStart = new int[m_iTotalMFCCFilters]; m_pMFCCFilterLength = new int[m_iTotalMFCCFilters]; m_ppMFCCFilters = new float*[m_iTotalMFCCFilters]; float FilterLimits[3]; int iFilterWidthMax = 0; for(int i = 0; i < m_iTotalMFCCFilters; i++) { for(int j = 0; j < 3; j++) { if(i + j < iNumLinearFilter) { FilterLimits[j] = (i + j) * fLinearSpacing + fLowestFreq; } else { float fLowestLogFreq = (iNumLinearFilter-1) * fLinearSpacing + fLowestFreq; FilterLimits[j] = fLowestLogFreq * powf(fLogSpacing, (float)((i + j) - iNumLinearFilter + 1)); } } float fTriangleHeight = 2.f / (FilterLimits[2] - FilterLimits[0]); int iStartBin = (int)(ceil(FilterLimits[0] / fFreqPerBin)); int iStopBin = (int)(floor(FilterLimits[2] / fFreqPerBin)); int iFilterWidth = iStopBin-iStartBin+1; m_pMFCCFilterStart[i] = iStartBin; m_pMFCCFilterLength[i] = iFilterWidth; m_ppMFCCFilters[i] = new float[iFilterWidth]; if(iFilterWidth > iFilterWidthMax) { iFilterWidthMax = iFilterWidth; } for(int n=iStartBin; n<iStopBin+1; n++) { float fFreq = n * fFreqPerBin; if(fFreq <= FilterLimits[1]) { float factor =(fFreq-FilterLimits[0]) / (FilterLimits[1] - FilterLimits[0]); float filterVal = fTriangleHeight * factor; m_ppMFCCFilters[i][n - iStartBin] = filterVal; } else { float factor =(FilterLimits[2] - fFreq) / (FilterLimits[2] - FilterLimits[1]); float filterVal = fTriangleHeight * factor; m_ppMFCCFilters[i][n - iStartBin] = filterVal ; } } } m_pfTempMelFilterResult = new float[iFilterWidthMax]; //Compute the DCT reduction matrix m_ppMFFC_DCT = new float[NCoeffs * m_iTotalMFCCFilters]; float fScaleDCTMatrix = 1.f / sqrtf(m_iTotalMFCCFilters / 2.f); for(int n = iStartMfccCoeff; n < NCoeffs+iStartMfccCoeff; n++) { for(int m = 0; m < m_iTotalMFCCFilters; m++) { m_ppMFFC_DCT[(n - iStartMfccCoeff) * m_iTotalMFCCFilters + m] = fScaleDCTMatrix * cosf(n * (m + 0.5f) * 3.141592653589793f / m_iTotalMFCCFilters); } } } //----------------------------------------------------------------------------- freeMFCCmemory void MFCC::freeMFCCmemory() { if(m_pMFCC != nullptr) { delete(m_pMFCC); m_pMFCC=nullptr; } if(m_ppMFFC_DCT != nullptr) { delete(m_ppMFFC_DCT); m_ppMFFC_DCT=nullptr; } if(m_fMelFilteredFFT != nullptr) { delete(m_fMelFilteredFFT); m_fMelFilteredFFT=nullptr; } if(m_pMFCCFilterStart != nullptr) { delete(m_pMFCCFilterStart); m_pMFCCFilterStart=nullptr; } if(m_pMFCCFilterLength != nullptr) { delete(m_pMFCCFilterLength); m_pMFCCFilterLength=nullptr; } if(m_pfTempMelFilterResult != nullptr) { delete(m_pfTempMelFilterResult); m_pfTempMelFilterResult=nullptr; } if(m_ppMFCCFilters != nullptr) { for(int i=0; i<m_iTotalMFCCFilters; i++) { if(m_ppMFCCFilters[i] != nullptr) { delete(m_ppMFCCFilters[i]); m_ppMFCCFilters[i]=nullptr; } } delete (m_ppMFCCFilters); m_ppMFCCFilters=nullptr; } } //----------------------------------------------------------------------------- vDSP_vmul inline void MFCC::vDSP_vmul(float* v1,int stride1, float* v2, int stride2, float* out, int outstride, int iNumSamples) { for(int i=0; i<iNumSamples; i++) { out[i*outstride] = v1[i*stride1] * v2[i*stride2]; } } //----------------------------------------------------------------------------- vDSP_sve inline float MFCC::vDSP_sve(float* v, int , int iNumSamples) { float fSum = 0; for(int i=0; i < iNumSamples; i++) { fSum += v[i]; } return fSum; } //----------------------------------------------------------------------------- vDSP_mmul inline void MFCC::vDSP_mmul(float* v1, int , float* v2, int , float* &vout, int , int M, int , int P) { for(int m = 0; m < M; m++) { float fProdSum = 0.f; for(int p = 0; p < P; p++) { fProdSum+=v1[m * P + p] * v2[p]; } vout[m]=fProdSum; } }