Note Streams
Note streams are Flow’s inline musical notation. They provide a concise syntax for writing melodies, rhythms, and chord progressions directly in your code.
Basic Syntax
Note streams are delimited by | pipe characters and evaluate to a Sequence:
use "@std"
timesig 4/4 {
Sequence melody = | C4 D4 E4 F4 |
(print (str melody))
}Open in playgroundEach note is a pitch name (A-G), optional accidental, and octave number. Notes without explicit durations are automatically fitted to fill the bar based on the time signature.
Note Names
Flow note literals use [A-G][octave][alteration]:
| Component | Options | Example |
|---|---|---|
| Pitch | A, B, C, D, E, F, G (uppercase) | C, D, G |
| Octave | 0-10 (required when an alteration is used) | C4, A3, G5 |
| Alteration | + / # sharp, - / b flat, ++ double sharp, -- double flat | C4+, B3-, F4##, Bb4 |
timesig 4/4 {
Sequence sharps = | C4+ D4+ F4+ G4+ |
Sequence flats = | B3- E4- A4- D5- |
}Open in playgroundAccidentals stack arbitrarily — the net pitch is (# count + + count) - (b count + - count). So F##4 is F double-sharp at octave 4, and Bb-+bbb resolves the same way (4 flats minus 1 sharp = triple-flat B). Note literals also include the multi-letter enharmonic edges E↔Fb and B↔Cb.
Note: Chord symbols use a different accidental convention:
sfor sharp andffor flat (e.g.,Csmaj7,Bfm). See Chords and Harmony.
H-as-B Alias (German Notation)
With enable hAsB; at the top of a file, H aliases to B and Hb (or H-) aliases to Bb — matching the German convention found in Bach et al.:
enable hAsB;
use "@std"
timesig 4/4 {
Sequence bWvWunderbar = | H4 Hb4 H3 | Note: same as | B4 Bb4 B3 |
}Open in playgroundDuration Suffixes
Append a letter to specify note duration:
| Suffix | Duration | Beats (in 4/4) |
|---|---|---|
w | Whole | 4 |
h | Half | 2 |
q | Quarter | 1 |
e | Eighth | 0.5 |
s | Sixteenth | 0.25 |
t | Thirty-second | 0.125 |
x | Sixty-fourth | 0.0625 |
y | 128th | 0.03125 |
timesig 4/4 {
Sequence mixed = | C4h D4q E4q | Note: 2 + 1 + 1 = 4 beats
Sequence fast = | C4e D4e E4e F4e G4e A4e B4e C5e | Note: 8 eighths
}Open in playgroundAuto-Fit Duration
Notes without a duration suffix are sized to fill the bar evenly:
timesig 4/4 {
Sequence four = | C4 D4 E4 F4 | Note: each becomes a quarter
Sequence three = | C4 E4 G4 | Note: each becomes ~1.33 beats
}
timesig 3/4 {
Sequence waltz = | C4 E4 G4 | Note: each becomes a quarter
}Open in playgroundDotted Notes
Append . after the duration suffix to extend a note by 50%:
timesig 4/4 {
Sequence dotted = | C4q. D4e E4h | Note: 1.5 + 0.5 + 2 = 4 beats
}Open in playgroundRests
Use _ for rests. Rests can have duration suffixes too:
timesig 4/4 {
Sequence auto = | C4 _ E4 F4 | Note: auto-fit rest
Sequence explicit = | C4q _q E4q F4q | Note: quarter rest
}Open in playgroundTied Notes
Use ~ after a note to tie it into the next note (sustain without re-attack):
timesig 4/4 {
Sequence tied = | C4h~ C4h | Note: C4 sustains across the tie
}Open in playgroundCent Offsets (Microtonal)
Use +Nc or -Nc for microtonal adjustments in cents (100 cents = 1 semitone):
timesig 4/4 {
Sequence microtonal = | C4+50c D4 E4-25c F4 |
}Open in playgroundChord Brackets
Enclose notes in [ ] to play them simultaneously:
timesig 4/4 {
Sequence chords = | [C4 E4 G4]q [D4 F4 A4]q [E4 G4 B4]q [C4 E4 G4]q |
}Open in playgroundTuplets
Wrap notes in { } with an explicit ratio N:M followed by a duration suffix to play N notes in the time of M:
timesig 4/4 {
Note: triplet — 3 quarters in the time of 2
Sequence trip = | {3:2 C4 E4 G4}q D4q E4q F4q |
Note: quintuplet of eighths
Sequence five = | {5:4 C4 D4 E4 F4 G4}e D4e E4e |
}Open in playgroundOr use the music21 shorthand {N ...}q — the ratio is inferred from a small lookup table (3→2, 5→4, 6→4, 7→4, 9→8, etc.; counts 2..11 supported):
timesig 4/4 {
Sequence trip = | {3 C4 E4 G4}q D4q E4q F4q | Note: same as {3:2 ...}q
}Open in playgroundPer-note tuplet ratios also work — useful inside otherwise straight bars:
timesig 4/4 {
Note: C4 lasts the time of a /3:2 (triplet eighth)
Sequence mixed = | C4/3:2q D4q E4q F4q |
}Open in playgroundFor arbitrary fractional durations, use C4/N — the note lasts 1/N of a whole note:
timesig 4/4 {
Sequence twelfth = | C4/12 D4/12 E4/12 F4/12 G4/12 A4/12 |
}Open in playgroundVoice Blocks (Polyphony)
A {voice ...} block inside a bar declares a parallel voice. Multiple voice blocks within the same |...| share the bar’s onset and play simultaneously — this is the canonical way to write polyphony:
timesig 4/4 {
Sequence twoVoices = | {voice C4w} {voice C5q D5q E5q F5q} |
Note: a held whole-note bass under a quarter-note melody
}Open in playgroundVoice blocks render identically through both audio and MIDI export — each voice becomes its own track on disk. They can carry their own articulation and dynamics:
timesig 4/4 {
Sequence chorale = | {voice mf C4h E4h} {voice p E5q stacc G5q stacc B5q stacc D6q>} |
}Open in playgroundVoice blocks may not be nested inside other voice blocks. Tuplets inside a voice block work fine.
Named Chords in Note Streams
Use chord symbols directly:
timesig 4/4 {
Sequence prog = | Cmaj7 Am7 Dm7 G7 |
}Open in playgroundSee Chords and Harmony for all chord types.
Roman Numerals
Within a key context, use roman numerals for scale-degree chords:
key Cmajor {
timesig 4/4 {
Sequence mjr = | I IV V I |
Sequence mnr = | ii V7 I |
}
}Open in playgroundFor automatic voice leading, see Chord Progressions.
Dynamics in Note Streams
Dynamic markings are sticky — once placed they set the velocity for all following notes in the bar (and downstream bars) until another marking is seen:
timesig 4/4 {
Sequence dynamic = | ff C4 D4 pp E4 F4 | Note: first two loud, last two soft
}Open in playground| Marking | Velocity | 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 (spike + envelope shape — see Dynamics and Expression) |
fp | 0.75 | Forte-piano |
Inline cresc / decresc
Use cresc and decresc between dynamic endpoints. Unmarked notes get interpolated velocities:
timesig 4/4 {
Sequence growing = | pp C4 cresc D4 E4 ff F4 |
Sequence fading = | ff G4 decresc F4 E4 pp D4 |
}Open in playgroundArticulation in Note Streams
timesig 4/4 {
Sequence accented = | C4q> D4q E4q F4q> | Note: > = accent (suffix)
Sequence staccato = | C4q stacc D4q E4q F4q |
Sequence tenuto = | C4q ten D4q E4q F4q |
Sequence marcato = | C4q marc D4q E4q F4q |
Sequence legato = | C4q leg D4q E4q F4q |
}Open in playground| Articulation | Keyword | Effect (locked envelope) |
|---|---|---|
| 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 | 1.5×→1.0× envelope spike over first 15% of frames |
Articulation marks accept on the same note as a duration suffix. Per-note articulations and dynamics propagate through pitch transforms (transpose, retrograde, etc.) — see Dynamics and Expression for the full reference.
Ghost Notes
Very soft, ornamental notes (velocity ~0.15):
timesig 4/4 {
Sequence ghosty = | C4 (ghost D4) E4 F4 |
}Open in playgroundGrace Notes
Quick ornamental note (32nd duration) before the main note:
timesig 4/4 {
Sequence graceful = | (grace B3) C4 D4 E4 F4 |
}Open in playgroundRandom Choice
Pick a random note from options:
timesig 4/4 {
Note: uniform random
Sequence random = | (? C4 E4 G4) (? C4 E4 G4) (? C4 E4 G4) (? C4 E4 G4) |
Note: weighted random (relative weights)
Sequence weighted = | (? C4:50 E4:30 G4:20) (? C4:50 E4:30 G4:20) _ _ |
Note: seeded random (deterministic)
Sequence seeded = | (?? C4 E4 G4) (?? D4 F4 A4) (?? E4 G4 B4) (?? C4 E4 G4) |
Note: rests as options
Sequence sparse = | (? C4 _) (? E4 _) (? G4 _) (? C4 _) |
}Open in playgroundUse (??set 42) to set a seed and (??reset) to restore it. See Generative Music for more.
Variable References
Use variables inside note streams. Lowercase identifiers are treated as variable references:
Note root = C4
timesig 4/4 {
Sequence mel = | root D4 E4 F4 |
}Open in playgroundMulti-Bar Streams
Separate bars with |:
timesig 4/4 {
Sequence twoBar = | C4 D4 E4 F4 | G4 A4 B4 C5 |
(print (str twoBar))
}Open in playgroundMulti-line bars work too. Adjacent | pipes at line wraps collapse charitably — no empty bars get inserted:
timesig 4/4 {
Sequence longMelody =
| C4 D4 E4 F4
| G4 A4 B4 C5
| D5 C5 B4 A4 |
}Open in playgroundPickup Bars
Prefix the first bar with the pickup keyword to mark it as an anacrusis:
timesig 4/4 {
Sequence withPickup = pickup | E4q F4q | G4 A4 B4 C5 |
}Open in playgroundContext Requirement
Note streams need at minimum a timesig context to determine bar length. For most music you also want tempo and key:
tempo 120 {
timesig 4/4 {
key Cmajor {
Sequence mel = | C4 D4 E4 F4 |
}
}
}Open in playgroundSee Also
- Musical Context - Setting tempo, key, and time signature
- Chords and Harmony - Chord notation and roman numerals
- Chord Progressions - Voice-led
progression | ... |syntax - Dynamics and Expression - Dynamics and articulation details
- Pattern Transforms - Transforming sequences
- Generative Music - Random, Euclidean, variation