Flow Language Wiki
Flow is a statically-typed, interpreted programming language designed for music production. It combines functional programming primitives with music-specific syntax and semantics, providing a seamless path from composition to audio export and notation interchange. The interpreter is written in C# targeting .NET 10.
Current status: v1.5 shipped publicly with three showcase pieces: “In Five Voices” (symphony), “Stride & Stomp” (ragtime), and “pulse” (EDM). The language is still pre-traction; breaking changes can still land in single commits, and there is no migration CLI yet.
Key Features
- Static typing with 16 primitive and 22 music-aware types (
Note,Chord,Sequence,Song,Bar,Buffer,Tuning,Sfz,MarkovModel,LsystemModel, etc.) - Flow operator (
->) for elegant function chaining; tuple-unpack flow (~>) for multi-arg dispatch - Inline note streams (
| C4 D4 E4 F4 |) with durations, dynamics, articulation, ornaments - Musical context blocks —
tempo,timesig,key,swing,voicePool,tuning,pan,gain,dynamics,rit,accel - Pattern transforms — transpose, invert, retrograde, augment, diminish, humanize, trill, tremolo, vary, polyrhythm, and more
- Tidal-style combinators —
every,fast,slow,jux,degrade,sometimes,palindrome(via@patterns) - Generative primitives — Markov chains, L-systems, cellular automata, chaos maps, Euclidean rhythms (via
@generative) - Chord-aware improvisation —
(jam over=chords style=#jazz)with composer-editable style packs (via@improv) - Tuples
<<a, b, c>>with per-position types, structural equality, and destructuring assignment - Generic
Dict<K, V>with insertion-order preservation and 14-op surface - Symbol primitive
#foo— interned, pointer-equality, distinct from String - Pattern matching —
(match scrutinee | pat => body | _ => default)with music-aware patterns - Universal named arguments —
(jam over=chords style=#jazz length=8)works on any function with named params - Built-in synthesizers — sample-based piano (4 velocity layers), brass, sax, flute, strings, bell, organ, drums; raw oscillators; user-defined wavetables
- SFZ orchestral sampler — load VSCO Community Edition or any SFZ patch via
loadSfz - Microtonal tuning — cent offsets in note streams, Scala
.sclloader, named-tuning pragmas,tuning { }blocks - Audio effects — Schroeder reverb, biquad filters, compressor, sidechain, delay, gain, constant-power panning, fades; granular synthesis, time-stretch, pitch-shift
- Song structure — sections (parameterized + overloaded), arrangements with
*Nrepeats, multi-track voices, polyphony - Harmony — chord literals, roman numerals, scales, arpeggios, voice-led
progression | I IV V I | - Vocalization — formant-synthesized vowels/syllables and a TTS hook
- Loops —
for/whilewithbreak/continue - String interpolation —
$"text {expr}"with escape support - Lambdas, closures, higher-order functions, function-type annotations
- Playback — blocking
play, non-blockingstream, loop, preview - Export — WAV (16/24/32-bit), Standard MIDI Files, MusicXML 3.1, LilyPond 2.24+
- Import — WAV, MIDI (via the
flow midi2flowCLI), ABC 2.1, PC-98 MML - Tooling —
flowCLI (run/eval/repl/watch/play/render/flow2midi/midi2flow/check/new/version/lsp/test/doc), VSCode extension, LSP for Neovim / Helix / Emacs / Zed
For the full, up-to-date inventory see FEATURES.md in the repo.
Wiki Pages
Getting Started
- Quick Start — Install, run your first script, hear your first melody
Core Language
- Language Basics — Variables, types, tuples, dicts, symbols, match, named args, comments, scoping
- Functions — Procedures, lambdas, closures, overloading, named args, function types
- Flow Operator — The
->pipe operator,~>tuple unpack,as NAMEchain naming - Collections — Arrays,
Dict<K, V>, and list operations - Loops —
for,while,break,continue - String Interpolation —
$"..."syntax
Music Features
- Note Streams — Inline musical notation
- Musical Context — Tempo, key, time signature, swing, dynamics, pan, gain, voicePool, tuning, rit/accel
- Chords and Harmony — Chord literals, roman numerals, scales
- Chord Progressions — Voice-led
progression | I IV V I | - Song Structure — Sections (including parameterized), songs, arrangements
Expression and Transforms
- Pattern Transforms — Transpose, invert, retrograde, humanize, trill, tremolo, vary, polyrhythm, tempoRamp
- Dynamics and Expression — Dynamics, articulation, ornaments
- Generative Music — Euclidean rhythms, Markov, L-systems, cellular automata, chaos maps, Tidal combinators,
jam
Audio
- Audio and Synthesis — Buffers, oscillators, envelopes, synthesizers, custom wavetables, SFZ sampler
- Effects — Reverb, filters, compressor, sidechain, delay, gain, panning, granular, stretch, pitch-shift
- Voices and Tracks — Multi-track timeline rendering, voice-pool polyphony
- Vocalization — Formant-synthesized singing and TTS
- Visualization — ASCII piano-roll and waveform
- Playback and Export —
play,stream, WAV / MIDI / MusicXML / LilyPond export, loading WAVs, ABC / MML import - Live Coding —
live { }blocks,flow watchstatus panel, hot-swap, determinism trade-off - OSC and MIDI —
@osc(send/listen/pump),@midi(hardware output, clock),@jack(transport sync)
Reference
- Standard Library — Modules and complete function reference
- Imports and Modules — The
usestatement, the 15 stdlib modules, runtime gates - Tips and Tricks — Idioms, shorthands, and common pitfalls
- Examples — Complete working programs
Quick Example
use "@std"
use "@audio"
tempo 120 {
timesig 4/4 {
key Cmajor {
section intro {
Sequence melody = | C4q E4q G4q C5q | -> crescendo 0.2 0.7
}
section hook {
Sequence chords = progression | I IV V I |
}
Song mySong = [intro hook*2]
Buffer rendered = (renderSong mySong "piano")
Buffer final = rendered -> reverb 0.3 -> fadeOut 0.5
(exportWav final "my_song.wav")
(writeMidi "my_song.mid" mySong)
(print $"rendered {(getFrames final)} frames")
}
}
}Open in playgroundSee Also
- README — Install, build, showcase
- FEATURES.md — Complete feature inventory with status (Fully / Partial / Not yet)
- examples/ — Tutorial chapters covering DSP, generative, improv, notation, tuning, sections, symphony, ragtime