-
Notifications
You must be signed in to change notification settings - Fork 0
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.
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))
}
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.
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, - flat, ++ double sharp, -- double flat |
C4+, B3-, F4++
|
timesig 4/4 {
Sequence sharps = | C4+ D4+ F4+ G4+ |
Sequence flats = | B3- E4- A4- D5- |
}
Note: Chord symbols use a different accidental convention:
sfor sharp andffor flat (e.g.,Csmaj7,Bfm). See Chords and Harmony.
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 |
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
}
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
}
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
}
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
}
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
}
Use +Nc or -Nc for microtonal adjustments in cents (100 cents = 1 semitone):
timesig 4/4 {
Sequence microtonal = | C4+50c D4 E4-25c F4 |
}
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 |
}
Use chord symbols directly:
timesig 4/4 {
Sequence prog = | Cmaj7 Am7 Dm7 G7 |
}
See Chords and Harmony for all chord types.
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 |
}
}
For automatic voice leading, see Chord Progressions.
Dynamic markings set the velocity of following notes:
timesig 4/4 {
Sequence dynamic = | ff C4 D4 pp E4 F4 |
}
| Marking | Velocity | Name |
|---|---|---|
ppp |
~0.1 | Pianississimo |
pp |
~0.2 | Pianissimo |
p |
~0.35 | Piano |
mp |
~0.5 | Mezzo-piano |
mf |
~0.63 | Mezzo-forte (default) |
f |
~0.75 | Forte |
ff |
~0.875 | Fortissimo |
fff |
~1.0 | Fortississimo |
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 |
}
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 |
}
| Articulation | Keyword | Effect |
|---|---|---|
| Accent |
> (suffix) |
Velocity bump |
| Staccato | stacc |
Shortened (~50% duration) |
| Tenuto | ten |
Full sustain |
| Marcato | marc |
Accented + slightly shortened |
Very soft, ornamental notes (velocity ~0.15):
timesig 4/4 {
Sequence ghosty = | C4 (ghost D4) E4 F4 |
}
Quick ornamental note (32nd duration) before the main note:
timesig 4/4 {
Sequence graceful = | (grace B3) C4 D4 E4 F4 |
}
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 _) |
}
Use (??set 42) to set a seed and (??reset) to restore it. See Generative Music for more.
Use variables inside note streams. Lowercase identifiers are treated as variable references:
Note root = C4
timesig 4/4 {
Sequence mel = | root D4 E4 F4 |
}
Separate bars with |:
timesig 4/4 {
Sequence twoBar = | C4 D4 E4 F4 | G4 A4 B4 C5 |
(print (str twoBar))
}
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 |
}
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 |
}
}
}
- 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