-
-
Notifications
You must be signed in to change notification settings - Fork 288
Simple Frequency Detection
Audio frequency detection is the process of identifying the pitch or dominant frequency of a sound signal. Three common methods used are Fast Fourier Transform (FFT), AutoCorrelation, and Zero-Crossing.
-
AutoCorrelation compares a signal with delayed versions of itself to detect repeating patterns, which correspond to pitch. It's effective for monophonic signals and works well in noisy environments, but can be computationally intensive.
-
Zero-Crossing counts how often the signal crosses the zero amplitude axis to estimate frequency. It is simple and fast but only reliable for clean, single-frequency signals and can be inaccurate with harmonics or noise.
This chapter describes how to use the more lightweight FrequencyDetectorAutoCorrelation and FrequencyDetectorZeroCrossing classes.
Here is a simple example:
#include "AudioTools.h"
AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave;
GeneratedSoundStream<int16_t> sound(sineWave);
FrequencyDetectorAutoCorrelation out(1024);
// FrequencyDetectorZeroCrossing out;
StreamCopy copier(out, sound, 10 * 1024);
// Arduino Setup
void setup(void) {
// Open Serial
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
// start I2S
Serial.println("starting ...");
out.begin(info);
// Setup sine wave
sineWave.begin(info, 200);
Serial.println("started...");
}
// Arduino loop - copy sound to out
void loop() {
copier.copy();
Serial.print(out.frequency(0));
Serial.print(" ");
Serial.println(out.frequency(1));
}
In the example above we use the FrequencyDetector as output class. However you can specify an audio source in the constructor and treat the FrequencyDetector itself as audio source which will as a side effect give you the frequencies. On the output side you can also specify an output class: in this case the frequency detector will just forward the data written to that output, so that you can use this class in an output chain!
The FrequencyDetectorZeroCrossing uses the write size (=copy size), so if you want to increase the number of analysed samples, just increase this size!
The FrequencyDetectorAutoCorrelation however requires a buffer size in samples that needs to be big enough, but this depends on the minimum frequency that you want to measure.
The recommended buffer size for AutoCorrelation depends on the lowest frequency you want to detect, since the algorithm must capture at least one full period of the waveform.
Use a buffer that spans at least 2–3 periods of the lowest frequency you're analyzing.
Buffer size = (Sampling Rate / Lowest Frequency) × N
Where:
- Sampling Rate is in Hz (e.g., 44100 Hz)
- Lowest Frequency is the minimum expected frequency (e.g., 80 Hz for a bass note)
- N is the number of waveform cycles (usually 2–3)
To detect down to 80 Hz with a sampling rate of 44100 Hz:
Buffer size = (44100 / 80) × 3 ≈ 1650 samples
So a buffer size of 1024 to 2048 samples is common for pitch detection in voice or music.
Use Case | Recommended Buffer Size |
---|---|
Voice / Melody Detection | 1024–2048 samples |
Broad Range / Low Frequencies | 2048–4096 samples |
- Smaller buffers ➜ faster response, less low-frequency accuracy
- Larger buffers ➜ better pitch accuracy, more latency
Choose the buffer size based on the trade-off between accuracy and latency.