Skip to content

Parser for Uzu pattern mini-notation, used in live coding and algorithmic music generation.

License

Notifications You must be signed in to change notification settings

rpmessner/uzu_parser

Repository files navigation

UzuParser

Parser for Strudel/Tidal-style mini-notation, used in live coding and algorithmic music generation.

Overview

UzuParser converts text-based pattern notation into an Abstract Syntax Tree (AST). It's designed for live coding environments and algorithmic music systems, providing a simple yet expressive syntax for creating rhythmic and melodic patterns.

Note: UzuParser handles parsing only. For event generation and pattern transformations, see UzuPattern.

Installation

Add uzu_parser to your dependencies in mix.exs:

def deps do
  [
    {:uzu_parser, "~> 0.6.0"}
  ]
end

Quick Start

# Parse a pattern - returns AST
{:ok, ast} = UzuParser.parse("bd sd hh")
# => {:ok, {:sequence, [
#      %{type: :atom, value: "bd", source_start: 0, source_end: 2},
#      %{type: :atom, value: "sd", source_start: 3, source_end: 5},
#      %{type: :atom, value: "hh", source_start: 6, source_end: 8}
#    ]}}

# For timed events, use UzuPattern:
pattern = UzuPattern.parse("bd sd hh")
haps = UzuPattern.query(pattern, 0)
# => [%Hap{value: %{sound: "bd"}, part: %{begin: Ratio.new(0,1), ...}}, ...]

Syntax

Basic Sequences

Space-separated sounds create a sequence:

UzuParser.parse("bd sd hh sd")  # 4 elements in sequence

Rests

Use ~ for silence:

UzuParser.parse("bd ~ sd ~")  # kick and snare on alternating beats

Subdivisions

Brackets create subdivisions within a step:

UzuParser.parse("bd [sd sd] hh")  # snare plays twice as fast
UzuParser.parse("bd [sd hh cp]")  # three sounds in the time of one step

Repetition

Asterisk multiplies elements:

UzuParser.parse("bd*4")      # equivalent to "bd bd bd bd"
UzuParser.parse("[bd sd]*2") # repeat the subdivision

Replication

Exclamation mark replicates with weight:

UzuParser.parse("bd!4")      # four bds, each with weight 1
UzuParser.parse("[bd!3 sd]") # three bds then one sd in subdivision

Division (Slow)

Slash spreads pattern across cycles:

UzuParser.parse("[bd sd]/2")  # pattern takes 2 cycles to complete

Sample Selection

Colon selects sample variants:

UzuParser.parse("bd:0 bd:1 bd:2")  # different kick drum samples

Polyphony (Chords)

Comma within brackets plays sounds simultaneously:

UzuParser.parse("[bd,sd]")        # kick and snare together
UzuParser.parse("[c3,e3,g3]")     # C major chord

Probability

Question mark adds probability:

UzuParser.parse("bd?")       # 50% chance to play
UzuParser.parse("bd?0.25")   # 25% chance to play

Weight

At sign specifies relative duration:

UzuParser.parse("bd@2 sd")   # kick twice as long as snare
UzuParser.parse("bd@3 sd@1") # kick takes 3/4, snare takes 1/4

Elongation

Underscore extends the previous sound:

UzuParser.parse("bd _ sd")   # kick held for 2/3, snare for 1/3
UzuParser.parse("bd _ _ sd") # kick held for 3/4, snare for 1/4

Alternation

Angle brackets cycle through options:

UzuParser.parse("<bd sd hh>")  # bd on cycle 0, sd on cycle 1, hh on cycle 2

Random Choice

Pipe randomly selects one option:

UzuParser.parse("bd|sd|hh")  # pick one randomly per cycle

Polymetric

Curly braces create independent timing:

UzuParser.parse("{bd sd, hh hh hh}")  # 2-against-3 polyrhythm
UzuParser.parse("{bd sd hh}%8")       # fit pattern into 8 steps

Euclidean Rhythms

Parentheses create Euclidean patterns:

UzuParser.parse("bd(3,8)")      # 3 hits distributed over 8 steps
UzuParser.parse("bd(3,8,1)")    # with rotation offset

Parameters

Pipe with key:value sets sound parameters:

UzuParser.parse("bd|gain:0.8|speed:2")
UzuParser.parse("bd|lpf:2000|room:0.5")

Period Separator

Period works like space but creates visual grouping:

UzuParser.parse("bd sd . hh cp")  # same as "bd sd hh cp"

AST Structure

The parser returns an AST with node types:

  • :sequence - Sequential elements
  • :stack - Polyphonic (simultaneous) elements
  • :subdivision - Bracketed group with optional modifiers
  • :alternation - Angle bracket alternation
  • :polymetric - Curly brace polymetric group
  • :atom - Sound/note with optional modifiers
  • :rest - Silence (~)
  • :elongation - Underscore continuation (_)

Each atom node includes:

  • value - Sound name
  • sample - Sample number (from :n)
  • repeat - Repetition count (from *n)
  • replicate - Replication count (from !n)
  • euclidean - {k, n, offset} tuple (from (k,n) or (k,n,o))
  • probability - Float 0-1 (from ? or ?n)
  • weight - Float (from @n)
  • params - Map of parameters (from |key:value)
  • source_start, source_end - Position in source string

Source Position Tracking

All AST nodes include source positions for editor integration:

{:ok, {:sequence, nodes}} = UzuParser.parse("bd sd")
[bd, sd] = nodes

bd.source_start  # => 0
bd.source_end    # => 2
sd.source_start  # => 3
sd.source_end    # => 5

This enables features like syntax highlighting, error reporting, and click-to-edit in live coding environments.

Ecosystem

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   UzuParser     │────▶│   UzuPattern    │────▶│    Waveform     │
│   (parsing)     │     │ (interpretation │     │    (audio)      │
│                 │     │  & transforms)  │     │                 │
│ • parse/1       │     │ • Interpreter   │     │ • OSC           │
│ • mini-notation │     │ • Pattern struct│     │ • SuperDirt     │
│ • AST output    │     │ • fast/slow/rev │     │ • Web Audio     │
│                 │     │ • query/2       │     │ • scheduling    │
└─────────────────┘     └─────────────────┘     └─────────────────┘
  • UzuParser: Parses mini-notation strings into AST
  • UzuPattern: Interprets AST into patterns, applies transformations, queries events
  • Waveform: Handles audio output via OSC/SuperDirt/Web Audio

Error Handling

# Successful parse
{:ok, ast} = UzuParser.parse("bd sd")

# Parse error
{:error, message} = UzuParser.parse("[bd sd")
# => {:error, "missing terminator: ]"}

Development

# Run tests
mix test

# Generate documentation
mix docs

# Format code
mix format

License

MIT License - See LICENSE for details

Credits

Inspired by the pattern mini-notation from TidalCycles and Strudel.

About

Parser for Uzu pattern mini-notation, used in live coding and algorithmic music generation.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages