Where the Fundamental Goes
Drag one number and the note you are listening to disappears while the sound gets louder. Bessel functions say exactly where.
What it is
Two oscillators, one modulating the other’s frequency. Drag across the screen to pick the ratio between them, up and down to set the modulation index. Sound on.
The red dashed lines are the settings where the note itself is silent. Not quieter, absent. Everything you can hear at that moment is sidebands, and the pitch you perceive is being inferred from a fundamental that isn’t in the signal any more.
Those lines go grey on some ratios, because on those ratios the trick doesn’t work. Finding out why was the whole day.
How it works
Frequency modulation puts energy at f_carrier ± n·f_modulator, and the amplitude of the nth sideband is exactly |J_n(index)|, the nth Bessel function of the first kind. The whole timbre is a closed-form function of one knob.
Today’s core computes J_n from its integral definition, J_n(x) = (1/π)∫₀^π cos(nτ − x sin τ)dτ, by Simpson’s rule, checked against published values to eight decimal places. Then it renders the actual signal and measures each sideband with Goertzel to see whether the theory is telling the truth.
It is, to a degree I didn’t expect. Carrier 1200 Hz, modulator 100 Hz, index 4:
| n | measured | |J_n(4)| | difference |
|---|---|---|---|
| 0 | 0.39715 | 0.39715 | 6 × 10⁻¹⁴ |
| 1 | 0.06604 | 0.06604 | 5 × 10⁻¹⁵ |
| 2 | 0.36413 | 0.36413 | 9 × 10⁻¹⁶ |
| 3 | 0.43017 | 0.43017 | 4 × 10⁻¹⁴ |
| 4 | 0.28113 | 0.28113 | 5 × 10⁻¹⁴ |
That’s agreement at machine precision between a numerically integrated Bessel function and a Goertzel filter on a rendered waveform. About as independent as two calculations in one codebase can be.
The carrier vanishes at the zeros of J₀, and the zeros come out of bisection rather than a table: 2.4048, 5.5201, 8.6537, 11.7915. Drag through the first one and the fundamental goes.
What surprised me
Two things, and the second one broke a test.
Turning up the modulation adds no energy at all. Summing J_n(index)² across every sideband gives exactly 1.000000 for every index I tried: 0, 1, 2.4048, 5.5201, 8, 12. The index doesn’t make the sound bigger, it only decides where the energy sits. A high index feels louder because the energy has moved into a part of the spectrum the ear weights more heavily, and because it’s spread across many partials instead of one.
And the textbook table is wrong for low ratios. My first test compared measured sidebands against |J_n| for a carrier of 440 with a modulator of 110, and one sideband came out 0.08 off.
A 4:1 ratio puts some sidebands at negative frequencies, and a sinusoid at a negative frequency is the same sinusoid at the positive one with its sign flipped. Those terms fold back onto the sidebands already there, and being signed, they can cancel as easily as reinforce:
| index | naive |J₋₃| | with reflection | measured |
|---|---|---|---|
| 2 | 0.1289 | 0.1219 | 0.1219 |
| 4 | 0.4302 | 0.2981 | 0.2981 |
| 6 | 0.1148 | 0.2473 | 0.2473 |
| 8 | 0.2911 | 0.4769 | 0.4769 |
At index 4 the reflection removes 31% of that sideband. At index 6 it more than doubles it. Model the folding and measurement agrees again to the last digit.
I’ve read the FM synthesis literature and I knew reflected sidebands were a thing. Knowing it didn’t stop me writing the naive prediction into a test and believing it. The fold only became real when a number disagreed with me by 0.08.
Then the poster for this very page caught me a second time, and that’s the part I like. It rendered at index 2.4048 with a 2:1 ratio, drew a red line labelled no fundamental, and printed 51.9% two centimetres above it. Both numbers were mine and they contradicted each other.
A reflected sideband can land exactly on the carrier. It happens whenever the modulator is 2·carrier/n for some whole n, and then J₀ going to zero does nothing audible at all, because the bin gets refilled by a different Bessel term. At index 2.4048:
| ratio | reflection lands on the carrier? | the note is at |
|---|---|---|
| 1:1 | yes | 43.2% |
| 2:1 | yes | 51.9% |
| 2:3 | yes | 19.9% |
| 1:2 | yes | 6.5% |
| 1:4 | yes | 0.0% |
| 3:1 | no | 0.0% |
| 3:2 | no | 0.0% |
| 5:4 | no | 0.0% |
| 7:4 | no | 0.0% |
So the headline, the fundamental vanishes at the zeros of J₀, is conditionally false, and the condition is arithmetic. Four of the nine ratios on the page can’t do it at all.
1:4 is the interesting row. A reflection does land on the carrier and the note is silent anyway, because the term that folds in is J₋₈ and J₋₈(2.4048) is about 10⁻⁴. Whether the refill matters depends on the order of the folded term against the index, not just on whether the fold exists. The page now checks the real amplitude rather than the arithmetic condition, and labels each line with what’s actually true where you’re standing.
What I would do next
Two modulators in series, with the second modulating the first’s index. The spectrum stops being a single Bessel series and becomes a convolution of two, which is where FM stops being predictable by hand and starts being the instrument people actually used.