fermata 0.1.0

An S-expression DSL for working with MusicXML
Documentation

𝄐 Fermata

An S-expression DSL for working with MusicXML

In music, a fermata (𝄐) indicates that a note should be held longer than its written value — a pause, a moment of expressiveness left to the performer's discretion.

Fermata is a Lisp-like domain-specific language for describing musical notation. It compiles to MusicXML, LilyPond, and Rust, enabling precise musical communication between humans and machines.

Status: 🚧 Under Construction

This crate is in early development. The API will change significantly.

Vision

;; Describe music naturally
(score
 (title "Prelude in C")
 (composer "J.S. Bach")
 (tempo 66 :quarter)

 (part :piano
       (staff :treble
              (measure
               (voice
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5))
                (chord :8 (c5 e5 g5)))))
       (staff :bass
              (measure
               (voice
                (note c3 :h)
                (note c4 :h))))))

Output Targets

Target Use Case
MusicXML Import into Finale, Sibelius, MuseScore, Dorico
LilyPond Publication-quality PDF engraving
Rust Embed notation generation in Rust applications
SVG Direct rendering via verovioxide

Planned Features

  • REPL — Interactive fermata> prompt for experimentation
  • Macros — Define reusable patterns like (cadence :authentic :key c-major)
  • Transformations(transpose +2 ...), (invert ...), (retrograde ...)
  • Bidirectional — Parse MusicXML back into Fermata expressions
  • Theory-aware — Built-in knowledge of scales, chords, intervals, voice leading

Installation

cargo install fermata

Or add to your Cargo.toml:

[dependencies]
fermata = "0.0.1"

Usage

As a CLI

# Start the REPL
fermata

# Compile to MusicXML
fermata compile score.fm -o score.musicxml

# Compile to LilyPond
fermata compile score.fm -o score.ly --target lilypond

# Render directly to SVG (requires verovioxide)
fermata render score.fm -o score.svg

As a Library

use fermata::{parse, compile_to_musicxml};

fn main() -> fermata::Result<()> {
let source = r#"
(score
 (part :piano
       (measure
        (note c4 :q)
        (note d4 :q)
        (note e4 :q)
        (note f4 :q))))
"#;

let ast = parse(source)?;
let musicxml = compile_to_musicxml(&ast)?;

std::fs::write("output.musicxml", musicxml)?;
Ok(())
}

Language Reference

Coming soon — see LANGUAGE.md for the developing specification.

Quick Reference

;; Notes
(note c4 :q) ; C4 quarter note
(note d#5 :h :dot) ; D#5 dotted half
(note bb3 :8 :staccato) ; Bb3 eighth, staccato

;; Rests
(rest :q) ; quarter rest
(rest :w) ; whole rest

;; Chords
(chord :q (c4 e4 g4)) ; C major triad, quarter

;; Durations
:w ; whole
:h ; half
:q ; quarter
:8 ; eighth
:16 ; sixteenth
:32 ; thirty-second

;; Articulations & Ornaments
:staccato :accent :tenuto :fermata
:trill :mordent :turn

;; Dynamics
:pp :p :mp :mf :f :ff
(cresc :from pp :to f :over 4) ; 4 measures

;; Structure
(score ...)
(part <instrument> ...)
(staff <clef> ...)
(measure ...)
(voice ...)

;; Clefs
:treble :bass :alto :tenor :percussion

;; Key signatures
(key c :major)
(key a :minor)
(key f# :major)

;; Time signatures
(time 4 4)
(time 6 8)
(time 2 2)

;; Theory macros (planned)
(scale c :major) ; => (c4 d4 e4 f4 g4 a4 b4 c5)
(chord-voicing c :dom7) ; => (c4 e4 g4 bb4)
(cadence :authentic :key c) ; => V-I progression
(progression c :major I IV V I)

Related Projects

  • verovioxide — Rust bindings for Verovio music engraving
  • Verovio — Fast, lightweight music notation engraving library
  • LilyPond — Music engraving program for publication-quality scores

License

Licensed under either of:

at your option.


"Music is the space between the notes." — Claude Debussy