@mcptoolshop/ai-jam-sessions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.es.md +177 -0
- package/README.fr.md +178 -0
- package/README.hi.md +175 -0
- package/README.it.md +177 -0
- package/README.ja.md +174 -0
- package/README.md +174 -0
- package/README.pt-BR.md +177 -0
- package/README.zh.md +173 -0
- package/dist/audio-engine.d.ts +12 -0
- package/dist/audio-engine.d.ts.map +1 -0
- package/dist/audio-engine.js +422 -0
- package/dist/audio-engine.js.map +1 -0
- package/dist/chord-detect.d.ts +14 -0
- package/dist/chord-detect.d.ts.map +1 -0
- package/dist/chord-detect.js +90 -0
- package/dist/chord-detect.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +805 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/journal.d.ts +41 -0
- package/dist/journal.d.ts.map +1 -0
- package/dist/journal.js +149 -0
- package/dist/journal.js.map +1 -0
- package/dist/mcp-server.d.ts +3 -0
- package/dist/mcp-server.d.ts.map +1 -0
- package/dist/mcp-server.js +1256 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/midi/parser.d.ts +16 -0
- package/dist/midi/parser.d.ts.map +1 -0
- package/dist/midi/parser.js +192 -0
- package/dist/midi/parser.js.map +1 -0
- package/dist/midi/types.d.ts +44 -0
- package/dist/midi/types.d.ts.map +1 -0
- package/dist/midi/types.js +8 -0
- package/dist/midi/types.js.map +1 -0
- package/dist/note-parser.d.ts +105 -0
- package/dist/note-parser.d.ts.map +1 -0
- package/dist/note-parser.js +319 -0
- package/dist/note-parser.js.map +1 -0
- package/dist/piano-roll.d.ts +28 -0
- package/dist/piano-roll.d.ts.map +1 -0
- package/dist/piano-roll.js +321 -0
- package/dist/piano-roll.js.map +1 -0
- package/dist/piano-voices.d.ts +90 -0
- package/dist/piano-voices.d.ts.map +1 -0
- package/dist/piano-voices.js +416 -0
- package/dist/piano-voices.js.map +1 -0
- package/dist/playback/controls.d.ts +124 -0
- package/dist/playback/controls.d.ts.map +1 -0
- package/dist/playback/controls.js +252 -0
- package/dist/playback/controls.js.map +1 -0
- package/dist/playback/midi-engine.d.ts +68 -0
- package/dist/playback/midi-engine.d.ts.map +1 -0
- package/dist/playback/midi-engine.js +227 -0
- package/dist/playback/midi-engine.js.map +1 -0
- package/dist/playback/position.d.ts +95 -0
- package/dist/playback/position.d.ts.map +1 -0
- package/dist/playback/position.js +223 -0
- package/dist/playback/position.js.map +1 -0
- package/dist/playback/timing.d.ts +31 -0
- package/dist/playback/timing.d.ts.map +1 -0
- package/dist/playback/timing.js +57 -0
- package/dist/playback/timing.js.map +1 -0
- package/dist/sample-engine.d.ts +17 -0
- package/dist/sample-engine.d.ts.map +1 -0
- package/dist/sample-engine.js +428 -0
- package/dist/sample-engine.js.map +1 -0
- package/dist/schemas.d.ts +40 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +42 -0
- package/dist/schemas.js.map +1 -0
- package/dist/session.d.ts +106 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +361 -0
- package/dist/session.js.map +1 -0
- package/dist/sfz-parser.d.ts +36 -0
- package/dist/sfz-parser.d.ts.map +1 -0
- package/dist/sfz-parser.js +95 -0
- package/dist/sfz-parser.js.map +1 -0
- package/dist/smoke.d.ts +2 -0
- package/dist/smoke.d.ts.map +1 -0
- package/dist/smoke.js +512 -0
- package/dist/smoke.js.map +1 -0
- package/dist/songs/config/loader.d.ts +14 -0
- package/dist/songs/config/loader.d.ts.map +1 -0
- package/dist/songs/config/loader.js +53 -0
- package/dist/songs/config/loader.js.map +1 -0
- package/dist/songs/config/schema.d.ts +79 -0
- package/dist/songs/config/schema.d.ts.map +1 -0
- package/dist/songs/config/schema.js +56 -0
- package/dist/songs/config/schema.js.map +1 -0
- package/dist/songs/index.d.ts +18 -0
- package/dist/songs/index.d.ts.map +1 -0
- package/dist/songs/index.js +22 -0
- package/dist/songs/index.js.map +1 -0
- package/dist/songs/jam.d.ts +48 -0
- package/dist/songs/jam.d.ts.map +1 -0
- package/dist/songs/jam.js +338 -0
- package/dist/songs/jam.js.map +1 -0
- package/dist/songs/library.d.ts +47 -0
- package/dist/songs/library.d.ts.map +1 -0
- package/dist/songs/library.js +156 -0
- package/dist/songs/library.js.map +1 -0
- package/dist/songs/loader.d.ts +27 -0
- package/dist/songs/loader.d.ts.map +1 -0
- package/dist/songs/loader.js +90 -0
- package/dist/songs/loader.js.map +1 -0
- package/dist/songs/midi/hands.d.ts +46 -0
- package/dist/songs/midi/hands.d.ts.map +1 -0
- package/dist/songs/midi/hands.js +134 -0
- package/dist/songs/midi/hands.js.map +1 -0
- package/dist/songs/midi/ingest.d.ts +8 -0
- package/dist/songs/midi/ingest.d.ts.map +1 -0
- package/dist/songs/midi/ingest.js +197 -0
- package/dist/songs/midi/ingest.js.map +1 -0
- package/dist/songs/midi/measures.d.ts +41 -0
- package/dist/songs/midi/measures.d.ts.map +1 -0
- package/dist/songs/midi/measures.js +64 -0
- package/dist/songs/midi/measures.js.map +1 -0
- package/dist/songs/midi/types.d.ts +25 -0
- package/dist/songs/midi/types.d.ts.map +1 -0
- package/dist/songs/midi/types.js +8 -0
- package/dist/songs/midi/types.js.map +1 -0
- package/dist/songs/registry.d.ts +37 -0
- package/dist/songs/registry.d.ts.map +1 -0
- package/dist/songs/registry.js +197 -0
- package/dist/songs/registry.js.map +1 -0
- package/dist/songs/types.d.ts +99 -0
- package/dist/songs/types.d.ts.map +1 -0
- package/dist/songs/types.js +29 -0
- package/dist/songs/types.js.map +1 -0
- package/dist/teaching/live-midi-feedback.d.ts +36 -0
- package/dist/teaching/live-midi-feedback.d.ts.map +1 -0
- package/dist/teaching/live-midi-feedback.js +259 -0
- package/dist/teaching/live-midi-feedback.js.map +1 -0
- package/dist/teaching/midi-feedback.d.ts +33 -0
- package/dist/teaching/midi-feedback.d.ts.map +1 -0
- package/dist/teaching/midi-feedback.js +208 -0
- package/dist/teaching/midi-feedback.js.map +1 -0
- package/dist/teaching/sing-on-midi.d.ts +77 -0
- package/dist/teaching/sing-on-midi.d.ts.map +1 -0
- package/dist/teaching/sing-on-midi.js +186 -0
- package/dist/teaching/sing-on-midi.js.map +1 -0
- package/dist/teaching.d.ts +148 -0
- package/dist/teaching.d.ts.map +1 -0
- package/dist/teaching.js +453 -0
- package/dist/teaching.js.map +1 -0
- package/dist/test-sound.d.ts +3 -0
- package/dist/test-sound.d.ts.map +1 -0
- package/dist/test-sound.js +41 -0
- package/dist/test-sound.js.map +1 -0
- package/dist/types.d.ts +229 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +28 -0
- package/dist/types.js.map +1 -0
- package/dist/vmpk.d.ts +23 -0
- package/dist/vmpk.d.ts.map +1 -0
- package/dist/vmpk.js +236 -0
- package/dist/vmpk.js.map +1 -0
- package/docs/fur-elise-m1-8.svg +290 -0
- package/logo.png +0 -0
- package/package.json +71 -0
- package/songs/library/blues/blues-in-the-night.json +14 -0
- package/songs/library/blues/blues-in-the-night.mid +0 -0
- package/songs/library/blues/born-under-a-bad-sign.json +13 -0
- package/songs/library/blues/born-under-a-bad-sign.mid +0 -0
- package/songs/library/blues/crossroad-blues.json +14 -0
- package/songs/library/blues/crossroad-blues.mid +0 -0
- package/songs/library/blues/everyday-i-have-the-blues.json +13 -0
- package/songs/library/blues/everyday-i-have-the-blues.mid +0 -0
- package/songs/library/blues/hoochie-coochie-man.json +14 -0
- package/songs/library/blues/hoochie-coochie-man.mid +0 -0
- package/songs/library/blues/red-house.json +14 -0
- package/songs/library/blues/red-house.mid +0 -0
- package/songs/library/blues/st-louis-blues.json +14 -0
- package/songs/library/blues/st-louis-blues.mid +0 -0
- package/songs/library/blues/stormy-monday.json +13 -0
- package/songs/library/blues/stormy-monday.mid +0 -0
- package/songs/library/blues/sweet-home-chicago.json +14 -0
- package/songs/library/blues/sweet-home-chicago.mid +0 -0
- package/songs/library/blues/the-thrill-is-gone.json +17 -0
- package/songs/library/blues/the-thrill-is-gone.mid +0 -0
- package/songs/library/classical/bach-prelude-c-major-bwv846.json +37 -0
- package/songs/library/classical/bach-prelude-c-major-bwv846.mid +0 -0
- package/songs/library/classical/chopin-nocturne-op9-no2.json +36 -0
- package/songs/library/classical/chopin-nocturne-op9-no2.mid +0 -0
- package/songs/library/classical/chopin-prelude-e-minor.json +35 -0
- package/songs/library/classical/chopin-prelude-e-minor.mid +0 -0
- package/songs/library/classical/clair-de-lune.json +37 -0
- package/songs/library/classical/clair-de-lune.mid +0 -0
- package/songs/library/classical/debussy-arabesque-no1.json +35 -0
- package/songs/library/classical/debussy-arabesque-no1.mid +0 -0
- package/songs/library/classical/fur-elise.json +35 -0
- package/songs/library/classical/fur-elise.mid +0 -0
- package/songs/library/classical/mozart-k545-mvt1.json +35 -0
- package/songs/library/classical/mozart-k545-mvt1.mid +0 -0
- package/songs/library/classical/pathetique-mvt2.json +36 -0
- package/songs/library/classical/pathetique-mvt2.mid +0 -0
- package/songs/library/classical/satie-gymnopedie-no1.json +36 -0
- package/songs/library/classical/satie-gymnopedie-no1.mid +0 -0
- package/songs/library/classical/schumann-traumerei.json +36 -0
- package/songs/library/classical/schumann-traumerei.mid +0 -0
- package/songs/library/film/cinema-paradiso.json +14 -0
- package/songs/library/film/cinema-paradiso.mid +0 -0
- package/songs/library/film/comptine-dun-autre-ete.json +17 -0
- package/songs/library/film/comptine-dun-autre-ete.mid +0 -0
- package/songs/library/film/forrest-gump.json +14 -0
- package/songs/library/film/forrest-gump.mid +0 -0
- package/songs/library/film/hedwigs-theme.json +14 -0
- package/songs/library/film/hedwigs-theme.mid +0 -0
- package/songs/library/film/mia-and-sebastians-theme.json +14 -0
- package/songs/library/film/mia-and-sebastians-theme.mid +0 -0
- package/songs/library/film/moon-river.json +14 -0
- package/songs/library/film/moon-river.mid +0 -0
- package/songs/library/film/my-heart-will-go-on.json +14 -0
- package/songs/library/film/my-heart-will-go-on.mid +0 -0
- package/songs/library/film/nuvole-bianche.json +14 -0
- package/songs/library/film/nuvole-bianche.mid +0 -0
- package/songs/library/film/pink-panther.json +14 -0
- package/songs/library/film/pink-panther.mid +0 -0
- package/songs/library/film/schindlers-list-theme.json +14 -0
- package/songs/library/film/schindlers-list-theme.mid +0 -0
- package/songs/library/folk/amazing-grace.json +14 -0
- package/songs/library/folk/amazing-grace.mid +0 -0
- package/songs/library/folk/auld-lang-syne.json +14 -0
- package/songs/library/folk/auld-lang-syne.mid +0 -0
- package/songs/library/folk/danny-boy.json +14 -0
- package/songs/library/folk/danny-boy.mid +0 -0
- package/songs/library/folk/greensleeves.json +17 -0
- package/songs/library/folk/greensleeves.mid +0 -0
- package/songs/library/folk/house-of-the-rising-sun.json +14 -0
- package/songs/library/folk/house-of-the-rising-sun.mid +0 -0
- package/songs/library/folk/sakura-sakura.json +14 -0
- package/songs/library/folk/sakura-sakura.mid +0 -0
- package/songs/library/folk/scarborough-fair.json +14 -0
- package/songs/library/folk/scarborough-fair.mid +0 -0
- package/songs/library/folk/shenandoah.json +14 -0
- package/songs/library/folk/shenandoah.mid +0 -0
- package/songs/library/folk/simple-gifts.json +14 -0
- package/songs/library/folk/simple-gifts.mid +0 -0
- package/songs/library/folk/the-water-is-wide.json +14 -0
- package/songs/library/folk/the-water-is-wide.mid +0 -0
- package/songs/library/jazz/all-the-things-you-are.json +13 -0
- package/songs/library/jazz/all-the-things-you-are.mid +0 -0
- package/songs/library/jazz/autumn-leaves.json +17 -0
- package/songs/library/jazz/autumn-leaves.mid +0 -0
- package/songs/library/jazz/blue-bossa.json +14 -0
- package/songs/library/jazz/blue-bossa.mid +0 -0
- package/songs/library/jazz/fly-me-to-the-moon.json +14 -0
- package/songs/library/jazz/fly-me-to-the-moon.mid +0 -0
- package/songs/library/jazz/georgia-on-my-mind.json +14 -0
- package/songs/library/jazz/georgia-on-my-mind.mid +0 -0
- package/songs/library/jazz/misty.json +14 -0
- package/songs/library/jazz/misty.mid +0 -0
- package/songs/library/jazz/my-funny-valentine.json +14 -0
- package/songs/library/jazz/my-funny-valentine.mid +0 -0
- package/songs/library/jazz/round-midnight.json +14 -0
- package/songs/library/jazz/round-midnight.mid +0 -0
- package/songs/library/jazz/summertime.json +14 -0
- package/songs/library/jazz/summertime.mid +0 -0
- package/songs/library/jazz/take-the-a-train.json +14 -0
- package/songs/library/jazz/take-the-a-train.mid +0 -0
- package/songs/library/latin/agua-de-beber.json +14 -0
- package/songs/library/latin/agua-de-beber.mid +0 -0
- package/songs/library/latin/besame-mucho.json +14 -0
- package/songs/library/latin/besame-mucho.mid +0 -0
- package/songs/library/latin/black-orpheus.json +14 -0
- package/songs/library/latin/black-orpheus.mid +0 -0
- package/songs/library/latin/corcovado.json +14 -0
- package/songs/library/latin/corcovado.mid +0 -0
- package/songs/library/latin/desafinado.json +14 -0
- package/songs/library/latin/desafinado.mid +0 -0
- package/songs/library/latin/el-condor-pasa.json +14 -0
- package/songs/library/latin/el-condor-pasa.mid +0 -0
- package/songs/library/latin/girl-from-ipanema.json +17 -0
- package/songs/library/latin/girl-from-ipanema.mid +0 -0
- package/songs/library/latin/mas-que-nada.json +14 -0
- package/songs/library/latin/mas-que-nada.mid +0 -0
- package/songs/library/latin/perfidia.json +14 -0
- package/songs/library/latin/perfidia.mid +0 -0
- package/songs/library/latin/wave.json +14 -0
- package/songs/library/latin/wave.mid +0 -0
- package/songs/library/new-age/divenire.json +14 -0
- package/songs/library/new-age/divenire.mid +0 -0
- package/songs/library/new-age/experience.json +14 -0
- package/songs/library/new-age/experience.mid +0 -0
- package/songs/library/new-age/kiss-the-rain.json +14 -0
- package/songs/library/new-age/kiss-the-rain.mid +0 -0
- package/songs/library/new-age/may-be.json +13 -0
- package/songs/library/new-age/may-be.mid +0 -0
- package/songs/library/new-age/metamorphosis-two.json +14 -0
- package/songs/library/new-age/metamorphosis-two.mid +0 -0
- package/songs/library/new-age/nuvole-bianche-na.json +14 -0
- package/songs/library/new-age/nuvole-bianche-na.mid +0 -0
- package/songs/library/new-age/opening-glassworks.json +14 -0
- package/songs/library/new-age/opening-glassworks.mid +0 -0
- package/songs/library/new-age/river-flows-in-you.json +17 -0
- package/songs/library/new-age/river-flows-in-you.mid +0 -0
- package/songs/library/new-age/una-mattina.json +14 -0
- package/songs/library/new-age/una-mattina.mid +0 -0
- package/songs/library/new-age/watermark.json +14 -0
- package/songs/library/new-age/watermark.mid +0 -0
- package/songs/library/pop/a-thousand-years.json +14 -0
- package/songs/library/pop/a-thousand-years.mid +0 -0
- package/songs/library/pop/all-of-me.json +14 -0
- package/songs/library/pop/all-of-me.mid +0 -0
- package/songs/library/pop/bohemian-rhapsody.json +14 -0
- package/songs/library/pop/bohemian-rhapsody.mid +0 -0
- package/songs/library/pop/clocks.json +14 -0
- package/songs/library/pop/clocks.mid +0 -0
- package/songs/library/pop/imagine.json +17 -0
- package/songs/library/pop/imagine.mid +0 -0
- package/songs/library/pop/let-it-be.json +14 -0
- package/songs/library/pop/let-it-be.mid +0 -0
- package/songs/library/pop/piano-man.json +14 -0
- package/songs/library/pop/piano-man.mid +0 -0
- package/songs/library/pop/someone-like-you.json +14 -0
- package/songs/library/pop/someone-like-you.mid +0 -0
- package/songs/library/pop/someone-you-loved.json +14 -0
- package/songs/library/pop/someone-you-loved.mid +0 -0
- package/songs/library/pop/viva-la-vida.json +14 -0
- package/songs/library/pop/viva-la-vida.mid +0 -0
- package/songs/library/ragtime/bethena.json +14 -0
- package/songs/library/ragtime/bethena.mid +0 -0
- package/songs/library/ragtime/elite-syncopations.json +13 -0
- package/songs/library/ragtime/elite-syncopations.mid +0 -0
- package/songs/library/ragtime/gladiolus-rag.json +13 -0
- package/songs/library/ragtime/gladiolus-rag.mid +0 -0
- package/songs/library/ragtime/maple-leaf-rag.json +13 -0
- package/songs/library/ragtime/maple-leaf-rag.mid +0 -0
- package/songs/library/ragtime/peacherine-rag.json +13 -0
- package/songs/library/ragtime/peacherine-rag.mid +0 -0
- package/songs/library/ragtime/pineapple-rag.json +13 -0
- package/songs/library/ragtime/pineapple-rag.mid +0 -0
- package/songs/library/ragtime/solace.json +14 -0
- package/songs/library/ragtime/solace.mid +0 -0
- package/songs/library/ragtime/the-easy-winners.json +13 -0
- package/songs/library/ragtime/the-easy-winners.mid +0 -0
- package/songs/library/ragtime/the-entertainer.json +17 -0
- package/songs/library/ragtime/the-entertainer.mid +0 -0
- package/songs/library/ragtime/weeping-willow.json +14 -0
- package/songs/library/ragtime/weeping-willow.mid +0 -0
- package/songs/library/rnb/fallin.json +17 -0
- package/songs/library/rnb/fallin.mid +0 -0
- package/songs/library/rnb/halo.json +14 -0
- package/songs/library/rnb/halo.mid +0 -0
- package/songs/library/rnb/i-will-always-love-you.json +14 -0
- package/songs/library/rnb/i-will-always-love-you.mid +0 -0
- package/songs/library/rnb/if-i-aint-got-you.json +17 -0
- package/songs/library/rnb/if-i-aint-got-you.mid +0 -0
- package/songs/library/rnb/isnt-she-lovely.json +17 -0
- package/songs/library/rnb/isnt-she-lovely.mid +0 -0
- package/songs/library/rnb/killing-me-softly.json +14 -0
- package/songs/library/rnb/killing-me-softly.mid +0 -0
- package/songs/library/rnb/no-one.json +14 -0
- package/songs/library/rnb/no-one.mid +0 -0
- package/songs/library/rnb/ordinary-people.json +14 -0
- package/songs/library/rnb/ordinary-people.mid +0 -0
- package/songs/library/rnb/ribbon-in-the-sky.json +14 -0
- package/songs/library/rnb/ribbon-in-the-sky.mid +0 -0
- package/songs/library/rnb/superstition.json +17 -0
- package/songs/library/rnb/superstition.mid +0 -0
- package/songs/library/rock/baba-oriley.json +14 -0
- package/songs/library/rock/baba-oriley.mid +0 -0
- package/songs/library/rock/bennie-and-the-jets.json +14 -0
- package/songs/library/rock/bennie-and-the-jets.mid +0 -0
- package/songs/library/rock/dont-stop-believin.json +14 -0
- package/songs/library/rock/dont-stop-believin.mid +0 -0
- package/songs/library/rock/dream-on.json +14 -0
- package/songs/library/rock/dream-on.mid +0 -0
- package/songs/library/rock/layla-unplugged.json +14 -0
- package/songs/library/rock/layla-unplugged.mid +0 -0
- package/songs/library/rock/november-rain.json +15 -0
- package/songs/library/rock/november-rain.mid +0 -0
- package/songs/library/rock/rocket-man.json +14 -0
- package/songs/library/rock/rocket-man.mid +0 -0
- package/songs/library/rock/stairway-to-heaven.json +14 -0
- package/songs/library/rock/stairway-to-heaven.mid +0 -0
- package/songs/library/rock/tiny-dancer.json +14 -0
- package/songs/library/rock/tiny-dancer.mid +0 -0
- package/songs/library/rock/your-song.json +17 -0
- package/songs/library/rock/your-song.mid +0 -0
- package/songs/library/soul/a-change-is-gonna-come.json +14 -0
- package/songs/library/soul/a-change-is-gonna-come.mid +0 -0
- package/songs/library/soul/aint-no-sunshine.json +14 -0
- package/songs/library/soul/aint-no-sunshine.mid +0 -0
- package/songs/library/soul/dock-of-the-bay.json +13 -0
- package/songs/library/soul/dock-of-the-bay.mid +0 -0
- package/songs/library/soul/i-got-you.json +14 -0
- package/songs/library/soul/i-got-you.mid +0 -0
- package/songs/library/soul/lean-on-me.json +17 -0
- package/songs/library/soul/lean-on-me.mid +0 -0
- package/songs/library/soul/lets-stay-together.json +14 -0
- package/songs/library/soul/lets-stay-together.mid +0 -0
- package/songs/library/soul/my-girl.json +14 -0
- package/songs/library/soul/my-girl.mid +0 -0
- package/songs/library/soul/respect.json +14 -0
- package/songs/library/soul/respect.mid +0 -0
- package/songs/library/soul/stand-by-me.json +14 -0
- package/songs/library/soul/stand-by-me.mid +0 -0
- package/songs/library/soul/whats-going-on.json +14 -0
- package/songs/library/soul/whats-going-on.mid +0 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
// ─── pianoai: Note Parser ────────────────────────────────────────────────────
|
|
2
|
+
//
|
|
3
|
+
// Converts scientific pitch notation (e.g. "C4:q", "F#5:e", "Bb3:h")
|
|
4
|
+
// into MIDI note numbers and durations for playback.
|
|
5
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
import { NOTE_OFFSETS, DURATION_MAP } from "./types.js";
|
|
7
|
+
/**
|
|
8
|
+
* Parse a scientific pitch string into a MIDI note number.
|
|
9
|
+
*
|
|
10
|
+
* Examples:
|
|
11
|
+
* "C4" → 60 (middle C)
|
|
12
|
+
* "A4" → 69 (concert A)
|
|
13
|
+
* "F#5" → 78
|
|
14
|
+
* "Bb3" → 58
|
|
15
|
+
* "R" → -1 (rest)
|
|
16
|
+
*/
|
|
17
|
+
export function parseNoteToMidi(noteStr) {
|
|
18
|
+
const trimmed = noteStr.trim();
|
|
19
|
+
if (trimmed === "R" || trimmed === "r")
|
|
20
|
+
return -1; // rest
|
|
21
|
+
// Match: letter + optional accidental + octave
|
|
22
|
+
// e.g. "C4", "F#5", "Bb3", "G#4"
|
|
23
|
+
const match = trimmed.match(/^([A-Ga-g])(#|b)?(\d)$/);
|
|
24
|
+
if (!match) {
|
|
25
|
+
throw new Error(`Invalid note: "${noteStr}"`);
|
|
26
|
+
}
|
|
27
|
+
const [, letter, accidental, octaveStr] = match;
|
|
28
|
+
const base = NOTE_OFFSETS[letter.toUpperCase()];
|
|
29
|
+
if (base === undefined) {
|
|
30
|
+
throw new Error(`Unknown note letter: "${letter}"`);
|
|
31
|
+
}
|
|
32
|
+
const octave = parseInt(octaveStr, 10);
|
|
33
|
+
let midi = (octave + 1) * 12 + base;
|
|
34
|
+
if (accidental === "#")
|
|
35
|
+
midi += 1;
|
|
36
|
+
if (accidental === "b")
|
|
37
|
+
midi -= 1;
|
|
38
|
+
if (midi < 0 || midi > 127) {
|
|
39
|
+
throw new Error(`MIDI note out of range: ${midi} (from "${noteStr}")`);
|
|
40
|
+
}
|
|
41
|
+
return midi;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Parse a duration suffix into a multiplier relative to a quarter note.
|
|
45
|
+
*
|
|
46
|
+
* ":w" → 4.0 (whole), ":h" → 2.0 (half), ":q" → 1.0 (quarter),
|
|
47
|
+
* ":e" → 0.5 (eighth), ":s" → 0.25 (sixteenth).
|
|
48
|
+
* Default (no suffix) → 1.0 (quarter).
|
|
49
|
+
*/
|
|
50
|
+
export function parseDuration(suffix) {
|
|
51
|
+
const mult = DURATION_MAP[suffix];
|
|
52
|
+
if (mult === undefined) {
|
|
53
|
+
throw new Error(`Unknown duration suffix: "${suffix}"`);
|
|
54
|
+
}
|
|
55
|
+
return mult;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Convert a BPM tempo + duration multiplier → milliseconds.
|
|
59
|
+
*
|
|
60
|
+
* At 120 BPM, a quarter note = 500ms.
|
|
61
|
+
* A half note at 120 BPM = 1000ms.
|
|
62
|
+
*/
|
|
63
|
+
export function durationToMs(multiplier, bpm) {
|
|
64
|
+
const quarterMs = 60_000 / bpm;
|
|
65
|
+
return quarterMs * multiplier;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Parse a single note token like "C4:q" or "R:h" into a MidiNote.
|
|
69
|
+
*
|
|
70
|
+
* @param token - e.g. "C4:q", "F#5:e", "Bb3:h", "R:q"
|
|
71
|
+
* @param bpm - tempo in beats per minute
|
|
72
|
+
* @param channel - MIDI channel (0-15)
|
|
73
|
+
* @param velocity - MIDI velocity (0-127)
|
|
74
|
+
*/
|
|
75
|
+
export function parseNoteToken(token, bpm, channel = 0, velocity = 80) {
|
|
76
|
+
const trimmed = token.trim();
|
|
77
|
+
const parts = trimmed.split(":");
|
|
78
|
+
const noteStr = parts[0];
|
|
79
|
+
const durationSuffix = parts[1] ?? "q"; // default to quarter note
|
|
80
|
+
const midi = parseNoteToMidi(noteStr);
|
|
81
|
+
const mult = parseDuration(durationSuffix);
|
|
82
|
+
const durationMs = durationToMs(mult, bpm);
|
|
83
|
+
return {
|
|
84
|
+
note: midi,
|
|
85
|
+
velocity: midi === -1 ? 0 : velocity, // rests have 0 velocity
|
|
86
|
+
durationMs,
|
|
87
|
+
channel,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse a hand string like "C4:q E4:q G4:q" into an array of Beats.
|
|
92
|
+
*
|
|
93
|
+
* Each space-separated token becomes a sequential beat.
|
|
94
|
+
* Chords use "+" to join simultaneous notes: "C4+E4+G4:q"
|
|
95
|
+
* The duration suffix on the last note applies to all chord tones.
|
|
96
|
+
*/
|
|
97
|
+
export function parseHandString(handStr, hand, bpm, channel = 0, velocity = 80) {
|
|
98
|
+
if (!handStr || handStr.trim() === "")
|
|
99
|
+
return [];
|
|
100
|
+
const tokens = handStr.trim().split(/\s+/);
|
|
101
|
+
return tokens.map((token) => {
|
|
102
|
+
if (token.includes("+")) {
|
|
103
|
+
return parseChordToken(token, hand, bpm, channel, velocity);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
notes: [parseNoteToken(token, bpm, channel, velocity)],
|
|
107
|
+
hand,
|
|
108
|
+
};
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Parse a chord token like "C4+E4+G4:q" into a Beat with multiple notes.
|
|
113
|
+
* The duration suffix from the last sub-token applies to all notes.
|
|
114
|
+
*/
|
|
115
|
+
function parseChordToken(token, hand, bpm, channel, velocity) {
|
|
116
|
+
const parts = token.split("+");
|
|
117
|
+
// Find the duration from the part that has one (last part has ":dur")
|
|
118
|
+
let sharedDuration = "q";
|
|
119
|
+
for (const part of parts) {
|
|
120
|
+
if (part.includes(":")) {
|
|
121
|
+
sharedDuration = part.split(":")[1];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
const notes = parts.map((part) => {
|
|
125
|
+
if (part.includes(":")) {
|
|
126
|
+
return parseNoteToken(part, bpm, channel, velocity);
|
|
127
|
+
}
|
|
128
|
+
return parseNoteToken(`${part}:${sharedDuration}`, bpm, channel, velocity);
|
|
129
|
+
});
|
|
130
|
+
return { notes, hand };
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Parse a full Measure into a PlayableMeasure with MIDI-ready beats.
|
|
134
|
+
*/
|
|
135
|
+
export function parseMeasure(measure, bpm, velocity = 80) {
|
|
136
|
+
return {
|
|
137
|
+
source: measure,
|
|
138
|
+
rightBeats: parseHandString(measure.rightHand, "right", bpm, 0, velocity),
|
|
139
|
+
leftBeats: parseHandString(measure.leftHand, "left", bpm, 0, velocity),
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Safely parse a note token — returns null on error instead of throwing.
|
|
144
|
+
* Collects a warning in the provided array when parsing fails.
|
|
145
|
+
*/
|
|
146
|
+
export function safeParseNoteToken(token, bpm, location, warnings, channel = 0, velocity = 80) {
|
|
147
|
+
try {
|
|
148
|
+
return parseNoteToken(token, bpm, channel, velocity);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
warnings.push({
|
|
152
|
+
location,
|
|
153
|
+
token,
|
|
154
|
+
message: err instanceof Error ? err.message : String(err),
|
|
155
|
+
});
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Safe version of parseHandString — skips bad tokens, collects warnings.
|
|
161
|
+
*/
|
|
162
|
+
export function safeParseHandString(handStr, hand, bpm, measureNumber, warnings, channel = 0, velocity = 80) {
|
|
163
|
+
if (!handStr || handStr.trim() === "")
|
|
164
|
+
return [];
|
|
165
|
+
const tokens = handStr.trim().split(/\s+/);
|
|
166
|
+
const beats = [];
|
|
167
|
+
for (const token of tokens) {
|
|
168
|
+
if (token.includes("+")) {
|
|
169
|
+
// Chord token — parse each sub-note
|
|
170
|
+
try {
|
|
171
|
+
beats.push(parseChordToken(token, hand, bpm, channel, velocity));
|
|
172
|
+
}
|
|
173
|
+
catch (err) {
|
|
174
|
+
warnings.push({
|
|
175
|
+
location: `measure ${measureNumber} ${hand} hand`,
|
|
176
|
+
token,
|
|
177
|
+
message: err instanceof Error ? err.message : String(err),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
const note = safeParseNoteToken(token, bpm, `measure ${measureNumber} ${hand} hand`, warnings, channel, velocity);
|
|
183
|
+
if (note) {
|
|
184
|
+
beats.push({ notes: [note], hand });
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return beats;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Safe version of parseMeasure — skips bad notes, collects warnings.
|
|
192
|
+
*/
|
|
193
|
+
export function safeParseMeasure(measure, bpm, warnings, velocity = 80) {
|
|
194
|
+
return {
|
|
195
|
+
source: measure,
|
|
196
|
+
rightBeats: safeParseHandString(measure.rightHand, "right", bpm, measure.number, warnings, 0, velocity),
|
|
197
|
+
leftBeats: safeParseHandString(measure.leftHand, "left", bpm, measure.number, warnings, 0, velocity),
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Convert a MIDI note number back to a note name (for display).
|
|
202
|
+
*
|
|
203
|
+
* 60 → "C4", 69 → "A4", 78 → "F#5"
|
|
204
|
+
*/
|
|
205
|
+
export function midiToNoteName(midi) {
|
|
206
|
+
if (midi < 0)
|
|
207
|
+
return "R";
|
|
208
|
+
const noteNames = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
|
|
209
|
+
const octave = Math.floor(midi / 12) - 1;
|
|
210
|
+
const noteIndex = midi % 12;
|
|
211
|
+
return `${noteNames[noteIndex]}${octave}`;
|
|
212
|
+
}
|
|
213
|
+
/** Solfege mapping: note name (with optional accidental) → solfege syllable. */
|
|
214
|
+
const SOLFEGE_MAP = {
|
|
215
|
+
C: "Do", "C#": "Di", Db: "Ra",
|
|
216
|
+
D: "Re", "D#": "Ri", Eb: "Me",
|
|
217
|
+
E: "Mi",
|
|
218
|
+
F: "Fa", "F#": "Fi", Gb: "Se",
|
|
219
|
+
G: "Sol", "G#": "Si", Ab: "Le",
|
|
220
|
+
A: "La", "A#": "Li", Bb: "Te",
|
|
221
|
+
B: "Ti",
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Convert a single note string (e.g. "C4", "F#5") to a singable syllable.
|
|
225
|
+
*
|
|
226
|
+
* - "note-names": "C", "F sharp", "B flat"
|
|
227
|
+
* - "solfege": "Do", "Fi", "Te"
|
|
228
|
+
* - "syllables": always "da"
|
|
229
|
+
* - "contour": falls back to letter (contour handled at measure level)
|
|
230
|
+
*/
|
|
231
|
+
export function noteToSingable(noteStr, mode) {
|
|
232
|
+
const trimmed = noteStr.trim();
|
|
233
|
+
if (trimmed === "R" || trimmed === "r")
|
|
234
|
+
return mode === "syllables" ? "..." : "rest";
|
|
235
|
+
const match = trimmed.match(/^([A-Ga-g])(#|b)?(\d)?$/);
|
|
236
|
+
if (!match)
|
|
237
|
+
return trimmed; // pass through unparseable
|
|
238
|
+
const [, letter, accidental] = match;
|
|
239
|
+
const upperLetter = letter.toUpperCase();
|
|
240
|
+
switch (mode) {
|
|
241
|
+
case "note-names": {
|
|
242
|
+
const acc = accidental === "#" ? " sharp" : accidental === "b" ? " flat" : "";
|
|
243
|
+
return `${upperLetter}${acc}`;
|
|
244
|
+
}
|
|
245
|
+
case "solfege": {
|
|
246
|
+
const key = accidental ? `${upperLetter}${accidental}` : upperLetter;
|
|
247
|
+
return SOLFEGE_MAP[key] ?? upperLetter;
|
|
248
|
+
}
|
|
249
|
+
case "syllables":
|
|
250
|
+
return "da";
|
|
251
|
+
case "contour":
|
|
252
|
+
return upperLetter; // fallback — contour handled at measure level
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Convert a hand string (e.g. "C4:q E4:q G4:q") to singable text.
|
|
257
|
+
*
|
|
258
|
+
* For "contour" mode, compares consecutive MIDI pitches and returns
|
|
259
|
+
* direction words: "up", "down", "same".
|
|
260
|
+
*
|
|
261
|
+
* For other modes, maps each note token through noteToSingable and
|
|
262
|
+
* joins with "... " (speech pause).
|
|
263
|
+
*/
|
|
264
|
+
export function handToSingableText(handStr, mode) {
|
|
265
|
+
if (!handStr || handStr.trim() === "")
|
|
266
|
+
return "";
|
|
267
|
+
const tokens = handStr.trim().split(/\s+/);
|
|
268
|
+
if (mode === "contour") {
|
|
269
|
+
if (tokens.length <= 1)
|
|
270
|
+
return "hold";
|
|
271
|
+
const midis = tokens.map((t) => {
|
|
272
|
+
const noteStr = t.split(":")[0];
|
|
273
|
+
try {
|
|
274
|
+
return parseNoteToMidi(noteStr);
|
|
275
|
+
}
|
|
276
|
+
catch {
|
|
277
|
+
return -1;
|
|
278
|
+
}
|
|
279
|
+
});
|
|
280
|
+
const dirs = [];
|
|
281
|
+
for (let i = 1; i < midis.length; i++) {
|
|
282
|
+
if (midis[i] < 0 || midis[i - 1] < 0) {
|
|
283
|
+
dirs.push("rest");
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
286
|
+
const diff = midis[i] - midis[i - 1];
|
|
287
|
+
dirs.push(diff > 0 ? "up" : diff < 0 ? "down" : "same");
|
|
288
|
+
}
|
|
289
|
+
return dirs.join("... ");
|
|
290
|
+
}
|
|
291
|
+
// note-names, solfege, syllables
|
|
292
|
+
const syllables = tokens.map((t) => {
|
|
293
|
+
const noteStr = t.split(":")[0];
|
|
294
|
+
return noteToSingable(noteStr, mode);
|
|
295
|
+
});
|
|
296
|
+
return syllables.join("... ");
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Convert a Measure to singable text for voice narration.
|
|
300
|
+
*
|
|
301
|
+
* Returns the singable syllables for the specified hand(s).
|
|
302
|
+
* When hand="both", right hand text comes first, then "Left hand:" prefix.
|
|
303
|
+
*/
|
|
304
|
+
export function measureToSingableText(measure, options) {
|
|
305
|
+
const { mode, hand } = options;
|
|
306
|
+
if (hand === "right")
|
|
307
|
+
return handToSingableText(measure.rightHand, mode);
|
|
308
|
+
if (hand === "left")
|
|
309
|
+
return handToSingableText(measure.leftHand, mode);
|
|
310
|
+
// both
|
|
311
|
+
const right = handToSingableText(measure.rightHand, mode);
|
|
312
|
+
const left = handToSingableText(measure.leftHand, mode);
|
|
313
|
+
if (!left)
|
|
314
|
+
return right;
|
|
315
|
+
if (!right)
|
|
316
|
+
return left;
|
|
317
|
+
return `${right}. Left hand: ${left}`;
|
|
318
|
+
}
|
|
319
|
+
//# sourceMappingURL=note-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"note-parser.js","sourceRoot":"","sources":["../src/note-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { SongEntry } from "./songs/types.js";
|
|
2
|
+
export type PianoRollColorMode = "hand" | "pitch-class";
|
|
3
|
+
export interface PianoRollOptions {
|
|
4
|
+
/** First measure to render (1-based). Default: 1 */
|
|
5
|
+
startMeasure?: number;
|
|
6
|
+
/** Last measure to render (1-based). Default: last measure */
|
|
7
|
+
endMeasure?: number;
|
|
8
|
+
/** Horizontal pixels per beat. Default: 60 */
|
|
9
|
+
pixelsPerBeat?: number;
|
|
10
|
+
/** Vertical pixels per semitone row. Default: 10 */
|
|
11
|
+
pitchRowHeight?: number;
|
|
12
|
+
/** Show metronome dots on downbeats. Default: true */
|
|
13
|
+
showMetronome?: boolean;
|
|
14
|
+
/** Show dynamics markings. Default: true */
|
|
15
|
+
showDynamics?: boolean;
|
|
16
|
+
/** Show measure teaching notes as tooltip titles. Default: false */
|
|
17
|
+
showTeachingNotes?: boolean;
|
|
18
|
+
/** Note coloring mode. Default: "hand" (blue RH / coral LH). */
|
|
19
|
+
colorMode?: PianoRollColorMode;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Render a SongEntry as an SVG piano roll string.
|
|
23
|
+
*
|
|
24
|
+
* Returns a complete SVG document as a string — no file I/O,
|
|
25
|
+
* no DOM, no external dependencies.
|
|
26
|
+
*/
|
|
27
|
+
export declare function renderPianoRoll(song: SongEntry, options?: PianoRollOptions): string;
|
|
28
|
+
//# sourceMappingURL=piano-roll.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"piano-roll.d.ts","sourceRoot":"","sources":["../src/piano-roll.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,SAAS,EAAW,MAAM,kBAAkB,CAAC;AAI3D,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,aAAa,CAAC;AAExD,MAAM,WAAW,gBAAgB;IAC/B,oDAAoD;IACpD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,oDAAoD;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,sDAAsD;IACtD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,4CAA4C;IAC5C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,oEAAoE;IACpE,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,gEAAgE;IAChE,SAAS,CAAC,EAAE,kBAAkB,CAAC;CAChC;AA2ID;;;;;GAKG;AACH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,SAAS,EACf,OAAO,CAAC,EAAE,gBAAgB,GACzB,MAAM,CAwNR"}
|