Mini-Notation in Depth
Mini-notation is the compact syntax inside pattern brackets. With a handful of characters you can subdivide time, layer voices, vary patterns per cycle, and shape rhythms — the same way you’d program a step sequencer, but with text. This chapter walks through each technique with timing breakdowns; for the terse syntax tables, see the Mini-Notation Grammar reference.
Here’s where we’re headed — a beat using everything this chapter covers:
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("TR-808")));
drums << [bd <sd [sd sd]>, ch*8, <_ oh>];
PLAY;Three layers separated by commas: a kick with a snare that varies between single and double hits each cycle, eight hi-hats, and an open hat sounding every other cycle. By the end of this page you’ll read patterns like this at a glance.
Nested Patterns
Section titled “Nested Patterns”Put a pattern inside a pattern to subdivide time. The inner pattern squeezes into the slot the outer pattern gives it:
let p = [[C4 D4] E4];// C4: 0 - 1/4, D4: 1/4 - 1/2, E4: 1/2 - 1The outer pattern has two slots, each half a cycle. The inner [C4 D4] divides its half into two quarters. In DAW terms: the bar splits in half, and the first half splits again.
This rule applies recursively at every level:
duration = parent_slot_duration / number_of_siblingsFor [[[C4 D4] E4] F4]:
| Note | Nesting depth | Calculation | Duration |
|---|---|---|---|
| F4 | 1 (outer) | 1 / 2 | 1/2 cycle |
| E4 | 2 (middle) | 1/2 / 2 | 1/4 cycle |
| C4 | 3 (inner) | 1/4 / 2 | 1/8 cycle |
| D4 | 3 (inner) | 1/4 / 2 | 1/8 cycle |
Nested groups don’t need matching sizes — each group divides its own slot independently:
let uneven = [[C4 D4 E4] [F4 G4]];// First half: 3 notes, 1/6 cycle each// Second half: 2 notes, 1/4 cycle eachThis naturally produces mixed groupings — triplets against duplets, quintuplets against pairs — without any special syntax.
Parallel Patterns
Section titled “Parallel Patterns”A comma splits a pattern into voices that play simultaneously:
let chord = [C4, E4, G4]; // C major chord — all notes at onceWith one element per voice, all onsets align and you get a chord. But each voice keeps its own time grid, based on its own element count:
let voices = [C4 D4, E4 F4 G4];// Voice 1: 2 elements, onsets at 0 and 1/2// Voice 2: 3 elements, onsets at 0, 1/3, 2/3| Time | Voice 1 | Voice 2 |
|---|---|---|
| 0 | C4 | E4 |
| 1/3 | F4 | |
| 1/2 | D4 | |
| 2/3 | G4 |
Five separate onsets in one cycle — a polyrhythmic texture, not a chord. The classic 3-against-2:
let three_two = [bd bd bd, sd sd];// Kicks every 1/3, snares every 1/2 — only the downbeat alignsParallel voices are how you write drum patterns, with each instrument on its own layer:
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("TR-808")));
drums << [bd _ bd _, _ sd _ sd, ch ch ch ch];// Kick on 1 and 3, snare on 2 and 4, steady hats
PLAY;Each voice can use nesting independently — every layer gets its own subdivision structure:
let layered = [[C4 D4] E4, G4 [A4 B4]];Alternating Patterns
Section titled “Alternating Patterns”Angle brackets <...> play one element per cycle, rotating through the list:
let alt = <C4 D4 E4>;// Cycle 0: C4, cycle 1: D4, cycle 2: E4, cycle 3: C4, ...The selection is simply cycle_number % number_of_elements, and the chosen element fills the entire slot the <...> occupies. Compare:
| Pattern | Behavior |
|---|---|
[bd sd hh] | All three play, every cycle |
<bd sd hh> | One per cycle, rotating |
Alternation is your tool for variation over time. Alternate whole phrases:
let phrases = <[C4 E4 G4 E4] [C4 F4 A4 F4]>; // Two bars, looping A-BOr nest <...> inside a sequence so one slot varies while the rest stays put:
let fills = [bd <sd [sd sd]>];// Cycle 0: bd sd — cycle 1: bd sd-sd (doubled snare)let every_other = <C4 _>; // Note every second cycle onlyModifiers
Section titled “Modifiers”Modifiers are postfix shorthand attached to a single element. There are three, and an element takes at most one:
| Modifier | Effect | Example | Equivalent |
|---|---|---|---|
*n | Play n times within the slot (faster) | [bd*2 sd] | [[bd bd] sd] |
@n | Weight: n× share of the cycle (longer) | [bd@2 sd] | bd gets 2/3, sd 1/3 |
!n | Replicate: n separate slots at normal speed | [bd!2 sd] | [bd bd sd] |
Fast (*n)
Section titled “Fast (*n)”*n squeezes n repetitions into one slot — the slot count stays the same, the element just plays faster:
let hats = [bd sd*2]; // bd in first half; sd twice in second halfDecimals are allowed: *1.5 plays the element one-and-a-half times, cutting the last repetition short.
Weight (@n)
Section titled “Weight (@n)”@n changes how the cycle is shared. Weights are relative — the cycle divides proportionally to the total:
| Pattern | Weights | Distribution |
|---|---|---|
[bd@2 sd] | 2 + 1 = 3 | bd: 2/3, sd: 1/3 |
[bd@3 sd@1] | 3 + 1 = 4 | bd: 3/4, sd: 1/4 |
[a@1 b@2 c@1] | 1 + 2 + 1 = 4 | a: 1/4, b: 1/2, c: 1/4 |
Each element still plays once — just for longer or shorter. Decimals work here too. A common use is a held note before a quick turn:
let phrase = [C4@3 D4]; // Long C4, quick D4 pickupReplicate (!n)
Section titled “Replicate (!n)”!n writes the element n times, as if you’d typed it out — n separate slots at normal speed:
let four_kicks = [bd!4]; // Same as [bd bd bd bd]Unlike *n, which speeds up inside one slot, !n adds slots. Replicate only accepts integers.
Element Decorations
Section titled “Element Decorations”Three more postfixes attach to individual elements. Each is covered in depth elsewhere; here’s the shape of them:
Velocity ^v sets how hard a note is played (0–127):
let accents = [C4^120 C4^60 C4^60 C4^60]; // Accent on beat 1Chords Root:Quality put whole chords in a pattern, with optional inversions:
let progression = [D4:min7 G4:7 C4:maj7~1]; // ii-V-I, last chord invertedSample methods transform individual hits, and chain:
let beat = [bd.vel(1.2) sd.pitch(-5).pan(0.5)];Postfix parts combine in a fixed order: velocity, then euclidean parameters, then modifier — C4^80(3,8)*2. See the grammar reference for the full token table, Music Theory for chord qualities and the chord() function, and Sampler & Sample for all sample methods.
Putting It Together
Section titled “Putting It Together”Back to the beat from the top of the page:
let beat = [bd <sd [sd sd]>, ch*8, <_ oh>];Read it comma by comma — three parallel voices:
| Voice | Pattern | Behavior |
|---|---|---|
| 1 | bd <sd [sd sd]> | Kick, then a snare slot that alternates per cycle |
| 2 | ch*8 | Eight closed hats per cycle |
| 3 | <_ oh> | Open hat every other cycle |
On even cycles voice 1 plays bd sd; on odd cycles the snare slot holds [sd sd], a doubled hit in the same half-cycle. Voice 3 alternates between silence and an open hat. Every technique composes with every other — nesting inside alternation inside parallel voices, to any depth.
use "std/instruments" { Sampler, Kit };
let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("TR-808")));
drums << [<bd [bd bd]> sd, ch!4, <_ _ oh _>];// Kick alternates single/double, snare on the backbeat,// four hats, open hat every fourth cycle
PLAY;Next Steps
Section titled “Next Steps”Two more rhythm-generation tools build on this notation, and a method API transforms any pattern in code.
- Polymetric & Euclidean — phasing meters and algorithmic rhythms
- Transforming Patterns —
.fast(),.reverse(),.transpose()and friends - Mini-Notation Grammar — the complete syntax reference