Pattern Transforms
Pattern transforms modify sequences in musically meaningful ways. They operate on Sequence values and return new Sequence values (or Buffers for render-level transforms), making them chainable with the flow operator.
All transforms preserve voice-block polyphony ({voice ...} content), chord brackets ([C4 E4 G4]q), tuplet fractions, quantize offsets, legato overlap, and portamento. Voice blocks and chords remain structurally intact after transpose, invert, retrograde, repeat, concat, swell, crescendo, and the rest of the core family.
Pitch Transforms
transpose
Shifts all notes by a number of semitones or cents:
use "@std"
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Note: up 2 semitones
Sequence up2 = mel -> transpose +2st
Note: down 3 semitones
Sequence down3 = mel -> transpose -3st
Note: true cent-precision — +50c shifts CentOffset by 50 cents; +150c = +1 semitone +50c
Sequence upCents = mel -> transpose +200c
}Open in playgroundinvert
Mirrors the pitch intervals around the first note:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence inv = (invert mel)
Note: intervals that went UP now go DOWN by the same amount
}Open in playgroundretrograde
Reverses the order of notes:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence ret = (retrograde mel) Note: F4 E4 D4 C4
}Open in playgroundup / down
Shifts notes by whole octaves:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence high = mel -> up 1 Note: C5 D5 E5 F5
Sequence low = mel -> down 1 Note: C3 D3 E3 F3
Sequence veryHigh = mel -> up 2 Note: C6 D6 E6 F6
}Open in playgroundDuration Transforms
augment
Doubles the duration of each note (toward whole notes):
timesig 4/4 {
Sequence mel = | C4q D4q E4q F4q |
Sequence aug = (augment mel) Note: each quarter → half
}Open in playgrounddiminish
Halves the duration of each note (toward 32nd notes):
timesig 4/4 {
Sequence mel = | C4h D4h |
Sequence dim = (diminish mel) Note: each half → quarter
}Open in playgroundRepetition
repeat
Repeats a sequence N times, optionally with cumulative transposition:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence twice = mel -> repeat 2
Sequence rising = mel -> repeat 3 +4st Note: 3x, each 4 semitones higher
}Open in playgroundconcat
Joins two sequences end-to-end:
timesig 4/4 {
Sequence a = | C4 D4 E4 F4 |
Sequence b = | G4 A4 B4 C5 |
Sequence joined = (concat a b)
}Open in playgroundDynamic Transforms
These transforms modify velocity rather than pitch.
crescendo / decrescendo
Linear velocity ramps:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence growing = mel -> crescendo 0.25 0.875
Sequence fading = mel -> decrescendo 0.875 0.25
}Open in playgroundswell
Rise-then-fall velocity curve:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 G4 A4 B4 C5 |
Sequence swelled = mel -> swell 0.25 0.875
Note: starts soft, peaks in the middle, ends soft
}Open in playgroundTempo-Expression Transforms
These simulate tempo change via velocity shaping (the sequence stays metrically aligned).
ritardando / accelerando
timesig 4/4 {
Sequence slow = | C4 D4 E4 F4 | -> ritardando 0.7
Sequence fast = | C4 D4 E4 F4 | -> accelerando 0.7
}Open in playgroundFor actual tempo interpolation in the rendered audio, see tempoRamp below, or the rit / accel context blocks.
fermata
Doubles the duration of a specific note (by index):
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence held = mel -> fermata 2 Note: index 2 = E4, held longer
}Open in playgroundArticulation Transforms
These shape how notes connect or detach without changing their authored durations.
legato
Sets a DurationOverlap on every note in the sequence — overlap is a multiplier (0.0 = no overlap, 0.5 = each note runs 50% into the next):
timesig 4/4 {
Sequence mel = | C4q D4q E4q F4q |
Sequence smooth = mel -> legato 0.5
}Open in playgroundDistinct from the per-note
legarticulation in note streams, which drives envelope shaping. Both compose.
portamento
Adds a glide time (in milliseconds) between consecutive notes — the engine sweeps pitch over glideMs at the start of each note:
timesig 4/4 {
Sequence mel = | C4q E4q G4q C5q |
Sequence glissy = mel -> portamento 50ms
}Open in playgroundQuantize
Snap notes to a metric grid with adjustable strength and optional swing. Requires a timesig context (the active time signature drives subdivision math):
use "@std"
timesig 4/4 {
Sequence loose = | C4 D4q. E4e F4 |
Note: hard-quantize to eighth-note grid
Sequence tight = (quantize loose e 1.0 0.0)
Note: 50% pull to sixteenths, with light swing
Sequence laidback = (quantize loose s 0.5 0.2)
}Open in playgroundstrength is clamped to [0, 1] and swing to [-1, 1]. At strength=0, swing=0 the transform is a byte-identical no-op.
Texture and Ornamentation
humanize / humanizeGaussian
Two flavors of velocity jitter:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Note: uniform jitter, frozen non-deterministic RNG
Sequence h1 = mel -> humanize 0.2
Note: Gaussian (Box-Muller), seeded — deterministic
Sequence h2 = (humanizeGaussian mel 0.2 42)
}Open in playgroundhumanizeGaussian recurses correctly into voice blocks; prefer it for reproducible renders. See Dynamics and Expression for the full discussion.
trill
Rapid alternation between each note and its upper neighbor at a specified interval:
timesig 4/4 {
Sequence mel = | C4h E4h |
Sequence trilled = mel -> trill +2st
}Open in playgroundtremolo
Rapid repetition of each note:
timesig 4/4 {
Sequence mel = | C4h E4h |
Sequence trem = mel -> tremolo 4 Note: each note repeated 4 times
}Open in playgroundGenerative / Stochastic
vary
Mutate a sequence randomly. Six overloads cover the combinations of mutation type, seed, and scale constraint — supported mutation types are "pitch", "rhythm", "rest", and "velocity":
use "@std"
Sequence s = | C4 D4 E4 F4 G4 |
Sequence v1 = s -> vary(0.3)
Sequence v2 = (vary s 0.5 "pitch")
Sequence v3 = (vary s 0.5 "pitch" 42) Note: seeded
Sequence v4 = (vary s 0.5 "pitch" "Cmajor") Note: diatonic
Sequence v5 = (vary s 0.5 "pitch" "Cmajor" 42) Note: diatonic + seeded
Sequence v6 = (vary s 0.5 "rhythm" 42) Note: seeded rhythm mutationOpen in playgroundSee Generative Music for details.
polyrhythm (buffer-level)
Overlay two sequences with different time signatures. Returns a Buffer:
use "@std"
use "@audio"
tempo 120 {
timesig 3/4 {
Sequence waltz = | A3 E4 E4 |
timesig 4/4 {
Sequence quarters = | C4 C4 C4 C4 |
Buffer mixed = (polyrhythm waltz quarters)
(exportWav mixed "poly.wav")
}
}
}Open in playgroundTidal-Style Combinators
Beyond the core transforms above, a separate @patterns module ships 13 Tidal-style combinators (every, fast, slow, chunk, phase, rev, iter, palindrome, jux, superimpose, sometimes, degrade, sparseSeq). They operate on whole sequences in units of bars and chain naturally with ->:
use "@patterns"
timesig 4/4 {
Sequence base = | C4 D4 E4 F4 | G4 A4 B4 C5 |
Note: every 4th bar, double-speed it
Sequence shifted = base -> (every 4 (fn Sequence s => (fast s 2.0)))
Note: probabilistic drop
Sequence sparse = (sometimes 0.3 (fn Sequence s => (degrade s)) base)
}Open in playgroundSee Generative Music for the full list and per-combinator docs.
Tempo Ramp (buffer-level)
tempoRamp
Renders a sequence with a linearly interpolated tempo from a start to an end BPM. Returns a Buffer:
use "@std"
use "@audio"
timesig 4/4 {
key Cmajor {
Sequence seq = | C4 D4 E4 F4 |
Note: ritardando (120 → 80)
Buffer slowing = (tempoRamp seq 120.0 80.0)
Note: accelerando (80 → 120)
Buffer speeding = (tempoRamp seq 80.0 120.0)
Note: with instrument override
Buffer instrBuf = (tempoRamp seq 120.0 80.0 "piano")
}
}Open in playgroundRitardando produces more frames than a constant-fast render; accelerando produces fewer frames than a constant-slow render.
Chaining Transforms
Transforms chain naturally with the flow operator:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence chain1 = (retrograde (transpose mel +5st))
Sequence chain2 = mel -> up 1 -> repeat 2 -> humanize 0.1
}Open in playgroundTransform Summary
| Transform | Type | Syntax | Effect |
|---|---|---|---|
transpose | Sequence | mel -> transpose +Nst | Shift pitch by semitones / cents |
invert | Sequence | (invert mel) | Mirror intervals around first note |
retrograde | Sequence | (retrograde mel) | Reverse note order |
augment | Sequence | (augment mel) | Double durations |
diminish | Sequence | (diminish mel) | Halve durations |
up | Sequence | mel -> up N | Up N octaves |
down | Sequence | mel -> down N | Down N octaves |
repeat | Sequence | mel -> repeat N | Repeat N times |
repeat | Sequence | mel -> repeat N +Mst | Repeat with transposition |
concat | Sequence | (concat a b) | Join sequences |
crescendo | Sequence | mel -> crescendo start end | Rising velocity |
decrescendo | Sequence | mel -> decrescendo start end | Falling velocity |
swell | Sequence | mel -> swell edge peak | Rise-then-fall velocity |
ritardando | Sequence | mel -> ritardando amount | Slowdown feel (via velocity) |
accelerando | Sequence | mel -> accelerando amount | Speedup feel (via velocity) |
fermata | Sequence | mel -> fermata index | Hold note at index |
legato | Sequence | mel -> legato overlap | Set DurationOverlap per note |
portamento | Sequence | mel -> portamento 50ms | Pitch glide between notes |
quantize | Sequence | (quantize mel res strength swing) | Snap to metric grid (needs timesig) |
humanize | Sequence | mel -> humanize amount | Random velocity variation (uniform, frozen RNG) |
humanizeGaussian | Sequence | (humanizeGaussian mel amount seed) | Gaussian velocity jitter (seeded) |
trill | Sequence | mel -> trill +Nst | Rapid alternation |
tremolo | Sequence | mel -> tremolo N | Rapid repetition |
vary | Sequence | mel -> vary(prob) | Random mutation (6 overloads) |
polyrhythm | Buffer | (polyrhythm a b) | Overlay sequences (LCM cycle) |
tempoRamp | Buffer | (tempoRamp seq startBpm endBpm) | Rendered tempo interpolation |
every / fast / slow / … | Sequence | (every n cb mel) etc. | Tidal-style combinators (opt-in via use "@patterns") |
See Also
- Flow Operator - Chaining with
-> - Dynamics and Expression - Dynamics and articulation
- Note Streams - Creating sequences
- Generative Music -
vary,euclidean, random choice - Musical Context -
rit/accelcontext blocks