A subtractive synthesizer makes a metallic sound by filtering a harmonically rich waveform. An FM synthesizer makes a metallic sound by creating frequencies that were not in either oscillator to begin with. The difference matters for voice blips, because the inharmonic partials that FM generates are what make a sound read as "synthetic" rather than "filtered."
The two parameters that control this are the carrier-to-modulator ratio and the modulation index. The ratio determines which frequencies appear in the output; the index determines how strong each one is. A voice blip that sits at a non-integer ratio with a moderate index has a metallic, slightly unstable quality that a subtractive blip cannot reproduce without extensive processing.
This article covers the specific parameter ranges for metallic and synthetic voice blips, the Web Audio implementation, and the envelope shapes that keep an FM tone from sounding like a bell. The laser and sci-fi synthesis guide covers FM as one technique among several; this article is specifically about the blip, which is a shorter and more constrained problem.
What does the carrier-to-modulator ratio actually control?
In a two-operator FM pair, the carrier is the oscillator the listener hears, and the modulator is the oscillator that changes the carrier's frequency. The ratio is the modulator frequency divided by the carrier frequency. When the ratio is an integer, the sidebands land on harmonic multiples of the carrier, and the result sounds tonal. When the ratio is not an integer, the sidebands land between the harmonics, and the result sounds inharmonic.
The inharmonicity is the source of the metallic character. A ratio of 2:1 produces a harmonic spectrum with a bell-like brightness. A ratio of 3.5:1 produces a spectrum whose partials do not align with the harmonic series, which the ear reads as metal rather than as a pitched note . A ratio of 1.41:1 produces a denser, more clangorous texture that is often used for gongs and cymbals.
| Ratio (mod:carrier) | Spectrum | Blip character |
|---|---|---|
| 1:1 | Harmonic | Warm, vocal-like |
| 2:1 | Harmonic (octave) | Bright, bell-like |
| 3:1 | Harmonic (twelfth) | Hollow, slightly metallic |
| 3.5:1 | Inharmonic | Metallic, clangorous |
| 1.41:1 | Inharmonic | Dense, gong-like |
The 3.5:1 ratio is the one that most directly produces a "synthetic metal" character. A ratio of 1.41 is more aggressive and works for alarm-like blips. A ratio of 2:1 is the safest starting point if the blip needs to remain somewhat musical; it is metallic but not clangorous.
The ratio also interacts with the carrier frequency. A 3.5:1 ratio on a 400 Hz carrier places the modulator at 1400 Hz, which keeps both operators in a range that most speakers reproduce. A 3.5:1 ratio on a 100 Hz carrier places the modulator at 350 Hz, which is still audible but the resulting spectrum is darker. The frequency tuning guide covers the genre-specific carrier ranges; the ratio is what determines the character within that range.
How does the modulation index change the blip's brightness and bandwidth?
The modulation index is the modulator's amplitude divided by its frequency. It controls how far the carrier's frequency deviates from its center, which in turn controls how many sidebands are generated and how strong each one is. A low index produces few sidebands and a relatively pure tone. A high index produces many sidebands and a bright, complex spectrum.
Carson's rule gives a useful approximation of the
bandwidth: the occupied bandwidth is roughly twice the
deviation plus twice the modulator frequency, which
simplifies to BW ≈ 2(β + 1)f_m, where β is
the modulation index and f_m is the
modulator frequency . At an index of 2, the
bandwidth is roughly six times the modulator frequency; at
an index of 5, it is twelve times. A blip with a 1400 Hz
modulator and an index of 2 occupies about 8.4 kHz of
bandwidth; the same blip at an index of 5 occupies about
16.8 kHz.
| Modulation index | Bandwidth (approx.) | Character |
|---|---|---|
| 0.5 | 3 × f_m | Nearly pure, slight edge |
| 1.0 | 4 × f_m | Warm, vocal |
| 2.0 | 6 × f_m | Bright, clearly metallic |
| 3.0 | 8 × f_m | Clangorous, dense |
| 5.0 | 12 × f_m | Noisy, nearly unpitched |
For a voice blip, the useful index range is 1.5 to 3.5. Below 1.5, the blip is too clean to read as synthetic. Above 3.5, the bandwidth becomes wide enough that the blip loses its pitch identity and starts to sound like a click with a metallic tail. The 2 to 3 range is where the blip is clearly metallic without losing the fundamental, which is what allows it to function as a voice cue rather than as an abstract sound.
The index can also be modulated over time. A short envelope on the index that starts high and drops to a lower value produces a blip that begins bright and settles into a cleaner tone. This is the FM equivalent of a filter envelope, and it is what makes an FM blip sound like a short event rather than a sustained note.
How do you implement a two-operator FM blip in the Web Audio API?
The Web Audio API does not have a dedicated FM oscillator node, but it does not need one. An oscillator's frequency is an AudioParam, and any audio node can connect to it. The modulator oscillator connects to a gain node that scales its output to the modulation depth, and that gain node connects to the carrier's frequency parameter .
function playFmBlip({
carrierFreq = 600,
ratio = 3.5,
index = 2.5,
duration = 0.05,
volume = 0.6
} = {}) {
const ctx = getAudioContext();
const now = ctx.currentTime;
const carrier = ctx.createOscillator();
const modulator = ctx.createOscillator();
const modGain = ctx.createGain();
const outGain = ctx.createGain();
carrier.type = 'sine';
carrier.frequency.value = carrierFreq;
modulator.type = 'sine';
modulator.frequency.value = carrierFreq * ratio;
// Modulation depth = index * modulator frequency
modGain.gain.value = index * modulator.frequency.value;
// Envelope on the output, not on the modulator
outGain.gain.setValueAtTime(0, now);
outGain.gain.linearRampToValueAtTime(volume, now + 0.002);
outGain.gain.exponentialRampToValueAtTime(0.001, now + duration);
modulator.connect(modGain);
modGain.connect(carrier.frequency);
carrier.connect(outGain);
outGain.connect(ctx.destination);
modulator.start(now);
carrier.start(now);
modulator.stop(now + duration + 0.01);
carrier.stop(now + duration + 0.01);
}
The critical line is the modulation depth calculation. The
modulation index is defined as the peak frequency deviation
divided by the modulator frequency, so the gain that scales
the modulator must be set to index × modulator
frequency. A common mistake is to set the gain to
the index value directly, which produces a much weaker
modulation and a sound that is not metallic enough.
The envelope is applied to the carrier's output, not to the modulator. If the modulator's amplitude is enveloped instead, the index changes over time, which is a useful effect but a different one. For a basic blip, a short output envelope is simpler and more predictable.
The carrierFreq of 600 Hz and the ratio of 3.5
place the modulator at 2100 Hz. The index of 2.5 produces a
bandwidth of roughly 7 times the modulator frequency, or
about 14.7 kHz, which is wide enough to be clearly metallic
but narrow enough that the fundamental is still present.
The
Web Audio blip tutorial
covers the basic oscillator setup; the FM version adds the
modulator chain on top of it.
Why does an FM blip sound like a bell instead of a voice, and how do you fix it?
The default FM blip is a bell. The ratio is inharmonic, the index is moderate, and the envelope is a simple decay. That combination produces the classic FM bell timbre, which is useful for UI notifications but not for a voice cue. A voice blip needs two changes: a ratio that is closer to harmonic, and an envelope that includes a short attack rather than an instant onset.
The ratio change is counterintuitive. A fully inharmonic ratio (3.5:1) produces the strongest metallic character, but it also produces the strongest bell character. A ratio that is close to an integer but not exactly on it, such as 2.1:1 or 1.95:1, produces a spectrum that is mostly harmonic with a slight inharmonic edge. The ear reads this as a voice with a synthetic quality rather than as a bell.
| Ratio | Bell character | Voice character |
|---|---|---|
| 3.5:1 | Strong | Weak |
| 2.1:1 | Moderate | Strong |
| 1.95:1 | Subtle | Strongest |
The 1.95:1 ratio is the one that works best for a synthetic voice blip. It is close enough to 2:1 that the spectrum is mostly harmonic, but the slight deviation adds just enough inharmonicity to prevent the blip from sounding like a pure sine. The result is a voice that is clearly synthesized but still readable as speech-like.
The envelope change is the second half of the fix. A bell has an instant attack and a long exponential decay. A voice blip needs a 2 to 5 millisecond attack and a decay that is short enough to end before the next character is revealed. The attack is what makes the blip read as an event rather than as a struck object. The square-wave blip synthesis guide covers the envelope shapes in more detail; the FM blip uses the same shapes, applied to a different source.
How do you make a set of FM voice blips for a cast of synthetic characters?
A set of FM blips for different characters needs to vary along dimensions that the ear can distinguish without training. The three dimensions that work are carrier frequency, ratio, and index. Changing all three at once produces characters that sound like different instruments; changing only one produces characters that sound like the same instrument at different settings.
| Character type | Carrier | Ratio | Index | Envelope |
|---|---|---|---|---|
| Friendly AI | 700 Hz | 2.0 | 1.5 | Soft attack, medium decay |
| Industrial robot | 500 Hz | 3.5 | 3.0 | Sharp attack, short decay |
| Corrupted system | 400 Hz | 1.41 | 4.0 | Unstable attack, noisy decay |
| Alien intelligence | 900 Hz | 2.76 | 2.0 | Slow attack, long decay |
The friendly AI uses a near-harmonic ratio and a low index, which keeps the blip clean and readable. The industrial robot uses a fully inharmonic ratio and a high index, which makes the blip sound mechanical and harsh. The corrupted system uses a ratio close to 1.41 and a very high index, which pushes the blip toward noise without losing the pitch entirely. The alien intelligence uses an intermediate ratio and a slow attack, which gives the blip a sense of deliberation that the other three do not have.
The envelope is the dimension that most strongly distinguishes the characters after the pitch and ratio. A slow attack reads as calm or deliberate; a sharp attack reads as aggressive or urgent. A long decay reads as spacious or distant; a short decay reads as immediate. The friendly/hostile tone design guide covers the emotional mapping of the envelope in more detail; the FM blip uses the same mapping.
The Celeste dialogue system is the reference for how this kind of set is built in practice. The sound designer started with simple synth sounds, then used a parametric EQ to model formants — the spectral peaks in human vowel sounds — and automated their positions over time to resemble the way a voice transitions between vowels . The result was a set of synthetic voices that read as speech without being recordings. The FM approach described here is a simpler version of the same idea: the ratio and index shape the spectrum, and the envelope shapes the articulation. The comparison of Animalese, Undertale and Balatro covers the broader design space that Celeste sits in.
What does a working FM voice blip actually sound like?
The test for an FM voice blip is not whether it sounds metallic. It is whether the metallic character supports the voice role or distracts from it. A blip that is too metallic reads as a UI notification; a blip that is too clean reads as a sine wave with a fancy name. The working blip sits between the two, and the balance is what the ratio and index control.
The first test is the recognition test. Play the blip in a dialogue line and ask whether it reads as a voice. If the player hears it as a sound effect that happens to play during dialogue, the blip is too metallic. If the player hears it as a character speaking, the blip is working.
The second test is the fatigue test. Play the blip for thirty seconds of continuous dialogue and ask whether it becomes grating. FM blips with high indices are more fatiguing than subtractive blips because the wide bandwidth puts energy in frequency ranges that the ear is sensitive to. A blip that survives thirty seconds at the intended text speed is a blip that will survive a full conversation.
The third test is the consistency test. Play the full set of character blips in sequence and ask whether they sound like they belong to the same world. FM blips can drift toward different timbres because the ratio and index interact in non-linear ways. A set that shares the same ratio family (all near-harmonic, for example) feels more coherent than a set that mixes fully harmonic and fully inharmonic ratios.
The FM blip is not a replacement for every voice blip. It is a specific tool for characters that are meant to sound synthetic, mechanical, or alien. A human character in a fantasy RPG does not need an FM blip; a square-wave or triangle-wave blip is more appropriate. The villain voice guide covers the case where FM is used for a human-sounding character with a threatening edge; the fully synthetic character is a different problem, and the FM parameters in this article are the ones that solve it.
Generate a Reference Blip for the FM Implementation
Open the SfxMaker blip generator and create a reference blip at 600 Hz with a triangle waveform and a 50 ms decay. Use this as the comparison point for the FM blip: the FM version should have more high-frequency content and a clearer metallic edge, but the same fundamental and the same envelope timing. If the FM version sounds like a different pitch, the carrier frequency is wrong; if it sounds like a different length, the envelope is wrong.
Open Blip Sound Generator →