Sound design for games
plonk gives you the instruments. This page is about using them well: what makes game music pleasant to hear for twenty minutes, how to balance a mix, and how to make sound effects feel like part of the music.
Give every part its own space
A mix gets muddy when parts fight over the same frequencies. Keep each part in its own range:
| Part | Range | In plonk |
|---|---|---|
| Kick, bass | under 250 Hz | octave: -1 bass, a sine kick with drop |
| Chords, pads | 250 Hz to 1 kHz | triangle or soft square, attack above 0.1, reverb |
| Lead melody | 500 Hz to 3 kHz | square or triangle, octave 5 |
| Hats, sparkle | over 4 kHz | filtered noise, short decay |
Only one part should carry the melody at a time. If the lead and the chords play busy lines together, simplify one.
Balance by ear, then check with numbers
Start from these levels and adjust:
- The lead and the bass are the loudest parts, about equal.
- Chords and pads a little below them.
- Drums clearly audible but under the melody: in
mix()'s report, about 10 to 15 LU under the whole mix. - The whole song about -16 LUFS. Louder than that leaves no room for sound effects; much quieter and players turn it up and get blasted by the effects.
plonk's master bus has a gentle compressor and a limiter, so a loud moment won't clip. It can't fix a bad balance, though. Check it:
import { mix } from "plonkjs";
const report = await mix(theme, 20); // renders 20 seconds offline, in a browser
report.song.lufs; // -16.2
report.tracks.hat.belowMix; // 12.4: how far the hats sit under the mix, in LU
report.warnings; // [] or plain words: "hat: buried (32 LU under the mix); raise its volume"mix() warns about clipping, a song that's too loud or too quiet, silent or buried tracks, and a muddy low end or harsh highs. It's how you (or a coding agent) catch "the drums are inaudible" without speakers. It can't tell you whether a melody is catchy: that still needs a person.
Fight fatigue with variation
A player might hear your loop for twenty minutes. Small changes keep it alive:
- Ghost notes and accents:
x x_ x x_breathes;C5!on the strong beats gives the melody shape. - Chance:
x?40plays 40% of the time. Hats and percussion with a little chance never repeat exactly. Chances are seeded, so the same song plays the same way every time, and tests stay stable. - Fills: give a track a list of patterns and it takes turns, one each time the section plays. A drum fill every second time round marks the phrase.
- Sections: two or three sections (
a a b a) beat one long loop. The B section can change key colour (a minor turn in a major song) or drop the drums. - Length: a whole pass of 30 to 60 seconds is long enough not to grate, short enough to stay tiny.
Make the music react
One song, bent to the moment, beats many songs:
- Drop the drums on menus and maps (
layer("kick", 0)); bring them in for play. - Speed up when time runs low (
tempo(1.12)); never jump. - Thin the music out under a big moment so the sound effect is heard.
See Music that reacts.
Put sound effects in the song's key
Sound effects that ignore the music clash with it. player.sfx() plays an instrument by scale degree in the song's key:
const POP = { wave: "sine", drop: 7, decay: 0.12, sustain: 0, volume: 0.3 };
const CLIMB = [1, 3, 5, 8, 10, 12];
// Each step of a cascade pops one note higher up the song's arpeggio: a little melody instead of noise.
player.sfx(POP, { degree: CLIMB[combo - 1], octave: 5 });And land the big moments on the beat:
player.sfx(FANFARE, { degree: 1, quantize: "beat" }); // waits for the next beat
for (const [k, d] of [1, 3, 5, 8].entries()) player.sfx(BELL, { degree: d, quantize: "beat", after: k * 2 });Quantize celebrations, level ends and stingers. Never quantize the player's own taps and pops: feedback that waits even a tenth of a second feels laggy.
Mood: tempo and key
| Feel | Tempo | Key |
|---|---|---|
| Calm, puzzle, menu | 80 to 100 bpm | major, pentatonic |
| Bouncy, playful | 100 to 130 bpm, a little swing | major, mixolydian |
| Spooky, mysterious | 70 to 110 bpm | minor, dorian, phrygian |
| Tense, urgent | 130 to 160 bpm | minor, or speed the main theme up |
A pentatonic key has no notes that clash, so it's the safest for random or generated melodies.
What plonk can't do
It's a synthesizer. There's no sampling, so no recorded drums, voices or real instruments, and its reverb is a simple room. For a chiptune or synth-pop soundtrack that costs a few kilobytes it's a good fit; for an orchestral score, it isn't.