Frequency modulation encodes a message signal by varying the instantaneous frequency of a carrier. Mathematically:
y(t) = sin(2πfct + (Δf / fm)·sin(2πfmt))
This is the same equation as the musical FM-synthesis tool on this site, but the radio/signals framing exposes Δf (peak frequency deviation) as the primary control rather than the modulation index I = Δf / fm. Real broadcast engineers think in kHz of deviation, not in dimensionless indices.
Real-world deviation values
- Narrowband FM (NBFM) — voice radio, two-way handhelds: Δf ≈ 2.5 – 5 kHz with fm ≤ 3 kHz, giving I ≤ 2.
- FM broadcast (88 – 108 MHz) — commercial radio: Δf = 75 kHz with fm ≤ 15 kHz (audio), giving I ≈ 5.
- NTSC TV audio — analog television: Δf = 25 kHz with fm ≤ 15 kHz, giving I ≈ 1.7.
- Aviation FM — aircraft band 108–137 MHz: Δf ≈ 2.5 kHz, narrow.
This tool scales these into the audible band (carrier ≤ 5 kHz, Δf ≤ 3 kHz) since Web Audio's sample rate (~48 kHz) can't reach RF frequencies. The modulation index I and the shape of the spectrum transfer identically across scales — Δf=75 kHz with fm=15 kHz produces the same Bessel sideband structure as Δf=1500 Hz with fm=300 Hz here.
Carson's rule
The total occupied bandwidth of an FM signal is approximated by Carson's rule: BW ≈ 2·(Δf + fm). The gold dashed markers show the BW boundaries on the spectrum plot. Carson covers ~98 % of the signal energy — the remaining ~2 % extends past the markers but is what FCC channel-spacing calculations rely on.
Reading the spectrum
- Carrier (solid green) — the unmodulated frequency. Vanishes at modulation indices where J0(I) = 0 (first zero at I ≈ 2.405).
- Peak / trough markers (orange dash) — fc ± Δf. These mark the maximum and minimum instantaneous frequency excursion. The audible "frequency swing" lives between them.
- Carson BW edges (gold dash) — the boundaries of the ~98 %-energy region. Sidebands outside the gold markers contribute < 2 % of total power.
- Bessel sidebands — the FFT bars at fc ± n·fm. Amplitudes are Jn(I); the count of significant sidebands scales with I.
Instantaneous frequency readout
The "Live instantaneous frequency" readout reads carrier.frequency.value directly from the Web Audio engine each animation frame. This value reflects the modulation in real time — it sweeps between the trough (fc − Δf) and the peak (fc + Δf) at the message frequency. This is conceptually the value an FM discriminator at the receiver would output, scaled into the audible region.
How is this different from the musical Frequency Modulator Tool?
Same Web Audio implementation — both tools route modulator → modGain → carrier.frequency. The difference is purely UI: the musical tool exposes modulation/carrier ratio + modulation index as the primary controls (the parameters synthesists think in), while this tool exposes the peak frequency deviation Δf in Hz as the primary control (the parameter broadcast engineers think in). The musical tool's "10 patches" set classic synth timbres; this tool's "10 broadcast presets" reference real-world FM standards scaled to audible range.
Why doesn't this run at real FM broadcast frequencies (88-108 MHz)?
Because Web Audio's sample rate is typically 48 kHz, capping the Nyquist limit at 24 kHz. Real broadcast is at MHz, which a browser can't synthesise. The tool runs in the audible-equivalent band where the modulation-index math and spectrum shape transfer identically — you hear the same Bessel sideband structure, just shifted down in absolute Hz.
Why does the modulation index I appear so prominently in the readouts when Δf is the primary control?
Because the index is the parameter that determines the spectral structure (the Bessel coefficient series). Two different (Δf, fm) combinations that share the same I = Δf/fm produce identical sideband patterns scaled by fm. Showing both lets you see: "if I bump message freq, the index drops and the spectrum becomes narrower." Real broadcast engineers use both views interchangeably.
What's the relationship between deviation Δf and audible "FM brightness"?
More deviation → wider spectrum → more harmonics → brighter / harsher sound. Real FM broadcast uses 75 kHz deviation at a 100 MHz carrier — perceived brightness scales with the index I = Δf/fm, not absolute Δf, so 1500 Hz deviation against a 300 Hz message here sounds about as "bright" as 75 kHz against 15 kHz audio in real broadcast (both around I = 5).
Why is there a "carrier-null" preset at deviation 601 Hz?
Because at modulation index I = 2.405 the Bessel function J0(I) ≈ 0, which means the carrier amplitude vanishes — all signal energy moves into the sidebands. With message 250 Hz, deviation 601 Hz gives I = 2.404 (close enough). Listen for the spectrum becoming symmetric around the carrier position while the carrier marker itself sits over an empty bar — the most famous identity in FM math.
Why don't the orange peak/trough markers correspond to FFT peaks?
Because they mark the instantaneous frequency excursion, not the energy distribution. The carrier physically reaches fc + Δf at the peak of every message cycle and fc − Δf at the trough, but spends infinitesimal time at those exact frequencies. The FFT shows where the average power sits — which is the Bessel sideband pattern centered on fc. Carson BW (gold dash) is the better "energy" boundary.
Can I model an FM stereo subcarrier (38 kHz multiplex)?
Not at scale — the 38 kHz pilot/subcarrier system needs frequencies above this tool's 5 kHz carrier ceiling. You can model the structure (carrier + sidebands at ±multiplex_freq) but not the exact 19 kHz pilot / 38 kHz subcarrier values. For broadcast modulation experiments, audio at the modeled multiplex scale (e.g. 380 Hz pilot, 760 Hz subcarrier) would behave similarly.
Why is the time-domain waveform amplitude constant when frequency is being modulated?
That's the defining property of FM: the carrier's amplitude is unchanged; only its frequency varies. If you saw amplitude variation in the time-domain plot, that would be AM, not FM. The "modulation" is encoded entirely in how fast the wave is oscillating at each moment. Watch the live instantaneous-frequency readout — it'll sweep between the trough and peak values at the message rate.