treble-lang 0.7.0

A live coding language for treble
Documentation

treble-lang

The Treble language: parser, session engine, and — behind the render feature — the lowering that turns a buffer into something the engine can play.

LANGUAGE.md is the specification and the authority. This file is just how to run the thing.

The library

treble-lang = { git = "https://github.com/MinIndustry/treble-lang.git", tag = "0.4.0" }

Parsing has no dependencies beyond nom. The engine is not pulled in: a tool that only wants to read a buffer should not pay for a DSP stack.

let mut session = treble_lang::Session::new();
let result = session.evaluate(source);
if let Some(piece) = session.piece() {
    println!("{} cycles", piece.total_cycles());
}

Rendering

The render feature adds treble_lang::render, which depends on treble-core:

treble-lang = { …, features = ["render"] }
  • render::compile — mini-notation to events, def blocks to instrument specs, fx names resolved against the engine's registry. Shared with the live front end, so a rendered piece and a played performance compile through the same code.
  • render::offline — drives that output through the engine to samples.
  • render::wav — writes the result, metadata and all.

The command line

cargo install --path . --features render

treble check  piece.rt      # parse, report errors, exit 1 on any
treble info   piece.rt      # sections, arrangement, spans, metadata
treble render piece.rt      # → piece.wav

render takes -o/--out, -r/--rate, -f/--force, -q/--quiet, --json, and -m/--meta key=value (repeatable, overrides the file's own tags — handy for stamping a build date or take number without editing the piece).

load "<file.trbl>" lines resolve beside the piece file (an absolute path is used as written; nothing else is searched), so an album of pieces can share one instrument library. check validates the loads too — a broken path or a loaded file that sounds is reported before any render.

Progress is reported on stderr and the summary on stdout, so --json composes:

treble render piece.rt --json | jq .renderedSeconds

Metadata

meta tags (LANGUAGE.md §8.9) travel into the WAV's INFO chunk, so a rendered piece carries its own title rather than relying on the filename:

meta title    "Nocturne for a Slow Machine"
meta composer "F. Grimau"
meta comment  "One collection, three centres."

The key set is open. Well-known keys map to their standard tags; anything else is filed alongside the comment rather than dropped.

The language server

cargo install --path . --features serve
treble serve

serve speaks LSP on stdin and stdout for an editor: diagnostics (the same checks as check, plus unknown instruments), completion, hover and go-to-definition on instrument names, and document symbols. On top of LSP it answers treble/outline and treble/timeline — the notes of chosen lines as the renderer schedules them, each pointing back at the step that wrote it — and plays through the default sound card with treble/play and treble/stop. Playback renders the asked-for lines of one section, placed where the piece first plays it, so a line heard alone sounds as it does in the render; an edit to a playing piece is re-rendered and swapped in at the next cycle. The protocol is written down in Quill's PROTOCOL.md, the editor it was built for.

An example piece

pieces/nocturne.rt is a complete five-and-a-half-minute piece — ten sections, seven instruments defined in the buffer, a theme in three metres, and a question-and-answer solo. It is the toolchain's end-to-end case:

treble check  pieces/nocturne.rt
treble info   pieces/nocturne.rt
treble render pieces/nocturne.rt

Renders are reproducible, so the WAV is not kept in the repository — the source beside it is the artefact.

The analysis examples read its notes rather than its audio:

cargo run --features render --example notes   -- pieces/nocturne.rt
cargo run --features render --example clashes -- pieces/nocturne.rt