A suite of tools to convert MusicXML scores to MIDI using Musical MIDI Accompaniment (MMA).
- Install
xmllint
(included in libxml2 on most platforms) git submodule update --init --recursive
npm install && npm run build
npm run --silent convert:unroll song.musicxml > song-unrolled.musicxml
to unroll a MusicXML score by expanding all jumps and repeatsnpm run --silent convert:mma song.musicxml > song.mma
to both unroll a score and convert it to an MMA scriptnpm run --silent convert:groove groove-name [chords="A,B,C"] [tempo=X] [count=Y] [keysig=Z] > groove.mma
to generate a groove MMA scriptnpm run convert:midi /path/to/song.mma
to convert an MMA script to MIDI file at/path/to/song.mid
npm run --silent convert:timemap song.musicxml > song.timemap.json
to convert a score to a timemap JSON file
PORT=3000 npm run develop
for development (including hot-reload)PORT=3000 npm run start
for productioncurl -sSf -F"musicXml=@test/data/salma-ya-salama.musicxml" -F"globalGroove=Maqsum" http://localhost:3000/convert -o "salma-ya-salama.mid"
curl -sSf -F"groove=Maqsum" -F"chords=I, vi, ii, V7" -F"count=8" http://localhost:3000/groove -o "maqsum.mid"
curl -sSf -F"jq=.[] |= {groove,description,timeSignature}" http://localhost:3000/grooves.json
- Convert a MIDI file to a timemap JSON file:
./src/js/midi-timemap.js song.mid > song.timemap.json
- Scrape MusicXML examples from the official site:
./src/js/musicxml-examples.js --output=./test/data/examples
- Convert MMA grooves to MusicXML:
./src/js/musicxml-grooves.js --output=./test/data/grooves
- Convert MIDI to JSON and back:
./src/js/midi-json.js < source.mid | jq [..] | ./src/js/midi-json.js > target.mid
This converter aims to create a valid MMA accompaniment script out of a MusicXML score. The MMA script is then converted to MIDI using the bundled mma
tool. To accomplish this, the converter expects to find the following information in the sheet:
-
Chord information, expressed as
harmony
elements. MMA recognizes a large number of chords, but MusicXML's harmony representation is more general and can lead to invalid chord names. Refer to chords.musicxml for a reference on how to express all MMA-supported chords. -
Melody information, expressed as
note
elements. This is converted to an MMASOLO
sequence for each measure. -
Optional playback style information, expressed as
sound/play/other-play
elements with attribute@type = 'groove'
. The content of this element represents the "groove" that is passed to MMA to generate an accompaniment. In case no such playback style information is found, or the specified style is not mapped to an existing MMA groove, the chords are played back as per the lead sheet without further accompaniment. Note that several styles can be specified in a single sheet, since thesound
element is associated withmeasure
ormeasure/direction
elements. The groove can be overridden with the argumentglobalGroove
.
The produced MMA script / MIDI file contains metadata that can be useful to downstream consumers. This metadata is generally expressed as MIDI Marker meta messages, with the following syntax:
Measure:N:T
informs the consumer that the MIDI playback has reached measure N (0-based) with duration T milliseconds.Groove:X
informs the consumer that the MIDI playback is henceforth using the specified playback style.
The tools contained here can also convert the score (or the generated MIDI file) to a so-called Timemap JSON file, which lists timing information for each measure:
[
{
// 0-based measure index (integer)
measure: number,
// 0-based offset in milliseconds (real)
timestamp: number,
// duration in milliseconds (real)
duration: number
},
// ...
]