Fiver:
I am interested in creating various visual effects based on analog audio signals. I started by trying to detect pitches in the chromatic scale for the frequency range of a 22-fret guitar in standard tuning:
A lot of people have posted on this forum intending to build a guitar tuner with an Arduino Uno, and using the FFT for automatic pitch detection. I haven't seen anyone report success. If you're going to do pitch detection this way, you'll have to be ingenious.
82.4 (E2) - 1174.7 Hz (D6) ...
... sampling rate ... ~2350 ...
Accurately identifying 1174 Hz with a sample rate of 2350 Hz will be challenging. The Nyquist criterion says that the sample rate has to exceed twice the frequency of the highest frequency signal component with significant content, not the highest frequency that you're interested in. 2350 is pretty close to twice 1174, so doing this detection will take a nearly perfect brick-wall filter. You'll need a higher sample rate, and an aggressive filter. Forum member pito has identified an eighth-order single-chip elliptical filter family that uses switched capacitors, whose cutoff frequency depends on either an external capacitor or an external clock signal. The datasheets can be reached from here: Mixed-signal and digital signal processing ICs | Analog Devices.
I keep running into resolution limitations for low frequencies due to frequency bin size.
The resolution of the FFT can be improved with parabolic interpolation. Here's a description from a guy at Stanford: Peak Detection (Steps 3 and 4). The idea is that an input signal whose frequency doesn't exactly match a specific FFT output frequency will show up spread over several adjacent FFT output values. It's estimated by identifying a local peak in the bins, and fitting a parabola to the the peak and its two adjacent values, calculating the axis, and calling that the estimated frequency. I've never tried it with the FFT, but it has worked for me with YIN. Note, though, that the input values to the interpolation are completely different kinds of objects than the output of the FFT. You may get different results.
Alternatively, I could use a different algorithm, such as the YIN used in these projects:
http://www.instructables.com/id/Arduino-Frequency-Detection/
The Deambulatory Matrix: Digital Chromatic Guitar Tuner (2008)
The first referenced project doesn't use YIN. It estimates pitch by examining the time between zero-crossings with the highest slope. That's going to have a high error rate, because guitar harmonics aren't precisely integer multiples of the fundamental - their phase rotates with regard to the phase of the fundamental, so they contribute their slope to the sum at varying points in the cycle. As for what the error rate might be, I can't say. It might be entirely acceptable.
I would also like to detect the fundamental frequency of strummed chords, and this method seems vulnerable to complex signals.
YIN isn't applicable to polyphonic signals. It looks for a near match between one segment of the input and another segment some time later, and uses the time interval between those two segments as the inverse of the frequency. If a signal has two components of roughly equal amplitude at, say, 1 Hz and 1.5 HZ, YIN will estimate the [edit: revise flawed logic] frequency at the least common multiple, 3 Hz. signal's period as the least common multiple of their periods, 1 second and 2/3 seconds. That's 3 seconds, and the frequency estimate will be 1/3 Hz.
If you mean that you want to identify the lowest component of the signal, you're in for a bit of a challenge: chord components can easily be within a minor third of one another, overlapping in the FFT output enough to confound parabolic interpolation. If you want to do that reliably, I think you'll have to look at multiple cycles at fine resolution.
You don't say that you hope to identify individual strings in a polyphonic signal. If you do, that's a lot of work. Here's an Apple patent on that process: US8592670B2 - Polyphonic note detection - Google Patents. It's feasible with an iPhone, running at more than a gigahertz, with gigabytes of storage; less feasible on an Arduino.
I'm beginning to wonder whether the Arduino is up to the task ...
Think a bit about how much latency you can tolerate. The Arduino can be persuaded to do interesting things if they don't take too much memory, but they sometimes take a long time. I've gotten reliable frequency identification for guitar-like signals in the 80-880 Hz range using YIN, but it takes about 150 milliseeconds to identify a string on the low end of the range. That's way too much latency if I'm trying to control a MIDI device, as the output would be always a sixteenth note behind the rest of the band at 100 beats per minute, but it's OK for other things, like identifying the frequency for a tuning application.
I'm looking at my $20 chromatic tuner and wondering how it can do this for so cheap
One thing to consider is that it doesn't do it all that fast. 150 milliseconds is practically imperceptible in that application. Another is that the tuner may use application-specific ICs to do its work. Here's a link to the only one I can find, quoted at about 6.5 USD in 10K lots: finepitch -- Musical Instrument Tuning IC.
Edit: grammar and spelling