private int numberWaveletTransforms = 2; // number of wavelet transform iterations, 3? #endregion Fields #region Constructors /// <summary> /// Create a Mfcc object /// This method is not optimized in the sense that the Mel Filter Bands /// and the DCT is created here (and not read in) /// </summary> /// <param name="winsize">window size</param> /// <param name="srate">sample rate</param> /// <param name="numberFilters">number of filters (MEL COEFFICIENTS). E.g. 36 (SPHINX-III uses 40)</param> /// <param name="numberCoefficients">number of MFCC COEFFICIENTS. E.g. 20</param> public MfccMirage(int winsize, int srate, int numberFilters, int numberCoefficients) { this.numberCoefficients = numberCoefficients; double[] mel = new double[srate/2 - 19]; double[] freq = new double[srate/2 - 19]; int startFreq = 20; // Mel Scale from StartFreq to SamplingRate/2, step every 1Hz for (int f = startFreq; f <= srate/2; f++) { mel[f-startFreq] = LinearToMel(f); freq[f-startFreq] = f; } // Prepare filters double[] freqs = new double[numberFilters + 2]; melScaleFreqsIndex = new int[numberFilters + 2]; for (int f = 0; f < freqs.Length; f++) { double melIndex = 1.0 + ((mel[mel.Length - 1] - 1.0) / (freqs.Length - 1.0) * f); double min = Math.Abs(mel[0] - melIndex); freqs[f] = freq[0]; for (int j = 1; j < mel.Length; j++) { double cur = Math.Abs(mel[j] - melIndex); if (cur < min) { min = cur; freqs[f] = freq[j]; } } melScaleFreqsIndex[f] = MathUtils.FreqToIndex(freqs[f], srate, winsize); } // triangle heights melScaleTriangleHeights = new double[numberFilters]; for (int j = 0; j < melScaleTriangleHeights.Length; j++) { melScaleTriangleHeights[j] = 2.0/(freqs[j+2] - freqs[j]); } double[] fftFreq = new double[winsize/2 + 1]; for (int j = 0; j < fftFreq.Length; j++) { fftFreq[j] = ((srate/2)/(fftFreq.Length -1.0)) * j; } // Compute the MFCC filter Weights filterWeights = new Matrix(numberFilters, winsize/2); for (int j = 0; j < numberFilters; j++) { for (int k = 0; k < fftFreq.Length; k++) { if ((fftFreq[k] > freqs[j]) && (fftFreq[k] <= freqs[j+1])) { filterWeights.MatrixData[j][k] = (float)(melScaleTriangleHeights[j] * ((fftFreq[k]-freqs[j])/(freqs[j+1]-freqs[j]))); } if ((fftFreq[k] > freqs[j+1]) && (fftFreq[k] < freqs[j+2])) { filterWeights.MatrixData[j][k] += (float)(melScaleTriangleHeights[j] * ((freqs[j+2]-fftFreq[k])/(freqs[j+2]-freqs[j+1]))); } } } #if DEBUG if (Mirage.Analyzer.DEBUG_INFO_VERBOSE) { if (Mirage.Analyzer.DEBUG_OUTPUT_TEXT) filterWeights.WriteAscii("melfilters-mirage-orig.ascii"); //filterWeights.DrawMatrixGraph("melfilters-mirage-orig.png"); } #endif // Compute the DCT // This whole section is copied from GetDCTMatrix() from CoMirva package dct = new DctComirva(numberCoefficients, numberFilters).DCTMatrix; #if DEBUG if (Mirage.Analyzer.DEBUG_INFO_VERBOSE) { if (Mirage.Analyzer.DEBUG_OUTPUT_TEXT) dct.WriteAscii("dct-mirage-orig.ascii"); //dct.DrawMatrixGraph("dct-mirage-orig.png"); } #endif }