Pattern Basics
This content is for v0.7. Switch to the latest version for up-to-date documentation.
Patterns are the core music type in Resonon. They describe sequences of notes, rests, and samples that play over time.
What is a Pattern?
Section titled “What is a Pattern?”A pattern is enclosed in square brackets [...] and contains musical elements:
[C4 E4 G4] // Three notes in sequence[C4 _ E4 _] // Notes with rests (underscore)[bd sd bd sd] // Drum samples (when using a sampler)Cycles and Time Division
Section titled “Cycles and Time Division”Patterns fit into cycles. A cycle is the fundamental time unit in Resonon — patterns repeat every cycle. Cycle duration is controlled by BPM and beats per cycle:
setbpm(120); // 120 BPM (default: 4 beats per cycle)setbpm(140, 4); // 140 BPM, 4 beats per cycleElements within a pattern divide the cycle evenly:
[C4] // One note fills the whole cycle[C4 D4] // Each note gets 1/2 of the cycle[C4 D4 E4 F4] // Each note gets 1/4 of the cycleThe more elements in a pattern, the faster they play:
| Pattern | Elements | Duration per element |
|---|---|---|
[C4] | 1 | Full cycle |
[C4 D4] | 2 | 1/2 cycle each |
[C4 D4 E4] | 3 | 1/3 cycle each |
[C4 D4 E4 F4] | 4 | 1/4 cycle each |
Tempo: BPM and Cycles Per Second
Section titled “Tempo: BPM and Cycles Per Second”Cycle duration depends on BPM and how many beats you assign per cycle. The relationship is:
cps = bpm / 60 / beats_per_cyclecycle_duration = 1 / cps| BPM | Beats/Cycle | Cycle Duration | CPS |
|---|---|---|---|
| 60 | 4 | 4.0 s | 0.25 |
| 120 | 4 | 2.0 s | 0.5 |
| 120 | 8 | 4.0 s | 0.25 |
| 140 | 4 | ~1.71 s | ~0.58 |
| 140 | 8 | ~3.43 s | ~0.29 |
Use the second argument to setbpm when your patterns have more (or fewer) than 4 beats:
setbpm(120, 8); // 8-beat cycles at 120 BPM (4 seconds per cycle)Use _ (underscore) for silent steps:
[C4 _ E4 _] // Play, rest, play, rest[bd _ _ sd] // Kick on 1, snare on 4[_ _ _ sd] // Snare on beat 4 onlyPlaying Patterns
Section titled “Playing Patterns”To hear a pattern, send it to a track and call PLAY:
// MIDI tracklet melody = MidiTrack(1);melody << [C4 E4 G4 E4];PLAY;
// Audio track with samplesuse "std/instruments" { Sampler, Kit };let drums = AudioTrack("drums");drums.load_instrument(Sampler(Kit("cr78")));drums << [bd sd bd sd];PLAY;The << operator sends a pattern to a track.
Pattern Looping
Section titled “Pattern Looping”Patterns repeat indefinitely until you stop them with PAUSE:
let t = MidiTrack(1);t << [C4 D4 E4 F4];PLAY; // Pattern loops forever// ...PAUSE; // Stop playbackNumeric Patterns
Section titled “Numeric Patterns”Numbers in patterns are interpreted as MIDI note values (0-127):
[60 62 64 65] // Same as [C4 D4 E4 F4][C4 62 E4 67] // Mix note names and numbers freelyThis is especially useful for drum programming with General MIDI note numbers:
// GM drum map: 36=kick, 38=snare, 42=closed hh[36 42 38 42]Pattern Types
Section titled “Pattern Types”The syntax you use determines the pattern type:
| Syntax | Type | Behavior |
|---|---|---|
[C4 D4 E4] | Sequence | Elements divide the cycle proportionally |
[C4, E4, G4] | Stack | All elements play simultaneously |
<C4 D4 E4> | Alternating | One element per cycle, rotating |
[bd sd hh] | Sample pattern | Same as Sequence, but for audio samples |
Sequence is the most common type. Elements share the cycle by equal weight (adjustable with @ — see Compact Notation).
Stack plays all elements at the same time, creating chords or layered rhythms. See Nested & Parallel Patterns for details.
Alternating selects one element per cycle and rotates through them. See Nested & Parallel Patterns for details.
Sample patterns behave identically to Sequences, but when sent to an AudioTrack with a sampler loaded, identifiers like bd and sd resolve as sample names instead of note names.
Pattern Constructors
Section titled “Pattern Constructors”You can also create patterns with constructor functions:
// Sequence() builds a sequential pattern (same as [] syntax)Sequence(C4, E4, G4)
// Stack() builds a simultaneous pattern (all notes at once)Stack(C4, E4, G4)
// Alternating() builds a rotating pattern (same as <> syntax)Alternating(C4, E4, G4)
// All three accept an array argumentlet notes = #[C4, D4, E4, F4, G4];Sequence(notes)Stack(notes)Alternating(notes)How Patterns Work
Section titled “How Patterns Work”Patterns are lazy — they compute events on demand, not upfront. Think of a pattern as a recipe, not a recording.
Three key properties:
- On-demand: the scheduler queries one cycle at a time, only computing what it needs right now
- Stateless: each query is independent — you can ask for any cycle in any order
- Infinite by default: patterns repeat forever without storing infinite data
This has a practical consequence: transformations like .fast(2) and .slow(2) adjust the query window, not the data. Chaining many transformations has zero performance cost because nothing is computed until the scheduler asks for events.
See Also
Section titled “See Also”- Nested & Parallel Patterns — Subdivide time and play multiple voices
- Compact Notation — Modifiers for repeating and extending notes
- Euclidean Rhythms — Generate rhythms algorithmically
- Script Patterns — Class-based procedural patterns
- Streams — Stateful evolving patterns