Type a drum machine.
SONIC is a compact live-coding language for trance and electronic music. A score is plain text; the same freestanding C engine renders it natively, through Node, or in the browser with WebAssembly.
Run, and the next bar hot-swaps without dropping the beat.Quick start
- Open the SONIC web IDE.
- Choose an example or replace the editor contents.
- Press
RunorCtrl/Cmd + Enter. - Use
Export WAVto render four seamless loops at 44.1 kHz stereo.
# a complete SONIC track
bpm 138
kick x... x... x... x...
hat ..x. ..x. ..x. ..x. gain 0.45
clap .... x... .... x... gain 0.4
bass a1 . a1 . a1 . a1 . cut 650 dec 0.18
pluck a3 c4 e4 a4 | g3 b3 d4 g4 del 0.45
Program structure
Every non-blank line is a comment, a global setting, or one voice. Comments begin with # and continue to the end of the line.
global-setting value
instrument pattern [parameter value ...]
Global settings
| Setting | Range | Meaning |
|---|---|---|
bpm 138 | 40–300 | Tempo. Defaults to 138 beats per minute. |
swing 0.2 | 0–1 | Delays odd-numbered steps in even-length bars. |
A trailing colon after an instrument is optional, so kick: and kick are equivalent.
Instruments
Synthesized drums
Pitched voices
| Instrument | Character |
|---|---|
sine | Pure fundamental tone. |
saw | Band-limited polyBLEP sawtooth. |
square | Band-limited square wave. |
sub | Low sine voice rendered one octave below the written note. |
bass | Dark filtered saw with short decay and filter envelope. |
pluck | Resonant saw pluck with a fast downward filter sweep. |
super | Seven detuned saw oscillators for wide leads and pads. |
fm | Two-operator FM for keys, bells, metallic hits, and inharmonic textures. |
Patterns and timing
Drum patterns
Drums read every character as one step. Use x for a hit, X for a 35% accent, and . for a rest. Spaces are visual only.
kick x... x... x... x...
clap .... X... .... x...
Pitched patterns
Pitched voices read whitespace-separated words. Notes use a letter, optional sharp or flat, and octave 0–8: c4, f#3, eb2. A dot rests; a hyphen extends the previous note.
super a3 - - - | g3 - - -
pluck c4 . e4 . g4 . b4 .
The one timing rule
| separates bars, and every bar is divided evenly across its steps. Four note words become quarter notes; 16 drum characters become sixteenths; three words become triplets. Each bar is four beats.
Tracks may use different bar counts. Each track loops independently, while the full song loop is the least common multiple of all track lengths, capped at 64 bars.
Voice parameters
Parameters come after the full pattern as name value pairs.
| Parameter | Range | Meaning |
|---|---|---|
gain | 0–1 | Voice volume. |
cut | 20–20000 | Low-pass filter cutoff in Hz. |
res | 0–1 | Filter resonance; internally capped below instability. |
att | seconds | Amplitude attack time. |
dec | seconds | Amplitude and filter-envelope decay time. |
fenv | Hz | Extra cutoff added at note-on, then swept downward. |
del | 0–1 | Send to the dotted-eighth ping-pong delay. |
pan | -1–1 | Stereo position from left to right. |
det | 0–1 | Supersaw detune spread. |
oct | -3–3 | Transpose written notes by octaves. |
ratio | 0.1–16 | FM modulator frequency divided by carrier frequency. |
index | 0–20 | FM modulation depth; larger values add brighter sidebands. |
FM synthesis recipes
The fm voice uses one sine oscillator to modulate another. Integer ratios emphasize harmonic sidebands. Fractional ratios create bell-like and metallic spectra. index 0 reduces exactly to the sine carrier.
# electric keys
fm c4 e4 g4 b4 ratio 1 index 1.2 dec 0.8
# glass bells
fm c5 . g5 . ratio 2.01 index 5 dec 1.8 del 0.3
# short metallic hit
fm c3 . . . ratio 2.71 index 8 dec 0.25
Terminal CLI
Node 16 or newer runs the same WebAssembly engine used by the browser. The package has no runtime dependencies.
cd cli
npm install -g .
sonic new mytrack.sonic
sonic play mytrack.sonic
sonic watch mytrack.sonic
sonic build mytrack.sonic -o mytrack.wav --loops 8
| Command | Behavior |
|---|---|
new | Creates a starter score without overwriting an existing file. |
play | Renders a temporary WAV and opens the platform audio player. |
watch | Re-renders and restarts playback whenever the source file changes. |
build | Writes a 16-bit, 44.1 kHz stereo WAV. Defaults to four loops. |
Engine architecture and limits
The parser, event compiler, sequencer, oscillators, filters, envelopes, delay, and soft-clip master bus live in one freestanding C file. The engine uses static memory: no standard library, heap allocation, garbage collector, or network access.
| Limit | Value |
|---|---|
| Source size | 65,535 bytes |
| Tracks | 32 |
| Compiled events | 8,192 |
| Simultaneous voices | 64, with oldest-voice stealing |
| Steps per bar | 256 |
| Global loop | 64 bars maximum |
| Sample rate | 8,000–48,000 Hz |
| Render chunk | 8,192 stereo frames |
A warm-up loop is rendered before playback or export so the feedback delay already contains its tail at bar one, producing a seamless loop boundary.
Compile errors
The IDE and CLI report the source line and a direct correction hint. Common errors include unknown instruments, invalid notes, parameter values without names, pattern tokens after parameters, empty voices, and resource limits.
sonic: line 4: expected a note (like a3, c#4, eb2), '.', '-' or '|'
If a track sounds silent, first check gain, note octave, and filter cut. If a pattern feels mistimed, count the steps inside each bar: SONIC always distributes them evenly.