I am working on a project whereby I am trying to determine the exact note played on an electric guitar with a microcontroller (as quickly as possible after the string is plucked) and to use this information (ie digital value of note) to manipulate an audio output via DAC.

I am using an STM32F4, sampling the DC offset and active fitered guitar signal with a 12-bit ADC (sample rates pretty much as fast as I need with timer triggered ADC DMA) and the highest number of F32 FFT points I can achieve with the RAM available is 4096 (ie 8192 samples).

The guitar frequencies I need to measure are between 82Hz and about 831Hz, with a resolution at the low end of 2Hz and about 22Hz at the top.

  • Am I correct in saying minimum sample time to achieve this is about 0.5s, driven by the minimum frequency and resolution requirement?
  • And at higher frequencies I can sample for shorter (with a higher sample rate)?
  • Or is there (hopefully) something I'm missing?
  • Can I measure the lower frequencies with fewer FFT points (and thus samples), saving time?
  • $\begingroup$ Normally for an FFT the frequency resolution is the inverse of the sample time. So for 0.5s of measurement you will always get 2Hz frequency resolution, independent of sampling rate. However you might be able to get a better resolution locally by interlacing two (or more) FFT's using different number of samples/sample time. For example 0.25s and 0.2439s give an effective spacing of 2Hz near 82Hz. However I am not sure what the best way would be to combine these different results and if they even can be trusted. $\endgroup$
    – fibonatic
    Sep 9, 2016 at 23:41
  • $\begingroup$ Assuming you get that FFT the way you want. How would you proceed with detecting the notes? $\endgroup$
    – Jazzmaniac
    Sep 10, 2016 at 9:19
  • $\begingroup$ The note is the first (big) harmonic in the frequency spectrum. $\endgroup$
    – makepeace
    Sep 10, 2016 at 22:18
  • $\begingroup$ @Fibonatic Could you explain how that would work? Do you mean using 2 ADC inputs and sampling for ~0.25 s each and then mixing the results? How would this help? $\endgroup$
    – makepeace
    Oct 15, 2016 at 13:10

2 Answers 2


Your highest frequency is 831 Hz; since undersampling to ignore the sub-82 Hz would only save you 10% sampling rate, let's ignore that possibility.

So, Nyquist says your sampling rate should be at least 1.662 kHz; now, your problem is, as @fibonatic mentioned, that a the freq. resolution of any DFT is alwas

$$\Delta f = \frac{f_\text{Nyquist}}{N_\text{DFT}}\\ \implies\\ N_\text{DFT} = \frac{f_\text{Nyquist}}{\Delta f}$$

and the time taken by capturing of samples you'll need for that DFT is

$$T = \frac{N_\text{DFT}}{f_\text{sample}} = \frac{N_\text{DFT}}{2f_\text{Nyquist}} = \frac{\frac{f_\text{Nyquist}}{\Delta f}}{2f_\text{Nyquist}}= \frac{1}{2\Delta f}$$

So no matter at which rate you'd sample, there's nothing oyu can do about the time period needed for a full-resolution DFT.

You could just pad a shorter observation with zeros, and that will increase your resolution. Point is that you trade resolution for quality, and the variance is going to grow significantly.

The DFT is simply not the right choice here; if you need 2Hz resolution at the lower frequency, you get the same at the higher frequencies without any need.

Honestly, think about it: you're planning to use a DFT that gives you 4096 frequency bins, where you'd need to distinguish maybe 100 tones, if that many.

I'm pretty certain that the cheap guitar tuners you get don't work that way. I'd assume they simply employ dedicated hardware (not firmware like you'd need to write) to implement a simple filterbank – possibly even a IIR filterbank, and if I had a guess, at very low sample bit width, with simple biquads. Or, even simpler, they just have couple of analog filter bandpasses, and just undersample the resulting sample streams and do the same digital filters on all the octaves they preselect that way.

If I had to do this, I'd atually do the same on your microcontroller (by the way, 8192-FFT sounds gigantic for a Cortex-M4, but you know your device better than I do), but with different architecture. Do a rough calculation: If you keep the sampling rate low, how many FIR filters of the different lengths you'll need can you let run over the data? Does implementing your filterbank as a PFB filterbank help? Does making a hierarchic decision (e.g. just first an "octave selector", then depending on the result of that, throwing away half, $\frac38$,$\frac78$,… of the samples and then doing a tone-detection filterbank.

  • $\begingroup$ Really cheap guitar tuners don't filter or FFT or even sample at a fixed sample rate. They just count the time between zero crossings. The better ones check the amplitude against a threshold and maybe reject zero-crossing pitch period estimates that are due to overtones. $\endgroup$
    – hotpaw2
    Sep 10, 2016 at 11:50
  • $\begingroup$ @hotpaw2 even the cheap ones usually have a high pass filter and often also a high frequency roll-off combined with some intended non-linearity to get a robust and predictable overtone structure for periodicity measurement, even if that is only zero crossing counting. Each single phase-synchronised overtone helps with the precision. The really good guitar tuners need to take into account the overtone stretch present in physical strings. That's a lot more tricky. $\endgroup$
    – Jazzmaniac
    Sep 10, 2016 at 16:09
  • $\begingroup$ Thanks for your suggestions. The added caveat is which I think necessitates the use of FFT is that I need to work out the string and fret position, which I can do by analysing the harmonics. Additionally, my current algorithm does a very quick course FFT to find where the first harmonic is, then does a finer FFT at a fast/slow sample rate. Thanks for your suggestion of padding - I will try that. $\endgroup$
    – makepeace
    Sep 10, 2016 at 16:37

Use edge triggered interrupts and the processor clock counter to time-stamp zero crossings. Maybe take ADC samples between zero-crossings and look for an autocorrelation maxima or AMDF lag minima using only zero-crossing lag candidates (the time between every Nth zero-crossing for some reasonable number of N). This might give you a reasonable pitch candidate in as few as 2 or 3 pitch periods, far quicker than a half second lag or more from waiting for enough samples for a long FFT window.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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