Skip to content

Nested & Parallel Patterns

Resonon provides three ways to structure patterns beyond simple sequences: nesting for time subdivision, parallel for simultaneous voices, and alternating for cycling through options.

Nested patterns subdivide time within their slot. Put patterns inside patterns to create faster subdivisions:

[[C4 D4] E4] // First half subdivided into C4, D4
// C4: 0-1/4, D4: 1/4-1/2, E4: 1/2-1

The outer pattern has two slots: [C4 D4] and E4. The inner pattern [C4 D4] divides its slot (the first half) into two equal parts.

Each nesting level divides its parent slot evenly among its children. The duration of any note is:

duration = parent_slot_duration / number_of_siblings

This rule applies recursively. For [[[C4 D4] E4] F4]:

NoteNesting depthCalculationDuration
F41 (outer)1 / 21/2 cycle
E42 (middle)1/2 / 21/4 cycle
C43 (inner)1/4 / 21/8 cycle
D43 (inner)1/4 / 21/8 cycle
[[C4 D4 E4] F4] // C4, D4, E4 share first half; F4 gets second half
[C4 [D4 E4]] // C4 gets first half; D4, E4 share second half
[C4 [D4 [E4 F4]]] // Progressive subdivision

Deep nesting creates complex rhythms:

[[[C4 D4] E4] F4] // C4: 0-1/8, D4: 1/8-1/4, E4: 1/4-1/2, F4: 1/2-1

A 3-level deep example with full timing breakdown:

[[[C4 D4] [E4 F4]] G4]
// Level 1: [[...] G4] → two slots of 1/2 each
// Level 2: [[C4 D4] [E4 F4]] → two slots of 1/4 each
// Level 3: [C4 D4] → two slots of 1/8 each; [E4 F4] → two slots of 1/8 each
// Result: C4: 0-1/8, D4: 1/8-1/4, E4: 1/4-3/8, F4: 3/8-1/2, G4: 1/2-1

Multiple nested groups subdivide both halves:

[[C4 D4] [E4 F4]] // Both slots subdivided into pairs

Nested groups don’t need the same number of elements. Each group divides its own slot independently:

[[C4 D4 E4] [F4 G4]]
// First half: 3 notes → each gets 1/6 of the cycle
// Second half: 2 notes → each gets 1/4 of the cycle
NoteGroupSlot durationNote durationTime span
C4first (3 notes)1/21/60 – 1/6
D4first (3 notes)1/21/61/6 – 1/3
E4first (3 notes)1/21/61/3 – 1/2
F4second (2 notes)1/21/41/2 – 3/4
G4second (2 notes)1/21/43/4 – 1

This naturally produces mixed rhythmic groupings — triplets against duplets, quintuplets against pairs, and so on.

Comma separates patterns that play simultaneously:

[C4, E4, G4] // C major chord (all notes at once)

All three notes start and end at the same time, creating a chord.

Use parallel patterns for counterpoint or layered rhythms:

[C4 D4, E4 F4] // Two melodic lines in parallel
[C4 D4, E4 F4, G4 A4] // Three parallel lines

Each voice in a parallel pattern is queried with the same time window but produces events on its own grid. Voices don’t need the same number of elements:

[C4 D4, E4 F4 G4]
// Voice 1: 2 elements → each gets 1/2 of the cycle
// Voice 2: 3 elements → each gets 1/3 of the cycle
TimeVoice 1Voice 2
0C4 startsE4 starts
1/3F4 starts
1/2D4 starts
2/3G4 starts
1cycle repeatscycle repeats

The result is five separate note onsets within one cycle — a polyrhythmic texture, not a chord.

Different element counts per voice create polyrhythmic relationships. A classic 3-against-2:

[bd bd bd, sd sd]
// Voice 1 (kick): 3 hits → every 1/3 of the cycle
// Voice 2 (snare): 2 hits → every 1/2 of the cycle
TimeKickSnare
0bdsd
1/3bd
1/2sd
2/3bd

