Flow

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 playground

invert

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 playground

retrograde

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 playground

up / 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 playground

Duration 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 playground

diminish

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 playground

Repetition

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 playground

concat

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 playground

Dynamic 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 playground

swell

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 playground

Tempo-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 playground

For 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 playground

Articulation 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 playground

Distinct from the per-note leg articulation 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 playground

Quantize

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 playground

strength 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 playground

humanizeGaussian 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 playground

tremolo

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 playground

Generative / 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 mutation
Open in playground

See 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 playground

Tidal-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 playground

See 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 playground

Ritardando 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 playground

Transform Summary

TransformTypeSyntaxEffect
transposeSequencemel -> transpose +NstShift pitch by semitones / cents
invertSequence(invert mel)Mirror intervals around first note
retrogradeSequence(retrograde mel)Reverse note order
augmentSequence(augment mel)Double durations
diminishSequence(diminish mel)Halve durations
upSequencemel -> up NUp N octaves
downSequencemel -> down NDown N octaves
repeatSequencemel -> repeat NRepeat N times
repeatSequencemel -> repeat N +MstRepeat with transposition
concatSequence(concat a b)Join sequences
crescendoSequencemel -> crescendo start endRising velocity
decrescendoSequencemel -> decrescendo start endFalling velocity
swellSequencemel -> swell edge peakRise-then-fall velocity
ritardandoSequencemel -> ritardando amountSlowdown feel (via velocity)
accelerandoSequencemel -> accelerando amountSpeedup feel (via velocity)
fermataSequencemel -> fermata indexHold note at index
legatoSequencemel -> legato overlapSet DurationOverlap per note
portamentoSequencemel -> portamento 50msPitch glide between notes
quantizeSequence(quantize mel res strength swing)Snap to metric grid (needs timesig)
humanizeSequencemel -> humanize amountRandom velocity variation (uniform, frozen RNG)
humanizeGaussianSequence(humanizeGaussian mel amount seed)Gaussian velocity jitter (seeded)
trillSequencemel -> trill +NstRapid alternation
tremoloSequencemel -> tremolo NRapid repetition
varySequencemel -> vary(prob)Random mutation (6 overloads)
polyrhythmBuffer(polyrhythm a b)Overlay sequences (LCM cycle)
tempoRampBuffer(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