Lab 23: Peak Detection — Build a Tuner
Time: ~50 minutes | Prerequisites: Lab 22 | Hardware: Pico 2, INMP441, OLED
A real instrument, from a coarse spectrum
Your bins are 25 Hz wide. The gap between A4 and A#4 is 26 Hz — barely one bin. So how
can this possibly tune a guitar? Because a bin isn't a fence. Read the neighbours and
you can see between them. Let's tune in — literally.
What You'll Build
A working chromatic tuner: note name, octave, cents-off, and a needle display that tells you sharp or flat.
Learning Objectives
- Explain why the loudest bin alone is too coarse for tuning
- Apply parabolic interpolation to locate a peak between bins
- Measure the accuracy gain from interpolation
- Demonstrate that windowing is required for interpolation to work
- Convert a frequency to a note name and cents deviation
Concepts Introduced
| ID | Concept |
|---|---|
| 422 | Argmax Search |
| 423 | Peak Bin |
| 424 | Bin To Frequency |
| 425 | Frequency Resolution Limit |
| 426 | Parabolic Interpolation |
| 427 | Sub Bin Accuracy |
| 428 | Local Maximum |
| 429 | Threshold Rejection |
| 430 | Pitch |
| 431 | Musical Note Mapping |
| 432 | Octave |
Background
A bin is not a fence
When a tone falls between two bins, both light up — and the ratio between them says where in the gap the true frequency sits. Fit a parabola through the peak and its two neighbours, and the apex gives you the answer:
1 2 | |
Three magnitudes, four arithmetic operations, and your resolution improves by roughly an order of magnitude. You didn't change the FFT at all — you just read its output more carefully.
Notes are logarithmic
Every octave doubles the frequency, and each octave is 12 equal semitones:
1 | |
A cent is 1/100 of a semitone. Trained musicians hear about 5 cents, so ±5 counts as in tune.
Lab 22 earns its keep here
Parabolic interpolation assumes the peak is shaped like a parabola. An unwindowed
peak isn't — and the refinement barely helps. Measured on this hardware: without a
window, 5.7 Hz error; with a Hanning window, 1.3 Hz. The window isn't decoration,
it's what makes this technique work.
Procedure
Step 1 — Measure the improvement
Open 23-tuner.py and run it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | |
1 2 3 4 5 6 7 8 | |
Bins are 25 Hz wide, yet we locate tones to about 1.3 Hz.
Step 2 — Prove the window matters
Delete the * WINDOW[i] from the test loop and re-run. The refined column gets dramatically
worse — around 5.7 Hz instead of 1.3.
That's Lab 22 paying a concrete dividend, not just producing prettier pictures.
Step 3 — Read the note table
1 2 3 4 5 | |
440 Hz is A4 exactly. 445 Hz is still A4, but 20 cents sharp — clearly audible to a musician.
Step 4 — Tune something
Part 3 runs the live tuner. Sing, hum, whistle, or play an instrument. The display shows:
- the note name and octave
- the measured frequency
- a needle: centre is in tune, left flat, right sharp
- the cents deviation
Try singing a steady note and watch how much you drift. Most people are surprised.
1.3 Hz is about 5 cents at A4
Which puts this tuner right at the threshold of human hearing — genuinely usable, but
not studio-grade. To do better you'd need a longer window (finer bins) or a different
algorithm entirely. Knowing your instrument's limits is as important as building it.
Step 5 — Predict, then measure
Prediction: you doubled N from 256 to 512 for this lab. What did that do to the bin width, and what did it cost?
Check against Lab 24's timing.
Expected Output
The accuracy table, the note table, and the live tuner display.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Interpolation barely helps | Window missing | Apply Hanning before the FFT |
| Note jumps an octave | Harmonic louder than fundamental | Common with some instruments; restrict the search range |
| Needle jitters | Genuine pitch variation | Average the last few readings |
| Always "listening" | Too quiet, or PEAK_RATIO too high |
Get closer, or lower it |
| Wrong octave number | Off-by-one in the octave formula | Check against a known 440 Hz tone |
Challenges
- Smooth the needle. Average the last five frequency estimates. Does it feel better or just slower?
- Guitar mode. Restrict detection to the six open-string frequencies (82, 110, 147, 196, 247, 330 Hz) and show which string you're nearest.
- Beat the interpolation. Compare parabolic interpolation against fitting on a log magnitude scale. Which is more accurate for a Hanning-windowed peak?
Check Your Understanding
- Why is the loudest bin alone insufficient for tuning?
- How does parabolic interpolation find a frequency between bins?
- Why does interpolation need a window to work well?
- What is a cent, and how many are in an octave?
- Our tuner is accurate to ~1.3 Hz. Is that good enough for a musician? Justify it.
You built a real instrument
Not a demo — a tuner someone could actually use. Next lab puts a stopwatch on every
stage and finds out what's really costing you time. The answer surprises most people.
Next: Lab 24: Real-Time Spectrum Analyzer | Previous: Lab 22