Notation System

Beepscript's notation is a text-based system where individual characters trigger sounds, character adjacency controls timbral morphing, and whitespace defines phrasing. It sits between traditional music notation (which describes pitch and rhythm) and programming languages (which describe process): Beepscript notation describes what it sounds like in a compact, typeable format.

Characters and atoms

Each character in the notation stream maps to a sound atom defined in a Lua configuration block. Atoms are synthesizer configurations: oscillator type, frequency, filter settings, envelope, effects chain. When the renderer encounters a character, it looks up its atom and triggers a voice with that configuration.

Single ASCII characters (az, AZ, 09) are the most common atoms. Multi-character atom names use the $name syntax for longer, descriptive identifiers.

Morphing and adjacency

When two characters are adjacent — no space between them — the synthesizer crossfades smoothly from one atom's timbre to the next. Writing ab produces a morph from atom a to atom b. Writing a b (with a space) produces a hard cut: atom a stops, then atom b starts after a silence gap.

This adjacency-based morphing is the core of Beepscript's timbral expressiveness. Longer sequences like abcba create smooth timbral arcs. Repeating a character like aaa sustains the same timbre. The morph behavior uses a 5ms crossfade window to avoid clicks.

Timing

Two Lua parameters control timing: bpm (beats per minute) and div (subdivisions per beat). At bpm=120; div=16, each character occupies 1/16th of a beat at 120 BPM. The equals sign = inserts a one-unit rest (silence). This gives precise rhythmic control without needing explicit duration values.

Operators

Special characters modify the behavior of adjacent notes:

Chords and simultaneity

Parentheses group characters for simultaneous playback. Writing (abc) triggers atoms a, b, and c at the same time — a chord. Each voice in the chord runs independently, so a chord can combine atoms from different synthesis engines.

Dynamics and expression

Beepscript supports per-note dynamics through multiple mechanisms:

Pattern Arrangement Language (PAL)

For longer compositions, PAL provides a track-based structure within the same text file. PAL operates above the character-level notation, organizing it into named patterns and tracks.

Patterns

Named sequences of notation that can be referenced and reused. Define a pattern with /pa/ and reference it by name. Patterns can be copied (*$pattern for an independent copy) or referenced (+$pattern for a shared reference that updates when the source changes).

Tracks

Named channels that play patterns in sequence or in parallel. Define tracks with /tr/. Each track has its own playback position, loop settings, and mute/solo state. Multiple tracks play simultaneously, enabling layered arrangements.

Arpeggio builder

The /ar/ directive generates arpeggiated patterns from chord definitions, with configurable direction (up, down, up-down), rate, and octave range.

Transport and control

Per-track loop points, quantization flags, and mute/solo toggles provide arrangement-level control. The PAL system turns Beepscript from a single-voice sequencer into a multi-track composition environment.

How it differs

Traditional music notation describes pitch, duration, and dynamics. Piano rolls describe note-on/off events in a time grid. Programming languages like SuperCollider or Csound describe synthesis processes in code. Beepscript's notation describes timbral identity and transitions: which sound (atom), how it connects to the next sound (adjacency), and what modifies it (operators). The compact format means a few characters of text can encode complex timbral behavior that would take many lines of code in a traditional synthesis language.

The documentation covers the full notation syntax. The tour walks through it step by step with editable, playable examples.

← Back to About