The Ultimate Score Konverter. A bidirectional music notation format converter in Rust.
Tusk converts between MusicXML, MEI, and LilyPond. Its internal model is based on MEI (Music Encoding Initiative) and extended where needed to cover concepts from other formats. Every conversion passes through this shared model, preserving as much musical information as possible across formats.
| From \ To | MusicXML | MEI | LilyPond | Extensions |
|---|---|---|---|---|
| MusicXML | ✅ | ✅ | ✅ | .musicxml, .mxl |
| MEI | ✅ | ✅ | ✅ | .mei |
| LilyPond | ✅ | ✅ | ✅ | .ly |
Output versions: MusicXML 4.1, MEI 6.0-dev, LilyPond 2.24. Older input versions are accepted but mileage may vary.
tusk convert <INPUT> <OUTPUT>
Formats are detected from file extensions, with content-based fallback for the input. Use --from / --to to override detection, and - for stdin/stdout.
$ tusk convert score.musicxml score.mei
score.musicxml (MusicXML) → score.mei (MEI)
$ tusk convert score.mei score.ly
score.mei (MEI) → score.ly (LilyPond)
$ tusk convert concert.mxl concert.mei
concert.mxl (MusicXML (.mxl)) → concert.mei (MEI)
# Pipe through stdin/stdout
$ cat score.mei | tusk convert - -t musicxml > score.musicxml
# List supported formats
$ tusk formatsuse tusk_musicxml::MusicXmlFormat;
use tusk_mei::MeiFormat;
use tusk_format::{Importer, Exporter};
let (base, ext) = MusicXmlFormat.import_from_str(&musicxml_string)?;
let mei_xml = MeiFormat.export_to_string(&base, &ext)?;Requires Rust (edition 2024). No other external dependencies.
git clone https://github.com/sonovice/tusk.git
cd tusk
cargo build --releaseBinary ends up at target/release/tusk.
cargo testAdditional regression tests against upstream MEI and LilyPond test suites are available via git submodules. These are not needed for the standard test suite.
git submodule update --init # all submodules
git submodule update --init tests/fixtures/mei/sample-encodings # MEI only
git submodule update --init tests/fixtures/lilypond/lilypond-repo # LilyPond only
cargo test -- --ignored # run regression testscrates/
├── core/
│ ├── model/ MEI data model, generated from RNG schema
│ └── format/ Format traits (Importer, Exporter, FormatRegistry)
├── formats/
│ ├── mei/ MEI parser, serializer, version migration
│ │ └── codegen/ RNG to Rust code generator
│ ├── musicxml/ MusicXML parser, serializer, MEI conversion
│ │ └── codegen/ XSD to Rust code generator
│ └── lilypond/ LilyPond lexer, parser, serializer, MEI conversion
└── bindings/
└── cli/ Command-line interface
The MEI model is generated from the official RNG schema at build time. No manual codegen step required.