7.10.6. STRUDEL-06 — Stacking & Combining
Strudel patterns are values, not statements — and once you have a few of them, the next question is how to combine them. This tutorial walks through four structural combinators that take patterns as input and return a new pattern:
|
vertical |
all patterns play simultaneously |
|
horizontal |
pattern i plays during cycle (i mod N) |
|
vertical |
a base pattern plus stacked transforms of itself |
|
vertical |
overlay one transformed copy of a pattern on top |
All four return a fresh Pattern, so you can pipe them through
setters (gain, room, orbit, …) just like any other pattern.
7.10.6.1. Part A: stack — play patterns at the same time
stack takes an array of patterns and merges their events into the
same cycle. Use it to combine independent voices (bass + lead + drums):
let pat <- stack([
note("c3 e3 g3 c4", "sine") |> sustain(0.5),
note("c5 ~ ~ g4 ~ ~ e4 ~", "triangle") |> sustain(0.3) |> gain(0.4)
])
Each element of the array is treated as one voice that runs in parallel.
Note that stack consumes its argument array (var pats parameter),
so you cannot reuse the inner patterns afterwards.
7.10.6.2. Part B: cat — sequence patterns across cycles
cat is the horizontal counterpart. With N patterns in the array,
pattern i plays during cycle (i mod N), each stretched to fill exactly
one cycle. This is the standard way to glue short building blocks into
longer arrangements:
let pat <- cat([
note("c4 e4 g4 c5", "sine") |> sustain(0.4),
note("c5 g4 e4 c4", "sine") |> sustain(0.4),
note("c4 e4 g4 b4", "sine") |> sustain(0.4)
])
Three cycles of melody, then it loops.
7.10.6.3. Part C: layer — chord-from-melody
layer(pats, base) stacks base plus every pattern in pats.
The idiom is to derive every layer from the same source so that one
melody plays as a chord:
let pat <- layer([
note("c4 e4 g4 c5", "sine") |> sustain(0.4) |> transpose(4.0), // major third
note("c4 e4 g4 c5", "sine") |> sustain(0.4) |> transpose(7.0) // perfect fifth
], note("c4 e4 g4 c5", "sine") |> sustain(0.4)) // root
Each note plays as a triad: root + third + fifth.
7.10.6.4. Part D: superimpose — overlay a transformed copy
superimpose(pat, fn) is equivalent to stack([pat, fn(pat)]) but
reads more naturally because it takes the transform as a lambda. Below
we add a faster octave-up echo on top:
let pat <- superimpose(note("c4 e4 g4 c5", "sine") |> sustain(0.4),
@(p) => gain(fast(transpose(p, 12.0), 2.0lf), 0.4))
The lambda has type @(Pattern) => Pattern — the same shape every
transforming combinator (jux, off, superimpose, …) expects.
See also
Full source: tutorials/daStrudel/daStrudel_06_stacking_combining.das
Previous tutorial: STRUDEL-05 — Euclidean Rhythms
Next tutorial: STRUDEL-07 — Per-Voice FX & Combinators
Related: Lambdas and Closures, Functions