Skip to content

Mini-Notation Grammar

Mini-notation is the compact syntax inside pattern brackets. One dense element, annotated:

let p = [C4^100(3,8)*2];
// ──┬─┬── ─┬── ┬
// │ │ │ └ modifier: fast ×2
// │ │ └ euclidean: 3 hits over 8 steps
// │ └ velocity: 100
// └ element: note C4
SyntaxNameMeaning
[a b]SequenceElements subdivide the slot equally
[a b, c d]ParallelComma-separated groups play simultaneously
<a b>AlternatingOne element per cycle, rotating
{a b c}PolymetricOne element per step (one step = one cycle unless %N)
{a b, c d}Polymetric stackGroups stretched to the same span (polyrhythm)
{…}%NSubdivisionN steps per cycle
C4, c#3, Bb-1NoteNote name + octave (−1 to 9)
_RestSilence
60, 62.5, -3NumberNumeric value (MIDI pitch on note tracks)
C4:min7ChordRoot + quality
C4:maj~1Inversion~n inverts the chord n times
^1, ^-2DegreeScale degree (resolved by a key)
^1:maj7, ^3:Degree chordQuality optional; bare : = diatonic
kickSampleIdentifier resolved against the track’s sampler
kick.pan(-0.5)Sample methodChainable, numeric arguments only
C4^100Velocity0–127, after note/number/chord/sample
C4(3,8), C4(3,8,2)Euclideanhits, steps, optional rotation
C4*2FastRepeat n times within the slot (decimals allowed)
C4@2Weightn× share of the slot (decimals allowed)
C4!2Replicaten separate equal slots (integer only)

Postfix parts combine in this fixed order: velocity, euclidean, modifier — e.g. C4^80(3,8)*2. At most one of * / @ / ! per element.

[a b c] divides its time slot equally among its elements. Nesting subdivides recursively; groups of unequal size divide their own slots independently.

let seq = [C4 D4 E4]; // thirds of a cycle
let nested = [[C4 D4] E4]; // C4 0–1/4, D4 1/4–1/2, E4 1/2–1
let uneven = [[C4 D4 E4] [F4 G4]]; // triplet against duplet

A comma inside […] splits the pattern into groups that play simultaneously, each on its own grid.

let chord = [C4, E4, G4]; // all at once
let layers = [bd bd bd, sd sd]; // 3:2 — kick thirds, snare halves

<a b c> plays one element per cycle, selected by cycle % length. Each selected element fills the slot the <…> occupies.

let alt = <C4 D4 E4>; // cycle 0: C4, cycle 1: D4, …
let inner = [bd <sd [sd sd]>]; // second slot varies per cycle

{a b c} assigns each element one step. Without %N a step is a full cycle; %N packs N steps into each cycle. Comma-separated groups are each stretched across the same span, producing polyrhythms.

let steps = {C4 D4 E4}%4; // 4 steps per cycle over 3 notes — phasing
let poly = {C4 E4 G4, F4 A4}; // 3 against 2
let both = {C4 D4 E4, F4 G4}%6;
  • Note names: C D E F G A B with #/b, upper- or lowercase, octave −1 to 9 (C4 = MIDI 60).
  • _ is a rest; it takes a slot like any element and accepts euclidean/modifier postfixes.
  • Bare numbers (integers, decimals, negative) are numeric values — MIDI pitches on note tracks, plain values in control patterns.
let mixed = [C4 _ eb3 60];

Root:Quality with optional inversion ~n (positive moves lowest notes up an octave; negative moves highest notes down).

let prog = [D4:min7 G4:7 C4:maj7~1];

Qualities (aliases in parentheses normalize at parse time):

CategoryQualities
Triadsmaj, min (m), dim, aug
Sevenths7 (dom, dom7), maj7, min7 (m7), dim7, aug7
Extended9, maj9, min9 (m9), add9
Sixths6, maj6, min6 (m6)
Suspended / powersus2, sus4, 5

9 is a dominant ninth (includes the flat seventh); maj9 has the major seventh.

^n is a scale degree (1 = root; negative wraps downward). ^n:quality builds a chord on the degree; a bare colon (^n:) takes the diatonic quality from the key. Degrees stay symbolic until resolved by a key context (e.g. .in_key()).

let degrees = [^1 ^4 ^5 ^-2];
let diatonic = [^1: ^4: ^5:maj7];

^v directly after a note, number, chord, or sample sets velocity (integer 0–127, clamped). On a chord it applies to every chord note. Not valid on rests.

let accents = [C4^120 C4^60 C4:maj^80 bd^110];

Standalone ^n is a scale degree; ^n attached to an element is velocity.

(hits, steps) distributes hits onsets as evenly as possible over steps subdivisions of the element’s slot; a third argument rotates the result by that many steps.

let tresillo = [C4(3,8)];
let rotated = [C4(3,8,2)];
let drum = [bd(3,8) hh(5,8)];

One modifier per element, after velocity and euclidean parts.

ModifierEffectEquivalent
*nPlays n times within the slot (sped up); decimals allowed — *1.5 cuts the last repetition short[bd*2][[bd bd]]
/nStretched over n cycles, advancing one slice per cycle; decimals allowed[a b]/2a on cycle 0, b on cycle 1
@nElement’s slot share is weighted n against its siblings; decimals allowed[bd@2 sd] → bd 2/3, sd 1/3
!nn separate copies, each in its own slot at normal speed; integer only[bd!2][bd bd]
let mods = [C4*2 D4@2 E4!3];
let slowed = [[C4 D4]/2 E4];

To slow a whole pattern, use the .slow(n) pattern method; the /n modifier applies the same stretch to a single element.

Inside patterns, a bare identifier names a sample in the track’s sampler; methods chain with numeric arguments only.

let beat = [bd.vel(1.2) sd.pitch(-5).pan(0.5) hh.slice(0, 0.5)*4];
MethodMeaning
vel(n)Hit velocity (1.0 = unchanged)
pitch(semitones)Pitch shift
pan(position)Stereo position, −1.0 to 1.0
reverse()Play backwards
slice(start, end)Play a portion, 0–1 range

See Sampler & Sample for the full method reference.

Any structure nests inside any other: patterns in alternations, polymeters in sequences, alternations in polymeters, and so on, to arbitrary depth. Structures ([…], <…>, {…}) accept euclidean parameters and modifiers as postfixes, but not velocity.

let kitchen_sink = [
bd <sd [sd sd]>,
{hh hh hh}%8,
<_ oh>
];