Flow

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 playground

Each 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]:

ComponentOptionsExample
PitchA, B, C, D, E, F, G (uppercase)C, D, G
Octave0-10 (required when an alteration is used)C4, A3, G5
Alteration+ / # sharp, - / b flat, ++ double sharp, -- double flatC4+, B3-, F4##, Bb4
timesig 4/4 {
    Sequence sharps = | C4+ D4+ F4+ G4+ |
    Sequence flats  = | B3- E4- A4- D5- |
}
Open in playground

Accidentals 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: s for sharp and f for 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 playground

Duration Suffixes

Append a letter to specify note duration:

SuffixDurationBeats (in 4/4)
wWhole4
hHalf2
qQuarter1
eEighth0.5
sSixteenth0.25
tThirty-second0.125
xSixty-fourth0.0625
y128th0.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 playground

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

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

Rests

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 playground

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

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

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

Tuplets

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 playground

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

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

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

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

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

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

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

For 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
MarkingVelocityName
ppp0.125Pianississimo
pp0.25Pianissimo
p0.375Piano
mp0.5Mezzo-piano
mf0.625Mezzo-forte (default)
f0.75Forte
ff0.875Fortissimo
fff1.0Fortississimo
sfz0.95Sforzando (spike + envelope shape — see Dynamics and Expression)
fp0.75Forte-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 playground

Articulation 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
ArticulationKeywordEffect (locked envelope)
Accent> (suffix)+0.30 velocity (clamped)
Staccatostacc25% duration, sustain = 0, release × 0.5
Marcatomarc25% duration + Accent’s +0.30 velocity boost
Tenutoten100% duration, release × 1.2 (soft tail)
Legatoleg110% duration + crossfade overlap into next note
Sforzandosfz dynamic1.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 playground

Grace Notes

Quick ornamental note (32nd duration) before the main note:

timesig 4/4 {
    Sequence graceful = | (grace B3) C4 D4 E4 F4 |
}
Open in playground

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

Use (??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 playground

Multi-Bar Streams

Separate bars with |:

timesig 4/4 {
    Sequence twoBar = | C4 D4 E4 F4 | G4 A4 B4 C5 |
    (print (str twoBar))
}
Open in playground

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

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

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

See Also