d@0
|
1 /*
|
d@9
|
2 ==============================================================================
|
d@0
|
3
|
d@9
|
4 MFCC.cpp
|
d@9
|
5 Created: 2 Sep 2014 3:30:50pm
|
d@9
|
6 Author: david.ronan
|
d@0
|
7
|
d@9
|
8 ==============================================================================
|
d@0
|
9 */
|
d@0
|
10
|
d@0
|
11 #include "MFCC.h"
|
d@0
|
12 #include <math.h>
|
d@0
|
13
|
d@0
|
14 //----------------------------------------------------------------------------- ComputeMFCC
|
d@4
|
15 void MFCC::ComputeMFCC(std::vector<float> magnitude, std::vector<float> &mfccs)
|
d@0
|
16 {
|
d@9
|
17 //Apply the Mel Filters to the spectrum magnitude:
|
d@9
|
18 for (int i = 0; i < m_iTotalMFCCFilters; i++)
|
d@9
|
19 {
|
d@9
|
20 //Multiply spectrum with spectral mask
|
d@9
|
21 MultiplyVector(magnitude, m_ppMFCCFilters[i], m_pfTempMelFilterResult, m_pMFCCFilterLength[i]);
|
d@0
|
22
|
d@9
|
23 //Sum the values of each bins
|
d@9
|
24 m_fMelFilteredFFT[i] = SumVector(m_pfTempMelFilterResult);
|
d@0
|
25
|
d@9
|
26 //Log compression
|
d@9
|
27 float filterOut = log10(m_fMelFilteredFFT[i] * 10.f + 1.f);
|
d@9
|
28 m_fMelFilteredFFT[i] = filterOut;
|
d@9
|
29 }
|
d@0
|
30
|
d@9
|
31 for (int j = 0; j < m_iNumMFCCCoefs; j++)
|
d@9
|
32 {
|
d@9
|
33 //Cosine Transform to reduce dimensionality:
|
d@9
|
34 MultiplySumVector(m_ppMFFC_DCT, m_fMelFilteredFFT, m_pMFCC, m_iNumMFCCCoefs, m_iTotalMFCCFilters);
|
d@9
|
35 mfccs.push_back(m_pMFCC[j]);
|
d@9
|
36 }
|
d@0
|
37
|
d@0
|
38 }
|
d@0
|
39
|
d@0
|
40
|
d@0
|
41 //----------------------------------------------------------------------------- initMFFCvariables
|
d@0
|
42 void MFCC::initMFFCvariables(int NCoeffs, int Nfft, float fSampleRate)
|
d@0
|
43 {
|
d@9
|
44 m_iNumMFCCCoefs = NCoeffs;
|
d@0
|
45
|
d@9
|
46 m_pMFCC = std::vector<float>(m_iNumMFCCCoefs, 0);
|
d@0
|
47
|
d@0
|
48
|
d@9
|
49 //Add a value to take into account the 0 coefficient
|
d@9
|
50 int iStartMfccCoeff = 1;
|
d@0
|
51
|
d@9
|
52 //Mel FilterBank parameters
|
d@9
|
53 float fLowestFreq = 133.3333f;
|
d@9
|
54 int iNumLinearFilter = 13;
|
d@9
|
55 float fLinearSpacing = 66.66666666f;
|
d@9
|
56 int iNumLogFilters = 27;
|
d@9
|
57 float fLogSpacing = 1.0711703f;
|
d@9
|
58 float fFreqPerBin = fSampleRate / static_cast<float>(Nfft);
|
d@9
|
59 m_iTotalMFCCFilters = iNumLinearFilter + iNumLogFilters;
|
d@0
|
60
|
d@9
|
61 m_fMelFilteredFFT = std::vector<float>(m_iTotalMFCCFilters, 0);
|
d@9
|
62 m_pMFCCFilterStart = std::vector<int>(m_iTotalMFCCFilters, 0);
|
d@9
|
63 m_pMFCCFilterLength = std::vector<int>(m_iTotalMFCCFilters, 0);
|
d@9
|
64 m_ppMFCCFilters = std::vector<std::vector<float>>(m_iTotalMFCCFilters);
|
d@0
|
65
|
d@9
|
66 float FilterLimits[3];
|
d@9
|
67 int iFilterWidthMax = 0;
|
d@9
|
68 for (int i = 0; i < m_iTotalMFCCFilters; i++)
|
d@0
|
69 {
|
d@9
|
70 for (int j = 0; j < 3; j++)
|
d@0
|
71 {
|
d@9
|
72 if (i + j < iNumLinearFilter)
|
d@1
|
73 {
|
d@9
|
74 FilterLimits[j] = (i + j) * fLinearSpacing + fLowestFreq;
|
d@9
|
75 }
|
d@9
|
76 else
|
d@9
|
77 {
|
d@9
|
78 float fLowestLogFreq = (iNumLinearFilter - 1) * fLinearSpacing + fLowestFreq;
|
d@9
|
79 FilterLimits[j] = fLowestLogFreq * powf(fLogSpacing, static_cast<float>((i + j) - iNumLinearFilter + 1));
|
d@0
|
80 }
|
d@0
|
81 }
|
d@0
|
82
|
d@9
|
83 float fTriangleHeight = 2.f / (FilterLimits[2] - FilterLimits[0]);
|
d@9
|
84
|
d@9
|
85 int iStartBin = static_cast<int>(ceil(FilterLimits[0] / fFreqPerBin));
|
d@9
|
86 int iStopBin = static_cast<int>(floor(FilterLimits[2] / fFreqPerBin));
|
d@9
|
87
|
d@9
|
88 int iFilterWidth = iStopBin - iStartBin + 1;
|
d@9
|
89 m_pMFCCFilterStart[i] = iStartBin;
|
d@9
|
90 m_pMFCCFilterLength[i] = iFilterWidth;
|
d@9
|
91 m_ppMFCCFilters[i] = std::vector<float>(iFilterWidth, 0);
|
d@9
|
92
|
d@9
|
93 if (iFilterWidth > iFilterWidthMax)
|
d@9
|
94 {
|
d@9
|
95 iFilterWidthMax = iFilterWidth;
|
d@9
|
96 }
|
d@9
|
97
|
d@9
|
98 for (int n = iStartBin; n<iStopBin + 1; n++)
|
d@9
|
99 {
|
d@9
|
100 float fFreq = n * fFreqPerBin;
|
d@9
|
101 if (fFreq <= FilterLimits[1])
|
d@9
|
102 {
|
d@9
|
103 float factor = (fFreq - FilterLimits[0]) / (FilterLimits[1] - FilterLimits[0]);
|
d@9
|
104 float filterVal = fTriangleHeight * factor;
|
d@9
|
105 m_ppMFCCFilters[i][n - iStartBin] = filterVal;
|
d@9
|
106 }
|
d@9
|
107 else
|
d@9
|
108 {
|
d@9
|
109 float factor = (FilterLimits[2] - fFreq) / (FilterLimits[2] - FilterLimits[1]);
|
d@9
|
110 float filterVal = fTriangleHeight * factor;
|
d@9
|
111 m_ppMFCCFilters[i][n - iStartBin] = filterVal;
|
d@9
|
112 }
|
d@9
|
113 }
|
d@9
|
114 }
|
d@9
|
115
|
d@9
|
116 m_pfTempMelFilterResult = std::vector<float>(iFilterWidthMax, 0);
|
d@9
|
117
|
d@9
|
118 //Compute the DCT reduction matrix
|
d@9
|
119 m_ppMFFC_DCT = std::vector<float>(NCoeffs * m_iTotalMFCCFilters, 0);
|
d@9
|
120
|
d@9
|
121 float fScaleDCTMatrix = 1.f / sqrtf(m_iTotalMFCCFilters / 2.f);
|
d@9
|
122
|
d@9
|
123 for (int n = iStartMfccCoeff; n < NCoeffs + iStartMfccCoeff; n++)
|
d@9
|
124 {
|
d@9
|
125 for (int m = 0; m < m_iTotalMFCCFilters; m++)
|
d@9
|
126 {
|
d@9
|
127 m_ppMFFC_DCT[(n - iStartMfccCoeff) * m_iTotalMFCCFilters + m] = fScaleDCTMatrix * cosf(n * (m + 0.5f) * 3.141592653589793f / m_iTotalMFCCFilters);
|
d@9
|
128 }
|
d@0
|
129 }
|
d@0
|
130 }
|
d@0
|
131
|
d@9
|
132 //----------------------------------------------------------------------------- MultiplyVector
|
d@9
|
133 void MFCC::MultiplyVector(std::vector<float> v1, std::vector<float> v2, std::vector<float> &out, int iNumSamples)
|
d@0
|
134 {
|
d@9
|
135
|
d@9
|
136 for (int i = 0; i < iNumSamples; i++)
|
d@9
|
137 {
|
d@9
|
138 out[i] = v1[i] * v2[i];
|
d@9
|
139 }
|
d@0
|
140 }
|
d@0
|
141
|
d@9
|
142 //----------------------------------------------------------------------------- SumVector
|
d@9
|
143 float MFCC::SumVector(std::vector<float> v)
|
d@0
|
144 {
|
d@9
|
145 float fSum = 0;
|
d@0
|
146
|
d@9
|
147 for (size_t i = 0; i < v.size(); i++)
|
d@9
|
148 {
|
d@9
|
149 fSum += v[i];
|
d@9
|
150 }
|
d@0
|
151
|
d@9
|
152 return fSum;
|
d@0
|
153 }
|
d@0
|
154
|
d@9
|
155 //----------------------------------------------------------------------------- MultiplySumVector
|
d@9
|
156 void MFCC::MultiplySumVector(std::vector<float> v1, std::vector<float> v2, std::vector<float> &vout, int M, int P)
|
d@0
|
157 {
|
d@9
|
158 for (int m = 0; m < M; m++)
|
d@9
|
159 {
|
d@9
|
160 float fProdSum = 0.f;
|
d@0
|
161
|
d@9
|
162 for (int p = 0; p < P; p++)
|
d@9
|
163 {
|
d@9
|
164 fProdSum += v1[m * P + p] * v2[p];
|
d@9
|
165 }
|
d@1
|
166
|
d@9
|
167 vout[m] = fProdSum;
|
d@9
|
168 }
|
d@4
|
169 }
|