Adds tools/musicxml-to-notes.ts: one part of a MusicXML score (.mxl or .musicxml) becomes the {bpm, lyrics, notes} file that chimera render notes sings. With it, a multi-voice show for the duet page (?show=<id>) can be built from a published arrangement, not from hand-typed JSON.
bun tools/musicxml-to-notes.ts score.mxl # list the parts
bun tools/musicxml-to-notes.ts score.mxl P1 --out p1.json [--bpm N] [--spell ba=bah,...]No new dependencies: .mxl is unzipped with the system unzip; it needs the wasm build (bun run wasm) for the dictionary.
Traps it handles
- Scores split words their own way (
to-ge-ther), and the dictionary can't say a lonege. Each word is joined again and syllabified by the engine's own dictionary, asrender noteswill. - More syllables than notes (
bais "B.A." in CMUdict) or none (a hum writtendm) stop the tool with the words and measures listed;--spell word=respellingfixes them. Fewer syllables than notes hold the last vowel, with a warning. - Curly apostrophes are normalized before the count.
- Repeats and 1st/2nd endings are written out; each pass through a repeat sings its own lyric line (verse 2 the second time).
- Tied notes become one note; a note with no lyric holds the previous vowel (
-). - D.C. / D.S. / To Coda / Fine, and two voices on one staff, stop the tool with an error, not a wrong melody.
Not handled
- Tempo changes:
render notestakes one bpm; the tool warns and uses the first (or--bpm). - Chords: the first note is sung.
- The XML is read with regular expressions; tested on MuseScore output only.
Ran
-
A 5-part a cappella MuseScore arrangement (71 measures, 198–314 notes per part): converted, rendered with
render notes --tele, and replayed on the duet page with 5 heads in sync. -
A hand-written score with a repeat, two endings and two verses: expands to the right order and lyrics.
-
A second (7-part) MuseScore arrangement: errors and warnings as designed.
-
bun run typecheckandbun run testpass. -
tests/musicxml-to-notes.test.ts(4 tests): play order with repeats, endings and verses; joined words and ties; too-long words refused once whatever their case; D.S. refused.
Activity
4I don't really know how to handle this PR wise, especially because it's vibe coded, but I asked Claude to improve your script a bit and: https://github.com/ProbablePrime/chimera-vocal-synth/tree/feat/musicxml-ify.ts
became the result.
My changes there convert a whole score into json and can output it directly in the shows folder too. It makes my workflow really easy, Here's how I do it:
- I downloaded: https://musescore.com/user/286001/scores/2962801 as MusicXML
- I ran:
bun tools/musicxml-ify.ts all-i-want-for-christmas-is-you-mariah-carey-ttbb-a-cappella-choir.mxl --output public/shows/christmas - I loaded: http://127.0.0.1:5317/?show=christmas
- I got: https://www.youtube.com/watch?v=QKg3-m-5C2A
- This immediately got copyright claimed, but I kind of see that as a win, Chimera is re-creating a song well enough for that to happen 🤣
@yungalgo is attempting to deploy a commit to the Jameson Hodge's projects Team on Vercel.
A member of the Team first needs to authorize it.