Dynamics and Expression
Flow provides comprehensive support for musical expression through dynamics markings, articulation, ornaments, and velocity/tempo transforms.
Dynamic Markings
Dynamic markings control note velocity (loudness). They can be used inline in note streams or as context blocks.
Inline Dynamics
Place dynamic markings before notes to set their velocity:
timesig 4/4 {
Sequence contrast = | ff C4 D4 pp E4 F4 |
Note: C4 and D4 are loud, E4 and F4 are soft
}Open in playground| Marking | Velocity | Italian Name |
|---|---|---|
ppp | 0.125 | Pianississimo |
pp | 0.25 | Pianissimo |
p | 0.375 | Piano |
mp | 0.5 | Mezzo-piano |
mf | 0.625 | Mezzo-forte (default) |
f | 0.75 | Forte |
ff | 0.875 | Fortissimo |
fff | 1.0 | Fortississimo |
sfz | 0.95 | Sforzando — also drives an envelope spike (see below) |
fp | 0.75 | Forte-piano |
Dynamic markings are sticky: once set, they apply to every following note in the stream until the next marking. They propagate through pitch transforms (transpose, retrograde, etc.) — see Velocity Preservation below.
Inline Crescendo/Decrescendo
Use cresc and decresc between dynamic markings for smooth transitions:
timesig 4/4 {
Note: Gradual crescendo from pp to ff
Sequence growing = | pp C4 cresc D4 E4 ff F4 |
Note: D4 and E4 get interpolated velocities between pp and ff
Note: Gradual decrescendo from ff to pp
Sequence fading = | ff G4 decresc F4 E4 pp D4 |
}Open in playgroundDynamics Context Block
Set a default velocity for all notes in scope:
dynamics f {
Note: All notes here default to forte
Sequence loud = | C4 D4 E4 F4 |
dynamics pp {
Note: Inner block overrides to pianissimo
Sequence soft = | C4 D4 E4 F4 |
}
}Open in playgroundArticulation
Articulation marks change how individual notes are played:
Accent (>)
Append > to a note for emphasis (higher velocity):
timesig 4/4 {
Sequence accented = | C4q> D4q E4q F4q> |
Note: C4 and F4 are accented
}Open in playgroundNamed Articulations
Place articulation keywords before the affected note:
timesig 4/4 {
Sequence stac = | C4q stacc D4q E4q F4q | Note: staccato (short)
Sequence ten = | C4q ten D4q E4q F4q | Note: tenuto (sustained)
Sequence marc = | C4q marc D4q E4q F4q | Note: marcato (strongly accented)
Sequence legArt = | C4q leg D4q E4q F4q | Note: legato (overlapping)
}Open in playground| Articulation | Keyword | Locked envelope effect |
|---|---|---|
| Accent | > (suffix) | +0.30 velocity (clamped) |
| Staccato | stacc | 25% duration, sustain = 0, release × 0.5 |
| Marcato | marc | 25% duration + Accent’s +0.30 velocity boost |
| Tenuto | ten | 100% duration, release × 1.2 (soft tail) |
| Legato | leg | 110% duration + crossfade overlap into next note |
| Sforzando | sfz (dynamic) | Velocity 0.95 + 1.5×→1.0× envelope spike over the first 15% of frames |
The envelope rules are locked across all 9 shipping synthesizers (piano, brass, sax, drums, bell, flute, organ, strings, wavetable) — drums opt out of articulation shaping. The sampled-instrument path (piano, brass, sax, strings, flute, bell, SFZ) additionally applies per-articulation A/D/S/R multipliers on top of the locked shape, so e.g. a sampled-piano staccato gets the duration cut plus a brighter decay shaping.
The per-note
legarticulation is distinct from thelegato(seq, overlap)transform — the articulation drives envelope shaping per note; the transform setsDurationOverlapfor the whole sequence. They compose: a note withlegANDlegato(seq, 0.5)applied renders at 1.0 × 1.10 × 1.5 = 1.65 of its authored duration.
Ornaments
Ghost Notes
Very soft notes (velocity ~0.15), used for subtle rhythmic feel:
timesig 4/4 {
Sequence ghosty = | C4 (ghost D4) E4 F4 |
Note: D4 is barely audible, like a "felt" note
}Open in playgroundGhost notes default to a short (sixteenth) duration. They’re commonly used in jazz and funk drumming/bass to add groove without overpowering the beat.
Grace Notes
Quick ornamental notes (32nd duration, velocity ~0.5) placed before the main note:
timesig 4/4 {
Sequence graceful = | (grace B3) C4 D4 E4 F4 |
Note: B3 plays as a quick pick-up into C4
}Open in playgroundGrace notes are decorative pitches that “lean into” the following note.
Trill
Rapid alternation between a note and its upper neighbor:
timesig 4/4 {
Sequence mel = | C4h E4h |
Sequence trilled = mel -> trill +2st
Note: C4 alternates rapidly with D4 (2 semitones up)
Note: E4 alternates rapidly with F#4
}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 at 1/4 the original duration
}Open in playgroundVelocity Transforms
crescendo
Gradually increases velocity across the sequence:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence growing = mel -> crescendo 0.25 0.875
Note: linearly from pp (0.25) to ff (0.875)
}Open in playgrounddecrescendo
Gradually decreases velocity:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence dying = mel -> decrescendo 0.875 0.25
}Open in playgroundswell
Velocity rises to the middle then falls back:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 G4 A4 B4 C5 |
Sequence swelled = mel -> swell 0.25 0.875
Note: starts at 0.25, peaks at 0.875 in the middle, returns to 0.25
}Open in playgroundTempo Expression
ritardando
Simulates a gradual slowdown (via velocity reduction):
timesig 4/4 {
Sequence mel = | mf C5q B4q A4q G4q |
Sequence slowing = mel -> ritardando 0.7
}Open in playgroundaccelerando
Simulates a gradual speedup (via velocity increase):
timesig 4/4 {
Sequence mel = | mf C4q D4q E4q F4q |
Sequence speeding = mel -> accelerando 0.7
}Open in playgroundfermata
Doubles the duration of a specific note:
timesig 4/4 {
Sequence mel = | mf C4q D4q E4q F4q |
Sequence held = mel -> fermata 2
Note: E4 (index 2) gets double duration
}Open in playgroundHumanize
Two flavors of velocity jitter ship:
humanize (uniform)
Adds subtle random velocity variation for a natural, “human-played” feel. Uniform distribution, shared (non-deterministic) RNG — frozen for backward compatibility:
timesig 4/4 {
Sequence mel = | C4 D4 E4 F4 |
Sequence human = mel -> humanize 0.2
Note: amount 0.0-1.0 controls the variation range
Note: 0.2 = up to 4% velocity variation (0.2 * 20%)
}Open in playgroundhumanizeGaussian (Box-Muller, seeded)
A deterministic, Gaussian-distributed alternative. Takes an explicit seed, so two runs at the same seed are byte-identical. Recurses correctly into voice blocks:
timesig 4/4 {
Sequence mel = | {voice C4w} {voice E4q G4q B4q C5q} |
Sequence h1 = (humanizeGaussian mel 0.3 42) Note: seed = 42
Sequence h2 = (humanizeGaussian mel 0.3 42) Note: identical to h1
}Open in playgroundPrefer humanizeGaussian for any sequence you plan to render reproducibly (showcases, regression tests, etc.).
Gain vs. Volume
Two buffer-level gain primitives ship — they differ only in how they interpret their second argument, so the function name documents your intent:
gain(buf, dB)— the second argument is in decibels. Negative attenuates, positive amplifies.volume(buf, multiplier)— the second argument is a linear multiplier.0.5= half-amplitude;2.0= double-amplitude.
use "@audio"
Buffer quieter = rendered -> gain -6dB Note: half loudness (perceptual)
Buffer doubled = rendered -> volume 2.0 Note: double the sample magnitudeOpen in playgroundBoth emit clipping warnings to stderr when post-multiplication samples exceed 1.0. volume rejects negative values — use gain for dB attenuation.
Velocity Preservation
Velocity and articulation are preserved through pitch transforms:
timesig 4/4 {
Sequence expressive = | ff C4q> D4q pp E4q stacc F4q |
Note: Transposing preserves dynamics and articulation
Sequence transposed = expressive -> transpose +2st
Note: Retrograde preserves them too
Sequence reversed = (retrograde expressive)
}Open in playgroundCombining Expression Techniques
use "@std"
use "@audio"
tempo 72 {
timesig 4/4 {
key Cmajor {
section intro {
Sequence phrase = | pp C4q E4q G4q C5q | -> crescendo 0.2 0.7
Sequence melody = | mf E4q G4q B4q E5q | -> humanize 0.1
}
section development {
Sequence theme = | f C4q> D4q E4q stacc F4q |
Sequence variation = theme -> transpose +4st -> decrescendo 0.8 0.4
}
section climax {
Sequence peak = | C4q E4q G4q C5q E5q G5q C6q C6q | -> swell 0.5 1.0
}
section ending {
Sequence resolve = | mp G4q E4q C4h | -> ritardando 0.5
Sequence finalChord = | pp C4w |
}
Song piece = [intro development climax ending]
Buffer buf = (renderSong piece "piano")
}
}
}Open in playgroundSee Also
- Note Streams - Inline dynamics and articulation syntax
- Pattern Transforms - All transform functions
- Musical Context - Dynamics context blocks
- Generative Music -
varyfor stochastic expression