kissfft

kissfft pitch detection using cepstrum concept in C/ and Proper input Mic


I'm a beginner to audio signal processing right now i'm try to implement the pitch detection algorithm i have found some step of cepstrum which is

result1 = IFFT(log(abs(FFT(Audio Input))))
peak = max(result);
out_frequency = 1/peak; // last step

Thus, i implement these algorithm in C by using kissfft and portaudio as a library for FFT and IFFT The problem is after i get the IFFT result and do the last step to extract the frequency, the outcome is not i was expect. (Note. I testing by singing in the note A(440Hz))

I'm not sure about i missing the last step of Cepstrum or i doing it wrong.

the microphone to test is my laptop mic, which i know that it is a Condenser Mic. should i change the MIC to Dynamic Mic or it's ok to use the normal Labtop mic

hear is the code i've been implement

kiss_fft_cpx cin[FFT_SIZE];
kiss_fft_cpx cout[FFT_SIZE];
kiss_fft_cpx fftBins[FFT_SIZE];
for ( i = 0; i <FFT_SIZE; i++){
    cin[i].r = zero;
    cin[i].i = zero;
    cout[i].r = zero;
    cout[i].i = zero;
    fftBins[i].r = zero;
    fftBins[i].i = zero;
}
for(j=0;j < FFT_SIZE;j++){
    cin[j].r = *in++ ;
}
kiss_fftr_cfg fftConfiguration = kiss_fftr_alloc( FFT_SIZE, 0, NULL, NULL );
kiss_fftr_cfg ifftConfiguration = kiss_fftr_alloc( FFT_SIZE, 1, NULL, NULL );

// FFT...
kiss_fftr( fftConfiguration, (kiss_fft_scalar*)cin, fftBins );
for(i = 0; i<FFT_SIZE;i++){
    fftBins[i].i = log(fabs(fftBins[i].r));
    fftBins[i].r = zero;
}
// iFFT...
kiss_fftri( ifftConfiguration, fftBins, (kiss_fft_scalar*)cout );
double maxi = 0;
double maxr = 0;
for(i = 0; i<FFT_SIZE;i++){
    if(maxi<cout[j].i){
        maxi = cout[j].i;
    }
    if(maxr<cout[j].r){
        maxr = cout[j].r;
    }
}
printf("%f\t%f\n",maxi,maxr);
double result;
result = 1./maxr;
printf("result = %f\n",result);
free(fftConfiguration);
free(ifftConfiguration);

regard


Solution

  • You are creating a complex array (kiss_fft_cpx) and then using it as a real array (kiss_fft_scalar). You'll want to use kiss_fft_scalar to send your mic samples to kiss_fftr.

    The real fft returns N/2+1 complex points.

    Don't neglect the imaginary part when you compute the magnitude. You can use sqrt(re^2+im^2) or you skip the sqrt without affecting the peak of the cepstrum.

    The frequency of interest needs to be adjusted for the fft size and your sampling frequency.