# Getting a more accurate frequency read from autocorrelation and peak-detection algorithm

For a project I am attempting to create an automatic tuner for a guitar, which reads the audio from the guitar jack, determines the frequency and adjusts the string by a motor.

Using http://www.instructables.com/id/Reliable-Frequency-Detection-Using-DSP-Techniques/ the algorithm is quite accurate.

void setup() {
sum = 0;
pd_state = 0;
int period = 0;
// Autocorrelation
for(i=0; i < samples; i++)
{
sum_old = sum;
sum = 0;
for(k=0; k < samples-i; k++) sum += (values[k])*(values[k+i]);

// Peak Detect State Machine
if (pd_state == 2 && (sum-sum_old) <=0)
{
period = i;
pd_state = 3;
}
if (pd_state == 1 && (sum > thresh) && (sum-sum_old) > 0) pd_state = 2;
if (!i) {
thresh = sum * 0.5;
pd_state = 1;
}
}
// Frequency identified in Hz
freq_per = realFreq/period;
lcd.cls();
lcd.printf("%f",freq_per);
}


At the end the frequency is determined by the by dividing the realFreq, which is the precise reading frequency with the period determined by the peak detection portion.

The frequency is quite accurate between 40-200 Hz normally about 0.5 Hz out which is accurate enough for my needs. But above 200 Hz the accuracy falls to 2-3Hz.

Is there a technique to improve the accuracy of this function. The sampling frequency is 4410 and I wanted to reduce this to improve the speed but keep the accuracy as high as possible.

Thank you.

If you were using an omnidirectional microphone to pick up the instrument sound you wanted to determine the pitch for, then using the autocorrelation method of determining the period of a waveform could have some merit in reducing the impact of random uncorrelated noise.

But, the way it is attempted to be used here seems to be an incomplete match to the problem's specifications. The signal is not expected to have high levels of noise, the hardware platform is "weak" (limited wordlength and processing power) and all that the selected method is doing is a "fancy" way of deriving a (periodic) signal's period. In addition to this, at some point later on, the same platform is going to have to control the motors too.

Since the signal will be coming directly from the guitar's pickup, it will be loud enough and clean (assuming no problems with the instrument's wiring). In this case, the zero-crossing method is probably the better choice for a guitar tuner. All that the processor would be doing is count how much time passes between setting and resetting a counter as the signal crosses a "zero voltage" point within limits. This method would return the pitch of a guitar string with much higher accuracy given the clock speeds that an Arduino is capable of running at and also leave plenty of time to the CPU to perform other tasks with ease (such as controlling the motors).