0
$\begingroup$

I'm writing an app in which I need to find the fundamental frequency of a note produced by a trombone. To do this I'm taking the FFT of audio data from a microphone and then using autocorrelation code taken from this question.

Once I've done that I'm then attempting to find the fundamental frequency by finding the highest and second highest peak locations and how many samples they are apart. I then find the amount of time one sample lasts with a sampling rate of 44100 and multiply that by the number of samples between the two peaks to give me the period of the fundamental frequency. Finally I use 1/period to find the fundamental frequency itself. Here's the code I've written for that (in Java):

public double findFundamentalFrequency(double[] autoCorrelatedData){

    double max = Integer.MIN_VALUE;
    double secondMax = Integer.MIN_VALUE;
    int maxLoc = Integer.MIN_VALUE;
    int secondMaxLoc = Integer.MIN_VALUE;

    for(int i = 0; i < autoCorrelatedData.length; i++){
        if(autoCorrelatedData[i] > max){
            secondMaxLoc = maxLoc;
            secondMax = max;

            max = autoCorrelatedData[i];
            maxLoc = i;
        }
        else if(autoCorrelatedData[i] > secondMax){
            secondMax = autoCorrelatedData[i];
            secondMaxLoc = i;
        }
    }

    double samplingPeriod = 1/44100.0;
    //Log.i("a", String.valueOf(maxLoc));
    //Log.i("b", String.valueOf(secondMaxLoc));
    double period = samplingPeriod * Math.abs(maxLoc - secondMaxLoc);
    double fundamentalFreq = 1.0/period;
    return fundamentalFreq;
}

Is this the correct way to find the fundamental frequency using autocorrelation? The answers this gives seem to be incorrect so I'm unsure if I've made a mistake somewhere or if I'm going about this the wrong way.

$\endgroup$
  • $\begingroup$ Since you already have the FFT (frequency data), wouldn't it work to get the fundamental frequency from that directly? $\endgroup$ – Dan Boschen Jul 18 '16 at 13:29
  • $\begingroup$ According to what I've read, when it comes to pitch of a musical note an FFT isn't enough for an accurate reading and one suggestion for getting a better reading was Autocorrelation. $\endgroup$ – PyroPez Jul 18 '16 at 13:35
  • $\begingroup$ I see, that makes sense; the distance between peaks in the Auto-correlation will be the delay between repetitions in your waveform, otherwise known as the period. Your explanation seems accurate but I haven't reviewed your code to see if there is a mistake there. $\endgroup$ – Dan Boschen Jul 18 '16 at 13:38
1
$\begingroup$

Three suggestions:

  • Try searching only over your expected pitch range: from a lag or period a bit shorter than that of your highest expected pitch for the instrument in question, to a lag a bit longer than twice the period of the lowest pitch expected.

  • Make sure there is a dip between your highest and 2nd highest peak, or else you might find the shoulder of the 1st peak, and thus completely miss finding any 2nd peak.

  • You might also want to try using parabolic interpolation to better estimate each pitch period if any are between autocorrelation lags.

$\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.