2 unstable releases
Uses new Rust 2024
| 0.1.0 | Feb 2, 2026 |
|---|---|
| 0.0.1 | Jan 31, 2026 |
#914 in Parser implementations
3MB
75K
SLoC
𝄐 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:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
"Music is the space between the notes." — Claude Debussy
Dependencies
~3MB
~49K SLoC
