0
$\begingroup$

I want to find the fundamental frequency for human voice in an Android Application. I want to use autocorrelation method. My code is this:

public double calculateFFT(double[] signal)

     {
      final int mNumberOfFFTPoints =1024;

      double[] magnitude = new double[mNumberOfFFTPoints/2];
      DoubleFFT_1D fft = new DoubleFFT_1D(mNumberOfFFTPoints);
      double[] fftData = new double[mNumberOfFFTPoints*2];
      double max_index=-1;
      double max_magnitude=-1;


      final float sampleRate=44100;
      double frequency;

      for (int i=0;i<mNumberOfFFTPoints;i++){

       //fftData[2 * i] = buffer[i+firstSample];
       fftData[2 * i] = signal[i];  //da controllare
       fftData[2 * i + 1] = 0;

       fft.complexForward(fftData);
      }

      for(int i = 0; i < mNumberOfFFTPoints/2; i++){

       magnitude[i]=Math.sqrt((fftData[2*i] * fftData[2*i]) + (fftData[2*i + 1] * fftData[2*i + 1]));

       if (max_magnitude<magnitude[i]){
        max_magnitude=magnitude[i];
        max_index=i;
       }
      }
      return frequency=sampleRate*(double)max_index/(double)mNumberOfFFTPoints;

 }

I used "edu.emory.mathcs.jtransforms.fft.DoubleFFT_1D;" Is my "return" the value of fundamental frequency or not?

thanks


I changed my code in this mode:

    public double calculateFFT(double[] signal)

    {

        final int mNumberOfFFTPoints =1024;
        double[] magnitude = new double[mNumberOfFFTPoints/2];
        DoubleFFT_1D fft = new DoubleFFT_1D(mNumberOfFFTPoints);
        double[] fftData = new double[mNumberOfFFTPoints*2];

        double max_index=-1;
        double max_magnitude=-1;

        final float sampleRate=44100;
        double frequency;


        for (int i=0;i<mNumberOfFFTPoints;i++){

            fftData[2 * i] = signal[i];  
            fftData[2 * i + 1] = 0;

            }

        fft.complexForward(fftData);

        for(int i = 0,j=0; i < mNumberOfFFTPoints/2; i += 2,j++){

            magnitude[j]=Math.sqrt((fftData[2*i] * fftData[2*i]) + (fftData[2*i + 1] * fftData[2*i + 1]));

        }
         fft.complexInverse(fftData, false);

         for(int i=0;i<magnitude.length;i++)

            if (max_magnitude<magnitude[i]){
                max_magnitude=magnitude[i];
                max_index=i;
            }

            return frequency=sampleRate*(double)max_index/(double)mNumberOfFFTPoints;

}

in this mode I calculate autocorrelation thanks inverse transform "fft.complexInverse(fftData, false);"; isn't it? And also in this case isn't the "return" the fundamental frequency?

$\endgroup$
  • $\begingroup$ This is a slightly harder problem than you may think. $\endgroup$ – Aaron May 26 '14 at 16:59
  • $\begingroup$ Duplicate - cross-posted on StackOverflow: stackoverflow.com/questions/23867867/… - this question has been posted by the OP three times on StackOverflow and now once here, and OP does not seem to be taking any notice of the helpful answers and comments already posted in response to the previous iterations of his questions. $\endgroup$ – Paul R May 27 '14 at 9:19
2
$\begingroup$

Very often not. Your posted code is for finding an FFT magnitude, not an autocorrelation result, and thus likely to fail at estimating the fundamental pitch of sound/voice/music with typically high overtone or harmonic content.

$\endgroup$
  • $\begingroup$ thanks for your answer, I wrote other code down, can you help me, please? $\endgroup$ – user3582433 May 27 '14 at 7:08
1
$\begingroup$

Your code displays a common misconception of fundamental frequency i.e. assuming the frequency of greatest magnitude is the fundamental. If you google 'the missing fundamental problem' you will soon realise this is not the case.

Autocorrelation or summary autocorrelation are the way to go for this problem.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.