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.
;; A simple C major scale
(score
:title "C Major Scale"
:composer "Anonymous"
(part :id "P1" :name "Piano"
(measure
:time (4 4)
:clef :treble
:key 0
(note C4 :q)
(note D4 :q)
(note E4 :q)
(note F4 :q))
(measure
(note G4 :q)
(note A4 :q)
(note B4 :q)
(note C5 :q))))| Feature | Description |
|---|---|
| Compile | Fermata source β MusicXML |
| Import | MusicXML β Fermata source |
| Check | Validate Fermata source files |
| Show | Built-in reference for durations, pitches, clefs, dynamics, etc. |
| MusicXML Parser | Full MusicXML 4.0 parsing |
| MusicXML Emitter | Full MusicXML 4.0 generation |
| Feature | Description |
|---|---|
| LilyPond | Compile to LilyPond for publication-quality PDF engraving |
| REPL | Interactive prompt for experimentation |
| Macros | Define reusable patterns like (cadence :authentic :key c-major) |
| Transformations | (transpose +2 ...), (invert ...), (retrograde ...) |
| Theory-aware | Built-in knowledge of scales, chords, intervals, voice leading |
| SVG | Direct rendering via verovioxide |
cargo install fermataOr add to your Cargo.toml:
[dependencies]
fermata = "0.1"# Compile Fermata source to MusicXML
fermata compile score.fm -o score.musicxml
# Import MusicXML to Fermata source
fermata import score.musicxml -o score.fm
# Validate a Fermata file
fermata check score.fm
# Show reference information
fermata show durations
fermata show pitches
fermata show dynamics
fermata show --help # list all topics
# Machine-readable output
fermata show durations --format json# Read from stdin, write to stdout
cat score.fm | fermata compile > score.musicxml
# Convert MusicXML from stdin
cat score.musicxml | fermata import > score.fmuse fermata::{parse, compile, CompileOptions, Target};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Parse Fermata source to AST
let source = r#"
(score :title "My Song"
(part :piano
(measure
(note c4 :q)
(note d4 :q)
(note e4 :q)
(note f4 :q))))
"#;
let score = parse(source)?;
// Compile to MusicXML (default)
let xml = compile(&score, CompileOptions::default())?;
std::fs::write("output.musicxml", &xml)?;
// Or compile to S-expression format
let sexpr = compile(&score, CompileOptions::sexpr())?;
println!("{}", sexpr);
Ok(())
}For lower-level control, use the modules directly:
fermata::lang- Language parsing and compilationfermata::musicxml- MusicXML parsing and emissionfermata::sexpr- S-expression parsing and printingfermata::ir- MusicXML-faithful intermediate representation
Use fermata show to explore the language:
fermata show syntax # Quick syntax overview
fermata show durations # :w :h :q :8 :16 :32 :64
fermata show pitches # C4, D#5, Bb3, etc.
fermata show dynamics # pp, p, mp, mf, f, ff, etc.
fermata show articulations # staccato, accent, tenuto, etc.
fermata show clefs # treble, bass, alto, tenor, etc.
fermata show keys # Key signatures and modes;; Notes with pitch and duration
(note c4 :q) ; C4 quarter note
(note d#5 :h) ; D#5 half note
(note bb3 :8) ; Bb3 eighth note
;; Rests
(rest :q) ; quarter rest
(rest :w) ; whole rest
;; Chords (pitches in nested list, then duration)
(chord (c4 e4 g4) :q) ; C major triad, quarter
;; Durations
:w ; whole
:h ; half
:q ; quarter
:8 ; eighth
:16 ; sixteenth
:32 ; thirty-second
;; Score structure
(score
:title "Title"
:composer "Composer"
(part :piano ; or :name "Piano"
(measure
(time 4 4) ; time signature
(clef :treble) ; clef
(key c :major) ; key signature
(note c4 :q)
(note d4 :q)
(note e4 :h))))
;; Dynamics
(p) (pp) (ppp) ; piano variants
(f) (ff) (fff) ; forte variants
(mp) (mf) ; mezzo variants
(sfz) (fp) ; accents
;; Articulations (on notes)
(note c4 :q :staccato)
(note c4 :q :accent)
(note c4 :q :tenuto)
;; Barlines
(barline :final) ; end barline
(barline :double) ; double barline
(barline :repeat-forward) ; repeat start
(barline :repeat-backward); repeat end
;; Theory macros (planned)
(scale c :major) ; => (c4 d4 e4 f4 g4 a4 b4 c5)
(chord-voicing c :dom7) ; => (c4 e4 g4 bb4)- verovioxide β Rust bindings for Verovio music engraving
- Verovio β Fast, lightweight music notation engraving library
- LilyPond β Music engraving program for publication-quality scores
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