Packages
Parser for Uzu pattern mini-notation, used in live coding and algorithmic music. Converts text-based patterns into timed musical events.
Current section
Files
Jump to
Current section
Files
uzu_parser
README.md
README.md
# UzuParserParser for Uzu pattern mini-notation, used in live coding and algorithmic music generation.## OverviewUzuParser converts text-based pattern notation into structured, timed musical events. It's designed for live coding environments and algorithmic music systems, providing a simple yet expressive syntax for creating rhythmic and melodic patterns.## InstallationAdd `uzu_parser` to your dependencies in `mix.exs`:```elixirdef deps do [ {:uzu_parser, "~> 0.1.0"} # Or for local development: # {:uzu_parser, path: "../uzu_parser"} ]end```## Quick Start```elixir# Parse a simple patternUzuParser.parse("bd sd hh sd")# => [# %UzuParser.Event{sound: "bd", time: 0.0, duration: 0.25},# %UzuParser.Event{sound: "sd", time: 0.25, duration: 0.25},# %UzuParser.Event{sound: "hh", time: 0.5, duration: 0.25},# %UzuParser.Event{sound: "sd", time: 0.75, duration: 0.25}# ]```## Syntax### Basic SequencesSpace-separated sounds are evenly distributed across one cycle (0.0 to 1.0):```elixirUzuParser.parse("bd sd hh sd") # 4 events at times 0.0, 0.25, 0.5, 0.75```### RestsUse `~` for silence:```elixirUzuParser.parse("bd ~ sd ~") # kick and snare on alternating beats```### SubdivisionsBrackets create faster divisions within a step:```elixirUzuParser.parse("bd [sd sd] hh") # snare plays twice as fastUzuParser.parse("bd [sd hh cp]") # three sounds in the time of one step```### RepetitionAsterisk multiplies elements:```elixirUzuParser.parse("bd*4") # equivalent to "bd bd bd bd"UzuParser.parse("bd*2 sd") # two kicks, one snare```### Sample SelectionColon selects different samples/variations:```elixirUzuParser.parse("bd:0") # kick drum, sample 0UzuParser.parse("bd:1 bd:2") # different kick drum samplesUzuParser.parse("bd:0*4") # repeat sample 0 four timesUzuParser.parse("bd:0 sd:1 hh:2") # each sound uses a different sample```### Polyphony (Chords)Comma within brackets plays multiple sounds simultaneously:```elixirUzuParser.parse("[bd,sd]") # kick and snare togetherUzuParser.parse("[bd,sd,hh]") # three sounds at onceUzuParser.parse("bd [sd,hh] cp") # chord on second beatUzuParser.parse("[bd:0,sd:1]") # chord with sample selection```### Random Removal (Probability)Question mark adds probability - events may or may not play:```elixirUzuParser.parse("bd?") # 50% chance to playUzuParser.parse("bd?0.25") # 25% chance to playUzuParser.parse("bd sd? hh") # only sd is probabilisticUzuParser.parse("bd:0?0.75") # sample selection + probability```The parser stores probability in the event's `params` field. The playback system decides whether to play each event based on this value.### Elongation (Temporal Weight)At sign specifies relative duration/weight of events:```elixirUzuParser.parse("bd@2 sd") # kick twice as long as snare (2/3 vs 1/3)UzuParser.parse("[bd sd@3 hh]") # snare 3x longer than bd and hhUzuParser.parse("bd@1.5 sd") # fractional weights supported```Events are assigned time and duration proportionally based on their weights. Default weight is 1.0 if not specified.### ReplicationExclamation mark repeats events (similar to `*` but clearer intent):```elixirUzuParser.parse("bd!3") # three bd eventsUzuParser.parse("bd!2 sd") # two kicks, one snareUzuParser.parse("[bd!2 sd]") # replication in subdivision```Note: In this parser, `!` and `*` produce identical results. Both create separate steps rather than subdividing time.### Random ChoicePipe randomly selects one option per evaluation:```elixirUzuParser.parse("bd|sd|hh") # pick one each timeUzuParser.parse("[bd|cp] sd") # randomize first beatUzuParser.parse("bd:0|sd:1") # with sample selection```The parser stores all options in the event's `params` field. The playback system decides which option to play using random selection.### AlternationAngle brackets cycle through options sequentially:```elixirUzuParser.parse("<bd sd hh>") # bd on cycle 1, sd on 2, hh on 3, repeatsUzuParser.parse("<bd sd> hh") # alternate kick patternUzuParser.parse("<bd:0 sd:1>") # with sample selection```The parser stores all options in the event's `params` field. The playback system uses the cycle number to select which option to play.### Complex PatternsCombine features for expressive patterns:```elixir# Realistic drum patternUzuParser.parse("bd sd [hh hh] sd")# Layered pattern with repetition and subdivisionsUzuParser.parse("bd*4 ~ [sd sd] ~")# Nested subdivisions and restsUzuParser.parse("[bd ~ sd ~] hh")```## Event StructureEach parsed event contains:- `sound` - The sound/sample name (string)- `sample` - Sample number (integer >= 0, or nil for default)- `time` - Position in the cycle (0.0 to 1.0)- `duration` - How long the event lasts (0.0 to 1.0)- `params` - Additional parameters (map, for future extensions)```elixir%UzuParser.Event{ sound: "bd", sample: 0, time: 0.0, duration: 0.25, params: %{}}```## Future Features- Parameters: `"bd|gain:0.8|speed:2"`- Euclidean rhythms: `"bd(3,8)"` (3 hits in 8 steps)## Pattern TransformationsFor pattern transformations like `fast`, `slow`, `rev`, `stack`, `cat`, `every`, and `jux`, see [UzuPattern](https://github.com/rpmessner/uzu_pattern) - the pattern orchestration library that builds on UzuParser.## Ecosystem RoleUzuParser is part of the Elixir music ecosystem:```┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ UzuParser │────▶│ UzuPattern │────▶│ Waveform ││ (parsing) │ │ (transforms) │ │ (audio) ││ │ │ │ │ ││ • parse/1 │ │ • Pattern struct│ │ • OSC ││ • mini-notation │ │ • fast/slow/rev │ │ • SuperDirt ││ • [%Event{}] │ │ • stack/cat │ │ • MIDI ││ │ │ • every/when │ │ • scheduling ││ │ │ • query/2 │ │ │└─────────────────┘ └─────────────────┘ └─────────────────┘```- **UzuParser**: Parses mini-notation strings into event lists- **UzuPattern**: Applies transformations to patterns (fast, slow, rev, stack, cat, every, jux)- **Waveform**: Handles audio output via OSC/SuperDirt/MIDI## Development```bash# Run testsmix test# Generate documentationmix docs# Format codemix format```## LicenseMIT License - See LICENSE for details## CreditsInspired by the pattern mini-notation from [TidalCycles](https://tidalcycles.org/) and [Strudel](https://strudel.cc/).