1
$\begingroup$

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.

$\endgroup$
1
$\begingroup$

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).

For more information on pitch detection in DSP, please see this link.

For more information on zero crossing, please see this link (linked from the same Instructables article that was posted along with the question).

For more information on the basic technique required to create the circuit that will be converting the guitar's signal to the digital form that Arduino expects, please see this link.

$\endgroup$
1
$\begingroup$

A zero crossing count method alone might be unreliable over the full pitch range.

But zero crossing measurements averaged over enough periods in conjunction with your autocorrelation method might be usable to improve an initial frequency estimate. e.g. only use the zero crossing information if it stays within a few percent of the autocorrelation estimate and that estimate is higher than a certain frequency (such as 199 Hz in your case). A low performance processor that can do a correlation estimate can likely also do a simultaneous zero crossing count measurement.

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