1
$\begingroup$

I am trying to implement MFCC's from scratch in C++. In each frame, I am processing real-valued data to construct MFCC vectors. Although I think that my implementation is correct, the testing result is very interesting for me. Here is how I implement the MFCC step by step, then the confusing things becomes.

This is how I implemented the filters. I am interested in signal frequencies as 200 Hz as min and 800 Hz as max. I am dealing with only one frame now.(No loop on frames)

std::vector<double> MFCC(NUM_MFCSS);
std::vector<std::vector<double>> filters(
    NUM_FILTERS, std::vector<double>(FFT_SIZE / 2 + 1));
double mel_min = 2595 * log10(1 + (200 / 700));
double mel_max = 2595 * log10(1 + (800 / 700));
double mel_spacing = (mel_max - mel_min) / (NUM_FILTERS + 1);
for (int i = 0; i < NUM_FILTERS; i++) {
  double mel_center = mel_min + mel_spacing * (i + 1);
  double f_min = 700 * (pow(10, mel_center / 2595) - 1);
  double f_max = 700 * (pow(10, (mel_center + mel_spacing) / 2595) - 1);
  double f_spacing = (f_max - f_min) / FFT_SIZE;
  for (int j = 0; j < FFT_SIZE / 2 + 1; j++) {
    double f = f_min + f_spacing * j;
    double mel = 2595 * log10(1 + (f / 700));
    if (mel < mel_center - mel_spacing / 2) {
      filters[i][j] = (mel - (mel_center - mel_spacing)) / (mel_spacing / 2);
    } else if (mel > mel_center + mel_spacing / 2) {
      filters[i][j] = ((mel_center + mel_spacing) - mel) / (mel_spacing / 2);
    } else {
      filters[i][j] = 1;
    }
  }
}

Converting it to the mel-scale and appropriate triangular filters are constructed.

Then I apply Hanning Window and FFT. I checked FFT works correctly. Then I tried to get filter-bank energies with dot-product of filters and fft's as follows:

std::vector<double> energies(NUM_FILTERS, 0);
for (int j = 0; j < NUM_FILTERS; j++) {
  for (int k = 0; k < (FFT_SIZE / 2) + 1; k++) {
    energies[j] +=
        filters[j][k] * (fft[k][0] * fft[k][0] + fft[k][1] * fft[k][1]);
  }
}

Once I applied the log of energies and DCT operation, I obtained the MFCC coefficients.

for (int j = 1; j < NUM_MFCSS + 1; j++) {
  double sum = 0;
  for (int k = 0; k < NUM_FILTERS; k++) {
    sum += log10(energies[k]) * std::cos(M_PI * j * (k - 0.5) / NUM_FILTERS);
  }
  MFCC[j] = sum;
}

My test signal is simply sinusoid of the frequencies in the range [200 Hz,800 Hz].

I applied hoop size to see the other frames energy and MFCC coefficients. What I observe are the following

  1. Filter-bank energies are constant for every index.
  2. MFCC coefficients are 0 in odd indexes, and in even indexes they are strictly decreasing. I could not interpret this two things. Why they are the case? Did you see any implementational/logical mistakes that I wrote?
$\endgroup$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.