Only the downbeat aligns — the rest is a 3:2 polyrhythm.

Each voice in a parallel pattern can use nesting independently:

[[C4 D4] E4, G4 [A4 B4]]
// Voice 1: [C4 D4] fills first half (C4: 0-1/4, D4: 1/4-1/2), E4 fills second half
// Voice 2: G4 fills first half, [A4 B4] fills second half (A4: 1/2-3/4, B4: 3/4-1)

This lets you create intricate rhythmic layers where each voice has its own subdivision structure.

Parallel patterns are essential for drum programming:

[bd _ bd _, _ sd _ sd, ch*8]
// Three parallel layers:
// - Kick on 1 and 3
// - Snare on 2 and 4
// - Hi-hat on every 8th

Alternating patterns use angle brackets <...> and play one element per cycle, rotating through them:

<C4 D4 E4> // Cycle 0: C4, Cycle 1: D4, Cycle 2: E4, Cycle 3: C4...

This differs from sequential patterns:

PatternBehavior
[bd sd hh]All three play within each cycle
<bd sd hh>One per cycle, rotating

Each alternating element fills the entire cycle when it’s selected. The selection follows a simple rotation:

selected_element = cycle_number % number_of_elements
Cycle<C4 D4 E4> playsWhy
0C40 % 3 = 0
1D41 % 3 = 1
2E42 % 3 = 2
3C43 % 3 = 0
4D44 % 3 = 1

The selected element gets the full time slot — it behaves exactly as if it were the only element in that position for that cycle.

Alternating patterns are great for evolving sequences:

<[C4 D4] [E4 F4] [G4 A4]> // Alternates between melodic fragments
<[C4 C4 C4 C4] [C4 D4 E4 F4]> // Steady vs moving

Create variation within a larger pattern:

[<C4 E4> G4] // First note alternates, second fixed
[<C3 [C3 C3]> E3] // Alternating kick patterns with steady snare
[<C4 D4> <E4 F4>] // Two alternating slots
// Verse/chorus alternation
<[C4 E4 G4 E4] [C4 F4 A4 F4]>
// Call and response
<[C4 D4 E4 _] [_ _ _ G4]>
// Note every other cycle
<C4 _>

You can also build alternating patterns with a constructor:

Alternating(C4, E4, G4) // Same as <C4 E4 G4>
// Also accepts an array
let notes = #[C4, D4, E4, F4, G4];
Alternating(notes)

The real power comes from combining these techniques:

// Evolving drum pattern with layered elements
[bd <sd [sd sd]>, ch*8, <_ oh>]
// Chord progression with alternating bass
[<C3 F3 G3 F3>, [C4 E4 G4]]
// Complex polyrhythm
[[bd bd] sd, ch*3, <oh _>]

Complex patterns combine nesting, parallel, and alternation. Here’s how to read [bd <sd [sd sd]>, [ch ch ch], <_ oh>] step by step:

Structure: Three parallel voices separated by commas.

VoicePatternBehavior
1bd <sd [sd sd]>Kick, then alternating snare
2[ch ch ch]Three hi-hats per cycle
3<_ oh>Open hat every other cycle

Cycle 0:

TimeVoice 1Voice 2Voice 3
0bdch_ (rest)
1/3ch
1/2sd
2/3ch

Cycle 1:

TimeVoice 1Voice 2Voice 3
0bdchoh
1/3ch
1/2sd
2/3sdch
3/4sd

Voice 1 alternates its second slot: cycle 0 plays a single sd, cycle 1 plays [sd sd] (two hits in the same time). Voice 3 alternates between silence and an open hat.

A complete drum pattern using all three techniques:

use "std/instruments" { Sampler, Kit };
let drums = AudioTrack(
Sampler(Kit("808")),
[<bd [bd bd]> sd, [ch ch ch ch], <_ _ oh _>]
);
// Kick: alternates between single and double hit
// Snare: steady on beat 2
// Hi-hat: steady 16ths
// Open hat: every 4th cycle on beat 3