@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.
Files changed (408) hide show
  1. package/LICENSE +21 -0
  2. package/README.es.md +177 -0
  3. package/README.fr.md +178 -0
  4. package/README.hi.md +175 -0
  5. package/README.it.md +177 -0
  6. package/README.ja.md +174 -0
  7. package/README.md +174 -0
  8. package/README.pt-BR.md +177 -0
  9. package/README.zh.md +173 -0
  10. package/dist/audio-engine.d.ts +12 -0
  11. package/dist/audio-engine.d.ts.map +1 -0
  12. package/dist/audio-engine.js +422 -0
  13. package/dist/audio-engine.js.map +1 -0
  14. package/dist/chord-detect.d.ts +14 -0
  15. package/dist/chord-detect.d.ts.map +1 -0
  16. package/dist/chord-detect.js +90 -0
  17. package/dist/chord-detect.js.map +1 -0
  18. package/dist/cli.d.ts +3 -0
  19. package/dist/cli.d.ts.map +1 -0
  20. package/dist/cli.js +805 -0
  21. package/dist/cli.js.map +1 -0
  22. package/dist/index.d.ts +32 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +41 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/journal.d.ts +41 -0
  27. package/dist/journal.d.ts.map +1 -0
  28. package/dist/journal.js +149 -0
  29. package/dist/journal.js.map +1 -0
  30. package/dist/mcp-server.d.ts +3 -0
  31. package/dist/mcp-server.d.ts.map +1 -0
  32. package/dist/mcp-server.js +1256 -0
  33. package/dist/mcp-server.js.map +1 -0
  34. package/dist/midi/parser.d.ts +16 -0
  35. package/dist/midi/parser.d.ts.map +1 -0
  36. package/dist/midi/parser.js +192 -0
  37. package/dist/midi/parser.js.map +1 -0
  38. package/dist/midi/types.d.ts +44 -0
  39. package/dist/midi/types.d.ts.map +1 -0
  40. package/dist/midi/types.js +8 -0
  41. package/dist/midi/types.js.map +1 -0
  42. package/dist/note-parser.d.ts +105 -0
  43. package/dist/note-parser.d.ts.map +1 -0
  44. package/dist/note-parser.js +319 -0
  45. package/dist/note-parser.js.map +1 -0
  46. package/dist/piano-roll.d.ts +28 -0
  47. package/dist/piano-roll.d.ts.map +1 -0
  48. package/dist/piano-roll.js +321 -0
  49. package/dist/piano-roll.js.map +1 -0
  50. package/dist/piano-voices.d.ts +90 -0
  51. package/dist/piano-voices.d.ts.map +1 -0
  52. package/dist/piano-voices.js +416 -0
  53. package/dist/piano-voices.js.map +1 -0
  54. package/dist/playback/controls.d.ts +124 -0
  55. package/dist/playback/controls.d.ts.map +1 -0
  56. package/dist/playback/controls.js +252 -0
  57. package/dist/playback/controls.js.map +1 -0
  58. package/dist/playback/midi-engine.d.ts +68 -0
  59. package/dist/playback/midi-engine.d.ts.map +1 -0
  60. package/dist/playback/midi-engine.js +227 -0
  61. package/dist/playback/midi-engine.js.map +1 -0
  62. package/dist/playback/position.d.ts +95 -0
  63. package/dist/playback/position.d.ts.map +1 -0
  64. package/dist/playback/position.js +223 -0
  65. package/dist/playback/position.js.map +1 -0
  66. package/dist/playback/timing.d.ts +31 -0
  67. package/dist/playback/timing.d.ts.map +1 -0
  68. package/dist/playback/timing.js +57 -0
  69. package/dist/playback/timing.js.map +1 -0
  70. package/dist/sample-engine.d.ts +17 -0
  71. package/dist/sample-engine.d.ts.map +1 -0
  72. package/dist/sample-engine.js +428 -0
  73. package/dist/sample-engine.js.map +1 -0
  74. package/dist/schemas.d.ts +40 -0
  75. package/dist/schemas.d.ts.map +1 -0
  76. package/dist/schemas.js +42 -0
  77. package/dist/schemas.js.map +1 -0
  78. package/dist/session.d.ts +106 -0
  79. package/dist/session.d.ts.map +1 -0
  80. package/dist/session.js +361 -0
  81. package/dist/session.js.map +1 -0
  82. package/dist/sfz-parser.d.ts +36 -0
  83. package/dist/sfz-parser.d.ts.map +1 -0
  84. package/dist/sfz-parser.js +95 -0
  85. package/dist/sfz-parser.js.map +1 -0
  86. package/dist/smoke.d.ts +2 -0
  87. package/dist/smoke.d.ts.map +1 -0
  88. package/dist/smoke.js +512 -0
  89. package/dist/smoke.js.map +1 -0
  90. package/dist/songs/config/loader.d.ts +14 -0
  91. package/dist/songs/config/loader.d.ts.map +1 -0
  92. package/dist/songs/config/loader.js +53 -0
  93. package/dist/songs/config/loader.js.map +1 -0
  94. package/dist/songs/config/schema.d.ts +79 -0
  95. package/dist/songs/config/schema.d.ts.map +1 -0
  96. package/dist/songs/config/schema.js +56 -0
  97. package/dist/songs/config/schema.js.map +1 -0
  98. package/dist/songs/index.d.ts +18 -0
  99. package/dist/songs/index.d.ts.map +1 -0
  100. package/dist/songs/index.js +22 -0
  101. package/dist/songs/index.js.map +1 -0
  102. package/dist/songs/jam.d.ts +48 -0
  103. package/dist/songs/jam.d.ts.map +1 -0
  104. package/dist/songs/jam.js +338 -0
  105. package/dist/songs/jam.js.map +1 -0
  106. package/dist/songs/library.d.ts +47 -0
  107. package/dist/songs/library.d.ts.map +1 -0
  108. package/dist/songs/library.js +156 -0
  109. package/dist/songs/library.js.map +1 -0
  110. package/dist/songs/loader.d.ts +27 -0
  111. package/dist/songs/loader.d.ts.map +1 -0
  112. package/dist/songs/loader.js +90 -0
  113. package/dist/songs/loader.js.map +1 -0
  114. package/dist/songs/midi/hands.d.ts +46 -0
  115. package/dist/songs/midi/hands.d.ts.map +1 -0
  116. package/dist/songs/midi/hands.js +134 -0
  117. package/dist/songs/midi/hands.js.map +1 -0
  118. package/dist/songs/midi/ingest.d.ts +8 -0
  119. package/dist/songs/midi/ingest.d.ts.map +1 -0
  120. package/dist/songs/midi/ingest.js +197 -0
  121. package/dist/songs/midi/ingest.js.map +1 -0
  122. package/dist/songs/midi/measures.d.ts +41 -0
  123. package/dist/songs/midi/measures.d.ts.map +1 -0
  124. package/dist/songs/midi/measures.js +64 -0
  125. package/dist/songs/midi/measures.js.map +1 -0
  126. package/dist/songs/midi/types.d.ts +25 -0
  127. package/dist/songs/midi/types.d.ts.map +1 -0
  128. package/dist/songs/midi/types.js +8 -0
  129. package/dist/songs/midi/types.js.map +1 -0
  130. package/dist/songs/registry.d.ts +37 -0
  131. package/dist/songs/registry.d.ts.map +1 -0
  132. package/dist/songs/registry.js +197 -0
  133. package/dist/songs/registry.js.map +1 -0
  134. package/dist/songs/types.d.ts +99 -0
  135. package/dist/songs/types.d.ts.map +1 -0
  136. package/dist/songs/types.js +29 -0
  137. package/dist/songs/types.js.map +1 -0
  138. package/dist/teaching/live-midi-feedback.d.ts +36 -0
  139. package/dist/teaching/live-midi-feedback.d.ts.map +1 -0
  140. package/dist/teaching/live-midi-feedback.js +259 -0
  141. package/dist/teaching/live-midi-feedback.js.map +1 -0
  142. package/dist/teaching/midi-feedback.d.ts +33 -0
  143. package/dist/teaching/midi-feedback.d.ts.map +1 -0
  144. package/dist/teaching/midi-feedback.js +208 -0
  145. package/dist/teaching/midi-feedback.js.map +1 -0
  146. package/dist/teaching/sing-on-midi.d.ts +77 -0
  147. package/dist/teaching/sing-on-midi.d.ts.map +1 -0
  148. package/dist/teaching/sing-on-midi.js +186 -0
  149. package/dist/teaching/sing-on-midi.js.map +1 -0
  150. package/dist/teaching.d.ts +148 -0
  151. package/dist/teaching.d.ts.map +1 -0
  152. package/dist/teaching.js +453 -0
  153. package/dist/teaching.js.map +1 -0
  154. package/dist/test-sound.d.ts +3 -0
  155. package/dist/test-sound.d.ts.map +1 -0
  156. package/dist/test-sound.js +41 -0
  157. package/dist/test-sound.js.map +1 -0
  158. package/dist/types.d.ts +229 -0
  159. package/dist/types.d.ts.map +1 -0
  160. package/dist/types.js +28 -0
  161. package/dist/types.js.map +1 -0
  162. package/dist/vmpk.d.ts +23 -0
  163. package/dist/vmpk.d.ts.map +1 -0
  164. package/dist/vmpk.js +236 -0
  165. package/dist/vmpk.js.map +1 -0
  166. package/docs/fur-elise-m1-8.svg +290 -0
  167. package/logo.png +0 -0
  168. package/package.json +71 -0
  169. package/songs/library/blues/blues-in-the-night.json +14 -0
  170. package/songs/library/blues/blues-in-the-night.mid +0 -0
  171. package/songs/library/blues/born-under-a-bad-sign.json +13 -0
  172. package/songs/library/blues/born-under-a-bad-sign.mid +0 -0
  173. package/songs/library/blues/crossroad-blues.json +14 -0
  174. package/songs/library/blues/crossroad-blues.mid +0 -0
  175. package/songs/library/blues/everyday-i-have-the-blues.json +13 -0
  176. package/songs/library/blues/everyday-i-have-the-blues.mid +0 -0
  177. package/songs/library/blues/hoochie-coochie-man.json +14 -0
  178. package/songs/library/blues/hoochie-coochie-man.mid +0 -0
  179. package/songs/library/blues/red-house.json +14 -0
  180. package/songs/library/blues/red-house.mid +0 -0
  181. package/songs/library/blues/st-louis-blues.json +14 -0
  182. package/songs/library/blues/st-louis-blues.mid +0 -0
  183. package/songs/library/blues/stormy-monday.json +13 -0
  184. package/songs/library/blues/stormy-monday.mid +0 -0
  185. package/songs/library/blues/sweet-home-chicago.json +14 -0
  186. package/songs/library/blues/sweet-home-chicago.mid +0 -0
  187. package/songs/library/blues/the-thrill-is-gone.json +17 -0
  188. package/songs/library/blues/the-thrill-is-gone.mid +0 -0
  189. package/songs/library/classical/bach-prelude-c-major-bwv846.json +37 -0
  190. package/songs/library/classical/bach-prelude-c-major-bwv846.mid +0 -0
  191. package/songs/library/classical/chopin-nocturne-op9-no2.json +36 -0
  192. package/songs/library/classical/chopin-nocturne-op9-no2.mid +0 -0
  193. package/songs/library/classical/chopin-prelude-e-minor.json +35 -0
  194. package/songs/library/classical/chopin-prelude-e-minor.mid +0 -0
  195. package/songs/library/classical/clair-de-lune.json +37 -0
  196. package/songs/library/classical/clair-de-lune.mid +0 -0
  197. package/songs/library/classical/debussy-arabesque-no1.json +35 -0
  198. package/songs/library/classical/debussy-arabesque-no1.mid +0 -0
  199. package/songs/library/classical/fur-elise.json +35 -0
  200. package/songs/library/classical/fur-elise.mid +0 -0
  201. package/songs/library/classical/mozart-k545-mvt1.json +35 -0
  202. package/songs/library/classical/mozart-k545-mvt1.mid +0 -0
  203. package/songs/library/classical/pathetique-mvt2.json +36 -0
  204. package/songs/library/classical/pathetique-mvt2.mid +0 -0
  205. package/songs/library/classical/satie-gymnopedie-no1.json +36 -0
  206. package/songs/library/classical/satie-gymnopedie-no1.mid +0 -0
  207. package/songs/library/classical/schumann-traumerei.json +36 -0
  208. package/songs/library/classical/schumann-traumerei.mid +0 -0
  209. package/songs/library/film/cinema-paradiso.json +14 -0
  210. package/songs/library/film/cinema-paradiso.mid +0 -0
  211. package/songs/library/film/comptine-dun-autre-ete.json +17 -0
  212. package/songs/library/film/comptine-dun-autre-ete.mid +0 -0
  213. package/songs/library/film/forrest-gump.json +14 -0
  214. package/songs/library/film/forrest-gump.mid +0 -0
  215. package/songs/library/film/hedwigs-theme.json +14 -0
  216. package/songs/library/film/hedwigs-theme.mid +0 -0
  217. package/songs/library/film/mia-and-sebastians-theme.json +14 -0
  218. package/songs/library/film/mia-and-sebastians-theme.mid +0 -0
  219. package/songs/library/film/moon-river.json +14 -0
  220. package/songs/library/film/moon-river.mid +0 -0
  221. package/songs/library/film/my-heart-will-go-on.json +14 -0
  222. package/songs/library/film/my-heart-will-go-on.mid +0 -0
  223. package/songs/library/film/nuvole-bianche.json +14 -0
  224. package/songs/library/film/nuvole-bianche.mid +0 -0
  225. package/songs/library/film/pink-panther.json +14 -0
  226. package/songs/library/film/pink-panther.mid +0 -0
  227. package/songs/library/film/schindlers-list-theme.json +14 -0
  228. package/songs/library/film/schindlers-list-theme.mid +0 -0
  229. package/songs/library/folk/amazing-grace.json +14 -0
  230. package/songs/library/folk/amazing-grace.mid +0 -0
  231. package/songs/library/folk/auld-lang-syne.json +14 -0
  232. package/songs/library/folk/auld-lang-syne.mid +0 -0
  233. package/songs/library/folk/danny-boy.json +14 -0
  234. package/songs/library/folk/danny-boy.mid +0 -0
  235. package/songs/library/folk/greensleeves.json +17 -0
  236. package/songs/library/folk/greensleeves.mid +0 -0
  237. package/songs/library/folk/house-of-the-rising-sun.json +14 -0
  238. package/songs/library/folk/house-of-the-rising-sun.mid +0 -0
  239. package/songs/library/folk/sakura-sakura.json +14 -0
  240. package/songs/library/folk/sakura-sakura.mid +0 -0
  241. package/songs/library/folk/scarborough-fair.json +14 -0
  242. package/songs/library/folk/scarborough-fair.mid +0 -0
  243. package/songs/library/folk/shenandoah.json +14 -0
  244. package/songs/library/folk/shenandoah.mid +0 -0
  245. package/songs/library/folk/simple-gifts.json +14 -0
  246. package/songs/library/folk/simple-gifts.mid +0 -0
  247. package/songs/library/folk/the-water-is-wide.json +14 -0
  248. package/songs/library/folk/the-water-is-wide.mid +0 -0
  249. package/songs/library/jazz/all-the-things-you-are.json +13 -0
  250. package/songs/library/jazz/all-the-things-you-are.mid +0 -0
  251. package/songs/library/jazz/autumn-leaves.json +17 -0
  252. package/songs/library/jazz/autumn-leaves.mid +0 -0
  253. package/songs/library/jazz/blue-bossa.json +14 -0
  254. package/songs/library/jazz/blue-bossa.mid +0 -0
  255. package/songs/library/jazz/fly-me-to-the-moon.json +14 -0
  256. package/songs/library/jazz/fly-me-to-the-moon.mid +0 -0
  257. package/songs/library/jazz/georgia-on-my-mind.json +14 -0
  258. package/songs/library/jazz/georgia-on-my-mind.mid +0 -0
  259. package/songs/library/jazz/misty.json +14 -0
  260. package/songs/library/jazz/misty.mid +0 -0
  261. package/songs/library/jazz/my-funny-valentine.json +14 -0
  262. package/songs/library/jazz/my-funny-valentine.mid +0 -0
  263. package/songs/library/jazz/round-midnight.json +14 -0
  264. package/songs/library/jazz/round-midnight.mid +0 -0
  265. package/songs/library/jazz/summertime.json +14 -0
  266. package/songs/library/jazz/summertime.mid +0 -0
  267. package/songs/library/jazz/take-the-a-train.json +14 -0
  268. package/songs/library/jazz/take-the-a-train.mid +0 -0
  269. package/songs/library/latin/agua-de-beber.json +14 -0
  270. package/songs/library/latin/agua-de-beber.mid +0 -0
  271. package/songs/library/latin/besame-mucho.json +14 -0
  272. package/songs/library/latin/besame-mucho.mid +0 -0
  273. package/songs/library/latin/black-orpheus.json +14 -0
  274. package/songs/library/latin/black-orpheus.mid +0 -0
  275. package/songs/library/latin/corcovado.json +14 -0
  276. package/songs/library/latin/corcovado.mid +0 -0
  277. package/songs/library/latin/desafinado.json +14 -0
  278. package/songs/library/latin/desafinado.mid +0 -0
  279. package/songs/library/latin/el-condor-pasa.json +14 -0
  280. package/songs/library/latin/el-condor-pasa.mid +0 -0
  281. package/songs/library/latin/girl-from-ipanema.json +17 -0
  282. package/songs/library/latin/girl-from-ipanema.mid +0 -0
  283. package/songs/library/latin/mas-que-nada.json +14 -0
  284. package/songs/library/latin/mas-que-nada.mid +0 -0
  285. package/songs/library/latin/perfidia.json +14 -0
  286. package/songs/library/latin/perfidia.mid +0 -0
  287. package/songs/library/latin/wave.json +14 -0
  288. package/songs/library/latin/wave.mid +0 -0
  289. package/songs/library/new-age/divenire.json +14 -0
  290. package/songs/library/new-age/divenire.mid +0 -0
  291. package/songs/library/new-age/experience.json +14 -0
  292. package/songs/library/new-age/experience.mid +0 -0
  293. package/songs/library/new-age/kiss-the-rain.json +14 -0
  294. package/songs/library/new-age/kiss-the-rain.mid +0 -0
  295. package/songs/library/new-age/may-be.json +13 -0
  296. package/songs/library/new-age/may-be.mid +0 -0
  297. package/songs/library/new-age/metamorphosis-two.json +14 -0
  298. package/songs/library/new-age/metamorphosis-two.mid +0 -0
  299. package/songs/library/new-age/nuvole-bianche-na.json +14 -0
  300. package/songs/library/new-age/nuvole-bianche-na.mid +0 -0
  301. package/songs/library/new-age/opening-glassworks.json +14 -0
  302. package/songs/library/new-age/opening-glassworks.mid +0 -0
  303. package/songs/library/new-age/river-flows-in-you.json +17 -0
  304. package/songs/library/new-age/river-flows-in-you.mid +0 -0
  305. package/songs/library/new-age/una-mattina.json +14 -0
  306. package/songs/library/new-age/una-mattina.mid +0 -0
  307. package/songs/library/new-age/watermark.json +14 -0
  308. package/songs/library/new-age/watermark.mid +0 -0
  309. package/songs/library/pop/a-thousand-years.json +14 -0
  310. package/songs/library/pop/a-thousand-years.mid +0 -0
  311. package/songs/library/pop/all-of-me.json +14 -0
  312. package/songs/library/pop/all-of-me.mid +0 -0
  313. package/songs/library/pop/bohemian-rhapsody.json +14 -0
  314. package/songs/library/pop/bohemian-rhapsody.mid +0 -0
  315. package/songs/library/pop/clocks.json +14 -0
  316. package/songs/library/pop/clocks.mid +0 -0
  317. package/songs/library/pop/imagine.json +17 -0
  318. package/songs/library/pop/imagine.mid +0 -0
  319. package/songs/library/pop/let-it-be.json +14 -0
  320. package/songs/library/pop/let-it-be.mid +0 -0
  321. package/songs/library/pop/piano-man.json +14 -0
  322. package/songs/library/pop/piano-man.mid +0 -0
  323. package/songs/library/pop/someone-like-you.json +14 -0
  324. package/songs/library/pop/someone-like-you.mid +0 -0
  325. package/songs/library/pop/someone-you-loved.json +14 -0
  326. package/songs/library/pop/someone-you-loved.mid +0 -0
  327. package/songs/library/pop/viva-la-vida.json +14 -0
  328. package/songs/library/pop/viva-la-vida.mid +0 -0
  329. package/songs/library/ragtime/bethena.json +14 -0
  330. package/songs/library/ragtime/bethena.mid +0 -0
  331. package/songs/library/ragtime/elite-syncopations.json +13 -0
  332. package/songs/library/ragtime/elite-syncopations.mid +0 -0
  333. package/songs/library/ragtime/gladiolus-rag.json +13 -0
  334. package/songs/library/ragtime/gladiolus-rag.mid +0 -0
  335. package/songs/library/ragtime/maple-leaf-rag.json +13 -0
  336. package/songs/library/ragtime/maple-leaf-rag.mid +0 -0
  337. package/songs/library/ragtime/peacherine-rag.json +13 -0
  338. package/songs/library/ragtime/peacherine-rag.mid +0 -0
  339. package/songs/library/ragtime/pineapple-rag.json +13 -0
  340. package/songs/library/ragtime/pineapple-rag.mid +0 -0
  341. package/songs/library/ragtime/solace.json +14 -0
  342. package/songs/library/ragtime/solace.mid +0 -0
  343. package/songs/library/ragtime/the-easy-winners.json +13 -0
  344. package/songs/library/ragtime/the-easy-winners.mid +0 -0
  345. package/songs/library/ragtime/the-entertainer.json +17 -0
  346. package/songs/library/ragtime/the-entertainer.mid +0 -0
  347. package/songs/library/ragtime/weeping-willow.json +14 -0
  348. package/songs/library/ragtime/weeping-willow.mid +0 -0
  349. package/songs/library/rnb/fallin.json +17 -0
  350. package/songs/library/rnb/fallin.mid +0 -0
  351. package/songs/library/rnb/halo.json +14 -0
  352. package/songs/library/rnb/halo.mid +0 -0
  353. package/songs/library/rnb/i-will-always-love-you.json +14 -0
  354. package/songs/library/rnb/i-will-always-love-you.mid +0 -0
  355. package/songs/library/rnb/if-i-aint-got-you.json +17 -0
  356. package/songs/library/rnb/if-i-aint-got-you.mid +0 -0
  357. package/songs/library/rnb/isnt-she-lovely.json +17 -0
  358. package/songs/library/rnb/isnt-she-lovely.mid +0 -0
  359. package/songs/library/rnb/killing-me-softly.json +14 -0
  360. package/songs/library/rnb/killing-me-softly.mid +0 -0
  361. package/songs/library/rnb/no-one.json +14 -0
  362. package/songs/library/rnb/no-one.mid +0 -0
  363. package/songs/library/rnb/ordinary-people.json +14 -0
  364. package/songs/library/rnb/ordinary-people.mid +0 -0
  365. package/songs/library/rnb/ribbon-in-the-sky.json +14 -0
  366. package/songs/library/rnb/ribbon-in-the-sky.mid +0 -0
  367. package/songs/library/rnb/superstition.json +17 -0
  368. package/songs/library/rnb/superstition.mid +0 -0
  369. package/songs/library/rock/baba-oriley.json +14 -0
  370. package/songs/library/rock/baba-oriley.mid +0 -0
  371. package/songs/library/rock/bennie-and-the-jets.json +14 -0
  372. package/songs/library/rock/bennie-and-the-jets.mid +0 -0
  373. package/songs/library/rock/dont-stop-believin.json +14 -0
  374. package/songs/library/rock/dont-stop-believin.mid +0 -0
  375. package/songs/library/rock/dream-on.json +14 -0
  376. package/songs/library/rock/dream-on.mid +0 -0
  377. package/songs/library/rock/layla-unplugged.json +14 -0
  378. package/songs/library/rock/layla-unplugged.mid +0 -0
  379. package/songs/library/rock/november-rain.json +15 -0
  380. package/songs/library/rock/november-rain.mid +0 -0
  381. package/songs/library/rock/rocket-man.json +14 -0
  382. package/songs/library/rock/rocket-man.mid +0 -0
  383. package/songs/library/rock/stairway-to-heaven.json +14 -0
  384. package/songs/library/rock/stairway-to-heaven.mid +0 -0
  385. package/songs/library/rock/tiny-dancer.json +14 -0
  386. package/songs/library/rock/tiny-dancer.mid +0 -0
  387. package/songs/library/rock/your-song.json +17 -0
  388. package/songs/library/rock/your-song.mid +0 -0
  389. package/songs/library/soul/a-change-is-gonna-come.json +14 -0
  390. package/songs/library/soul/a-change-is-gonna-come.mid +0 -0
  391. package/songs/library/soul/aint-no-sunshine.json +14 -0
  392. package/songs/library/soul/aint-no-sunshine.mid +0 -0
  393. package/songs/library/soul/dock-of-the-bay.json +13 -0
  394. package/songs/library/soul/dock-of-the-bay.mid +0 -0
  395. package/songs/library/soul/i-got-you.json +14 -0
  396. package/songs/library/soul/i-got-you.mid +0 -0
  397. package/songs/library/soul/lean-on-me.json +17 -0
  398. package/songs/library/soul/lean-on-me.mid +0 -0
  399. package/songs/library/soul/lets-stay-together.json +14 -0
  400. package/songs/library/soul/lets-stay-together.mid +0 -0
  401. package/songs/library/soul/my-girl.json +14 -0
  402. package/songs/library/soul/my-girl.mid +0 -0
  403. package/songs/library/soul/respect.json +14 -0
  404. package/songs/library/soul/respect.mid +0 -0
  405. package/songs/library/soul/stand-by-me.json +14 -0
  406. package/songs/library/soul/stand-by-me.mid +0 -0
  407. package/songs/library/soul/whats-going-on.json +14 -0
  408. package/songs/library/soul/whats-going-on.mid +0 -0
package/dist/smoke.js ADDED
@@ -0,0 +1,512 @@
1
+ // ─── pianoai: Smoke Test ─────────────────────────────────────────────────────
2
+ //
3
+ // Quick integration smoke test — no MIDI hardware needed.
4
+ // Verifies: ai-music-sheets loads, note parser works, sessions run with mock,
5
+ // teaching hooks fire, key moments detected, voice/aside hooks produce output,
6
+ // speed control works, progress fires, safe parsing collects warnings,
7
+ // sing-along converts notes and produces blocking directives,
8
+ // MIDI parsing, position tracking, PlaybackController, sing-on-MIDI,
9
+ // voice filters, and live MIDI feedback.
10
+ //
11
+ // Usage: pnpm smoke (or: node --import tsx src/smoke.ts)
12
+ // ─────────────────────────────────────────────────────────────────────────────
13
+ import { getAllSongs, getSong, getStats, searchSongs, initializeRegistry, } from "./songs/index.js";
14
+ import { createSession } from "./session.js";
15
+ import { createMockVmpkConnector } from "./vmpk.js";
16
+ import { parseNoteToMidi, midiToNoteName, safeParseNoteToken } from "./note-parser.js";
17
+ import { createRecordingTeachingHook, createVoiceTeachingHook, createAsideTeachingHook, createSingAlongHook, createLiveFeedbackHook, composeTeachingHooks, detectKeyMoments, } from "./teaching.js";
18
+ import { noteToSingable, measureToSingableText } from "./note-parser.js";
19
+ import { parseMidiBuffer } from "./midi/parser.js";
20
+ import { PositionTracker } from "./playback/position.js";
21
+ import { PlaybackController } from "./playback/controls.js";
22
+ import { createSingOnMidiHook, midiNoteToSingable, filterClusterForVoice } from "./teaching/sing-on-midi.js";
23
+ import { createLiveMidiFeedbackHook } from "./teaching/live-midi-feedback.js";
24
+ import { writeMidi } from "midi-file";
25
+ let passed = 0;
26
+ let failed = 0;
27
+ const pending = [];
28
+ function test(name, fn) {
29
+ try {
30
+ const result = fn();
31
+ if (result instanceof Promise) {
32
+ pending.push(result
33
+ .then(() => {
34
+ passed++;
35
+ console.log(` ✓ ${name}`);
36
+ })
37
+ .catch((err) => {
38
+ failed++;
39
+ console.log(` ✗ ${name}: ${err}`);
40
+ }));
41
+ }
42
+ else {
43
+ passed++;
44
+ console.log(` ✓ ${name}`);
45
+ }
46
+ }
47
+ catch (err) {
48
+ failed++;
49
+ console.log(` ✗ ${name}: ${err}`);
50
+ }
51
+ }
52
+ function assert(condition, msg) {
53
+ if (!condition)
54
+ throw new Error(`Assertion failed: ${msg}`);
55
+ }
56
+ console.log("\n pianoai smoke test\n");
57
+ // ─── Initialize song registry from builtin JSON files ───────────────────────
58
+ import { dirname, join } from "node:path";
59
+ import { fileURLToPath } from "node:url";
60
+ const __dirname = dirname(fileURLToPath(import.meta.url));
61
+ const builtinDir = join(__dirname, "..", "songs", "builtin");
62
+ initializeRegistry(builtinDir);
63
+ // ─── Test 1: song library loads ─────────────────────────────────────────────
64
+ console.log("song library integration:");
65
+ test("registry loads 100 songs", () => {
66
+ assert(getAllSongs().length >= 100, `expected 100+ songs, got ${getAllSongs().length}`);
67
+ });
68
+ test("all 10 genres covered", () => {
69
+ const stats = getStats();
70
+ const covered = Object.values(stats.byGenre).filter((n) => n > 0).length;
71
+ assert(covered === 10, `expected 10 genres, got ${covered}`);
72
+ });
73
+ test("getSong finds moonlight sonata", () => {
74
+ const song = getSong("moonlight-sonata-mvt1");
75
+ assert(song !== undefined, "song not found");
76
+ assert(song.genre === "classical", "wrong genre");
77
+ });
78
+ test("searchSongs by genre works", () => {
79
+ const results = searchSongs({ genre: "jazz" });
80
+ assert(results.length >= 10, `expected 10+ jazz songs, got ${results.length}`);
81
+ assert(results.some(s => s.id === "autumn-leaves"), "autumn-leaves should be in jazz results");
82
+ });
83
+ // ─── Test 2: Note parser ────────────────────────────────────────────────────
84
+ console.log("\nNote parser:");
85
+ test("C4 = MIDI 60", () => {
86
+ assert(parseNoteToMidi("C4") === 60, "C4 should be 60");
87
+ });
88
+ test("A4 = MIDI 69", () => {
89
+ assert(parseNoteToMidi("A4") === 69, "A4 should be 69");
90
+ });
91
+ test("MIDI 60 = C4", () => {
92
+ assert(midiToNoteName(60) === "C4", "60 should be C4");
93
+ });
94
+ test("round-trip: C#4 -> 61 -> C#4", () => {
95
+ const midi = parseNoteToMidi("C#4");
96
+ assert(midi === 61, "C#4 should be 61");
97
+ assert(midiToNoteName(midi) === "C#4", "61 should be C#4");
98
+ });
99
+ test("safe parse returns null + warning for bad token", () => {
100
+ const warnings = [];
101
+ const result = safeParseNoteToken("GARBAGE:q", 120, "test", warnings);
102
+ assert(result === null, "should return null for bad token");
103
+ assert(warnings.length === 1, "should collect 1 warning");
104
+ });
105
+ // ─── Test 3: Session engine ─────────────────────────────────────────────────
106
+ console.log("\nSession engine:");
107
+ test("creates session in loaded state", () => {
108
+ const mock = createMockVmpkConnector();
109
+ const sc = createSession(getSong("let-it-be"), mock);
110
+ assert(sc.state === "loaded", "should be loaded");
111
+ });
112
+ test("plays full song through mock", async () => {
113
+ const mock = createMockVmpkConnector();
114
+ const song = getSong("basic-12-bar-blues");
115
+ const sc = createSession(song, mock);
116
+ await mock.connect();
117
+ await sc.play();
118
+ assert(sc.state === "finished", `expected finished, got ${sc.state}`);
119
+ assert(sc.session.measuresPlayed === 12, "12 measures");
120
+ });
121
+ test("measure mode plays one and pauses", async () => {
122
+ const mock = createMockVmpkConnector();
123
+ const song = getSong("autumn-leaves");
124
+ const sc = createSession(song, mock, { mode: "measure" });
125
+ await mock.connect();
126
+ await sc.play();
127
+ assert(sc.state === "paused", `expected paused, got ${sc.state}`);
128
+ assert(sc.session.measuresPlayed === 1, "1 measure");
129
+ });
130
+ // ─── Test 4: Speed + progress ───────────────────────────────────────────────
131
+ console.log("\nSpeed + progress:");
132
+ test("speed multiplier affects effective tempo", () => {
133
+ const mock = createMockVmpkConnector();
134
+ const song = getSong("basic-12-bar-blues");
135
+ const sc = createSession(song, mock, { speed: 0.5 });
136
+ assert(sc.effectiveTempo() === song.tempo * 0.5, "should be half tempo");
137
+ });
138
+ test("progress fires during playback", async () => {
139
+ const mock = createMockVmpkConnector();
140
+ const song = getSong("basic-12-bar-blues");
141
+ const events = [];
142
+ const sc = createSession(song, mock, {
143
+ onProgress: (p) => events.push({ ...p }),
144
+ progressInterval: 0,
145
+ });
146
+ await mock.connect();
147
+ await sc.play();
148
+ assert(events.length === 12, `expected 12 progress events, got ${events.length}`);
149
+ assert(events[11].percent === "100%", "last event should be 100%");
150
+ });
151
+ // ─── Test 5: Teaching hooks ─────────────────────────────────────────────────
152
+ console.log("\nTeaching hooks:");
153
+ test("detectKeyMoments finds bar 1 in moonlight", () => {
154
+ const song = getSong("moonlight-sonata-mvt1");
155
+ const moments = detectKeyMoments(song, 1);
156
+ assert(moments.length > 0, "should find key moment at bar 1");
157
+ });
158
+ test("recording hook captures events during playback", async () => {
159
+ const mock = createMockVmpkConnector();
160
+ const hook = createRecordingTeachingHook();
161
+ const song = getSong("let-it-be");
162
+ const sc = createSession(song, mock, { teachingHook: hook });
163
+ await mock.connect();
164
+ await sc.play();
165
+ const starts = hook.events.filter((e) => e.type === "measure-start");
166
+ assert(starts.length === 8, `expected 8 measure-start events, got ${starts.length}`);
167
+ });
168
+ test("song-complete fires after full playback", async () => {
169
+ const mock = createMockVmpkConnector();
170
+ const hook = createRecordingTeachingHook();
171
+ const song = getSong("basic-12-bar-blues");
172
+ const sc = createSession(song, mock, { teachingHook: hook });
173
+ await mock.connect();
174
+ await sc.play();
175
+ const complete = hook.events.filter((e) => e.type === "song-complete");
176
+ assert(complete.length === 1, "should fire song-complete once");
177
+ });
178
+ // ─── Test 6: Voice + aside hooks ────────────────────────────────────────────
179
+ console.log("\nVoice + aside hooks:");
180
+ test("voice hook produces directives during playback", async () => {
181
+ const mock = createMockVmpkConnector();
182
+ const directives = [];
183
+ const voiceHook = createVoiceTeachingHook(async (d) => { directives.push(d); });
184
+ const song = getSong("moonlight-sonata-mvt1");
185
+ const sc = createSession(song, mock, { teachingHook: voiceHook });
186
+ await mock.connect();
187
+ await sc.play();
188
+ assert(directives.length > 0, "should produce voice directives");
189
+ const completion = directives.find((d) => d.text.includes("Great work"));
190
+ assert(completion !== undefined, "should have completion directive");
191
+ });
192
+ test("aside hook produces directives during playback", async () => {
193
+ const mock = createMockVmpkConnector();
194
+ const directives = [];
195
+ const asideHook = createAsideTeachingHook(async (d) => { directives.push(d); });
196
+ const song = getSong("moonlight-sonata-mvt1");
197
+ const sc = createSession(song, mock, { teachingHook: asideHook });
198
+ await mock.connect();
199
+ await sc.play();
200
+ assert(directives.length > 0, "should produce aside directives");
201
+ assert(directives[0].tags.includes("piano-teacher"), "should have piano-teacher tag");
202
+ });
203
+ test("composed hooks dispatch to both voice and aside", async () => {
204
+ const mock = createMockVmpkConnector();
205
+ const voiceD = [];
206
+ const asideD = [];
207
+ const composed = composeTeachingHooks(createVoiceTeachingHook(async (d) => { voiceD.push(d); }), createAsideTeachingHook(async (d) => { asideD.push(d); }));
208
+ const song = getSong("let-it-be");
209
+ const sc = createSession(song, mock, { teachingHook: composed });
210
+ await mock.connect();
211
+ await sc.play();
212
+ assert(voiceD.length > 0, "voice should receive events");
213
+ assert(asideD.length > 0, "aside should receive events");
214
+ });
215
+ // ─── Test 7: Sing-along ─────────────────────────────────────────────────────
216
+ console.log("\nSing-along:");
217
+ test("noteToSingable converts C4 to note name", () => {
218
+ assert(noteToSingable("C4", "note-names") === "C", "C4 → C");
219
+ });
220
+ test("noteToSingable converts C4 to solfege", () => {
221
+ assert(noteToSingable("C4", "solfege") === "Do", "C4 → Do");
222
+ });
223
+ test("measureToSingableText produces singable output", () => {
224
+ const result = measureToSingableText({ rightHand: "C4:q E4:q G4:q", leftHand: "C3:h" }, { mode: "note-names", hand: "right" });
225
+ assert(result === "C... E... G", `expected "C... E... G", got "${result}"`);
226
+ });
227
+ test("sing-along hook produces blocking directives", async () => {
228
+ const directives = [];
229
+ const song = getSong("let-it-be");
230
+ const hook = createSingAlongHook(async (d) => { directives.push(d); }, song);
231
+ const mock = createMockVmpkConnector();
232
+ const sc = createSession(song, mock, { teachingHook: hook });
233
+ await mock.connect();
234
+ await sc.play();
235
+ assert(directives.length > 0, "should produce directives");
236
+ assert(directives[0].blocking === true, "first directive should be blocking");
237
+ });
238
+ test("composed sing-along + voice hooks both fire", async () => {
239
+ const singD = [];
240
+ const voiceD = [];
241
+ const song = getSong("let-it-be");
242
+ const composed = composeTeachingHooks(createSingAlongHook(async (d) => { singD.push(d); }, song), createVoiceTeachingHook(async (d) => { voiceD.push(d); }));
243
+ const mock = createMockVmpkConnector();
244
+ const sc = createSession(song, mock, { teachingHook: composed });
245
+ await mock.connect();
246
+ await sc.play();
247
+ assert(singD.length > 0, "sing-along should receive events");
248
+ assert(voiceD.length > 0, "voice should receive events");
249
+ });
250
+ // ─── Test 8: SyncMode ────────────────────────────────────────────────────────
251
+ console.log("\nSyncMode:");
252
+ test("concurrent sync completes without error", async () => {
253
+ const mock = createMockVmpkConnector();
254
+ const song = getSong("let-it-be");
255
+ const hook = createRecordingTeachingHook();
256
+ const sc = createSession(song, mock, { syncMode: "concurrent", teachingHook: hook });
257
+ await mock.connect();
258
+ await sc.play();
259
+ assert(sc.session.measuresPlayed === 8, "should play 8 measures");
260
+ assert(hook.events.filter(e => e.type === "measure-start").length === 8, "8 measure-start events");
261
+ });
262
+ test("before sync completes without error", async () => {
263
+ const mock = createMockVmpkConnector();
264
+ const song = getSong("let-it-be");
265
+ const hook = createRecordingTeachingHook();
266
+ const sc = createSession(song, mock, { syncMode: "before", teachingHook: hook });
267
+ await mock.connect();
268
+ await sc.play();
269
+ assert(sc.session.measuresPlayed === 8, "should play 8 measures");
270
+ });
271
+ // ─── Test 9: Live Feedback Hook ──────────────────────────────────────────────
272
+ console.log("\nLive feedback:");
273
+ test("live feedback hook fires during full playback", async () => {
274
+ const song = getSong("moonlight-sonata-mvt1");
275
+ const voiceD = [];
276
+ const asideD = [];
277
+ const hook = createLiveFeedbackHook(async (d) => { voiceD.push(d); }, async (d) => { asideD.push(d); }, song, { voiceInterval: 4 });
278
+ const mock = createMockVmpkConnector();
279
+ const sc = createSession(song, mock, { teachingHook: hook });
280
+ await mock.connect();
281
+ await sc.play();
282
+ assert(voiceD.length > 0, "should produce voice directives");
283
+ assert(asideD.length > 0, "should produce aside directives");
284
+ });
285
+ test("composed sing-along + live feedback fires", async () => {
286
+ const song = getSong("let-it-be");
287
+ const singD = [];
288
+ const feedbackVoiceD = [];
289
+ const feedbackAsideD = [];
290
+ const composed = composeTeachingHooks(createSingAlongHook(async (d) => { singD.push(d); }, song), createLiveFeedbackHook(async (d) => { feedbackVoiceD.push(d); }, async (d) => { feedbackAsideD.push(d); }, song, { voiceInterval: 4 }));
291
+ const mock = createMockVmpkConnector();
292
+ const sc = createSession(song, mock, { teachingHook: composed, syncMode: "concurrent" });
293
+ await mock.connect();
294
+ await sc.play();
295
+ assert(singD.length > 0, "sing-along should fire");
296
+ assert(feedbackVoiceD.length > 0 || feedbackAsideD.length > 0, "feedback should fire");
297
+ });
298
+ // ─── MIDI Helpers ──────────────────────────────────────────────────────────
299
+ function buildSmokeMidi(notes, bpm = 120, ticksPerBeat = 480) {
300
+ const usPerBeat = Math.round(60_000_000 / bpm);
301
+ const events = [];
302
+ events.push({ deltaTime: 0, type: "setTempo", meta: true, microsecondsPerBeat: usPerBeat });
303
+ const raw = [];
304
+ for (const n of notes) {
305
+ raw.push({ tick: n.startTick, event: { deltaTime: 0, type: "noteOn", channel: 0, noteNumber: n.note, velocity: n.velocity } });
306
+ raw.push({ tick: n.endTick, event: { deltaTime: 0, type: "noteOff", channel: 0, noteNumber: n.note, velocity: 0 } });
307
+ }
308
+ raw.sort((a, b) => a.tick - b.tick);
309
+ let prevTick = 0;
310
+ for (const r of raw) {
311
+ r.event.deltaTime = r.tick - prevTick;
312
+ prevTick = r.tick;
313
+ events.push(r.event);
314
+ }
315
+ events.push({ deltaTime: 0, type: "endOfTrack", meta: true });
316
+ return new Uint8Array(writeMidi({
317
+ header: { format: 0, numTracks: 1, ticksPerBeat },
318
+ tracks: [events],
319
+ }));
320
+ }
321
+ function createSmokeMockConnector() {
322
+ return {
323
+ async connect() { },
324
+ async disconnect() { },
325
+ status() { return "connected"; },
326
+ listPorts() { return ["Mock"]; },
327
+ noteOn(_n, _v, _c) { },
328
+ noteOff(_n, _c) { },
329
+ allNotesOff(_c) { },
330
+ async playNote(_m) { },
331
+ };
332
+ }
333
+ // ─── Test 10: MIDI file parsing ────────────────────────────────────────────
334
+ console.log("\nMIDI file parsing:");
335
+ test("parseMidiBuffer extracts note events", () => {
336
+ const buf = buildSmokeMidi([
337
+ { note: 60, velocity: 100, startTick: 0, endTick: 480 },
338
+ { note: 64, velocity: 90, startTick: 480, endTick: 960 },
339
+ ]);
340
+ const parsed = parseMidiBuffer(buf);
341
+ assert(parsed.events.length === 2, `expected 2 events, got ${parsed.events.length}`);
342
+ assert(parsed.events[0].note === 60, "first note should be 60");
343
+ assert(parsed.events[1].note === 64, "second note should be 64");
344
+ assert(parsed.bpm === 120, `expected 120 BPM, got ${parsed.bpm}`);
345
+ });
346
+ test("parseMidiBuffer computes duration", () => {
347
+ const buf = buildSmokeMidi([
348
+ { note: 60, velocity: 80, startTick: 0, endTick: 1920 },
349
+ ], 120, 480);
350
+ const parsed = parseMidiBuffer(buf);
351
+ // 1920 ticks at 480 ticks/beat at 120 BPM = 4 beats = 2 seconds
352
+ assert(parsed.durationSeconds > 1.5 && parsed.durationSeconds < 2.5, `expected ~2s duration, got ${parsed.durationSeconds}`);
353
+ });
354
+ // ─── Test 11: Position Tracker ─────────────────────────────────────────────
355
+ console.log("\nPosition tracker:");
356
+ test("PositionTracker computes measures from beats", () => {
357
+ const notes = [];
358
+ for (let i = 0; i < 8; i++) {
359
+ notes.push({ note: 60 + i, velocity: 80, startTick: i * 480, endTick: (i + 1) * 480 });
360
+ }
361
+ const buf = buildSmokeMidi(notes, 120, 480);
362
+ const parsed = parseMidiBuffer(buf);
363
+ const tracker = new PositionTracker(parsed);
364
+ assert(tracker.totalMeasures >= 2, `expected >= 2 measures, got ${tracker.totalMeasures}`);
365
+ });
366
+ test("snapshotAt returns measure 1 at time 0", () => {
367
+ const buf = buildSmokeMidi([{ note: 60, velocity: 80, startTick: 0, endTick: 480 }], 120, 480);
368
+ const parsed = parseMidiBuffer(buf);
369
+ const tracker = new PositionTracker(parsed);
370
+ const snap = tracker.snapshotAt(0);
371
+ assert(snap.measure === 1, `expected measure 1, got ${snap.measure}`);
372
+ assert(snap.bpm === 120, `expected 120 BPM, got ${snap.bpm}`);
373
+ });
374
+ test("timeForMeasure returns seek target", () => {
375
+ const buf = buildSmokeMidi([{ note: 60, velocity: 80, startTick: 0, endTick: 480 }], 120, 480);
376
+ const parsed = parseMidiBuffer(buf);
377
+ const tracker = new PositionTracker(parsed);
378
+ const t1 = tracker.timeForMeasure(1);
379
+ const t2 = tracker.timeForMeasure(2);
380
+ assert(Math.abs(t1) < 0.01, `measure 1 should start at ~0, got ${t1}`);
381
+ assert(Math.abs(t2 - 2.0) < 0.1, `measure 2 should start at ~2s, got ${t2}`);
382
+ });
383
+ test("eventsInMeasure partitions notes correctly", () => {
384
+ const notes = [];
385
+ for (let i = 0; i < 8; i++) {
386
+ notes.push({ note: 60 + i, velocity: 80, startTick: i * 480, endTick: (i + 1) * 480 });
387
+ }
388
+ const buf = buildSmokeMidi(notes, 120, 480);
389
+ const parsed = parseMidiBuffer(buf);
390
+ const tracker = new PositionTracker(parsed);
391
+ const m1 = tracker.eventsInMeasure(1);
392
+ assert(m1.length === 4, `expected 4 events in measure 1, got ${m1.length}`);
393
+ });
394
+ // ─── Test 12: PlaybackController ───────────────────────────────────────────
395
+ console.log("\nPlaybackController:");
396
+ test("PlaybackController emits noteOn events", async () => {
397
+ const buf = buildSmokeMidi([
398
+ { note: 60, velocity: 100, startTick: 0, endTick: 480 },
399
+ { note: 64, velocity: 90, startTick: 480, endTick: 960 },
400
+ ]);
401
+ const parsed = parseMidiBuffer(buf);
402
+ const connector = createSmokeMockConnector();
403
+ const controller = new PlaybackController(connector, parsed);
404
+ const noteOns = [];
405
+ controller.on("noteOn", (e) => { if (e.type === "noteOn")
406
+ noteOns.push(e.note); });
407
+ await controller.play({ speed: 100 });
408
+ assert(noteOns.length === 2, `expected 2 noteOn events, got ${noteOns.length}`);
409
+ assert(controller.state === "finished", `expected finished, got ${controller.state}`);
410
+ });
411
+ test("PlaybackController invokes teaching hook", async () => {
412
+ const buf = buildSmokeMidi([
413
+ { note: 60, velocity: 100, startTick: 0, endTick: 480 },
414
+ ]);
415
+ const parsed = parseMidiBuffer(buf);
416
+ const connector = createSmokeMockConnector();
417
+ const controller = new PlaybackController(connector, parsed);
418
+ const hook = createRecordingTeachingHook();
419
+ await controller.play({ speed: 100, teachingHook: hook });
420
+ const starts = hook.events.filter((e) => e.type === "measure-start");
421
+ assert(starts.length >= 1, `expected >= 1 measure-start, got ${starts.length}`);
422
+ const completions = hook.events.filter((e) => e.type === "song-complete");
423
+ assert(completions.length === 1, "should fire song-complete once");
424
+ });
425
+ // ─── Test 13: Sing-on-MIDI ─────────────────────────────────────────────────
426
+ console.log("\nSing-on-MIDI:");
427
+ test("midiNoteToSingable converts note-names", () => {
428
+ assert(midiNoteToSingable(60, "note-names") === "C4", "60 → C4");
429
+ assert(midiNoteToSingable(69, "note-names") === "A4", "69 → A4");
430
+ });
431
+ test("midiNoteToSingable converts solfege", () => {
432
+ assert(midiNoteToSingable(60, "solfege") === "Do", "60 → Do");
433
+ assert(midiNoteToSingable(64, "solfege") === "Mi", "64 → Mi");
434
+ });
435
+ test("createSingOnMidiHook produces directives", async () => {
436
+ const buf = buildSmokeMidi([
437
+ { note: 60, velocity: 100, startTick: 0, endTick: 480 },
438
+ { note: 64, velocity: 90, startTick: 480, endTick: 960 },
439
+ ]);
440
+ const parsed = parseMidiBuffer(buf);
441
+ const directives = [];
442
+ const hook = createSingOnMidiHook(async (d) => { directives.push(d); }, parsed, { mode: "note-names" });
443
+ await hook.onMeasureStart(1, undefined, undefined);
444
+ await hook.onMeasureStart(2, undefined, undefined);
445
+ assert(hook.directives.length === 2, `expected 2 directives, got ${hook.directives.length}`);
446
+ assert(hook.directives[0].text.includes("C4"), `first should contain C4, got ${hook.directives[0].text}`);
447
+ });
448
+ // ─── Test 14: Voice Filters ───────────────────────────────────────────────
449
+ console.log("\nVoice filters:");
450
+ test("melody-only picks highest note", () => {
451
+ const chord = [
452
+ { note: 48, velocity: 80, time: 0, duration: 0.5, channel: 0 },
453
+ { note: 60, velocity: 80, time: 0, duration: 0.5, channel: 0 },
454
+ { note: 72, velocity: 80, time: 0, duration: 0.5, channel: 0 },
455
+ ];
456
+ const filtered = filterClusterForVoice(chord, "melody-only");
457
+ assert(filtered.length === 1, `expected 1, got ${filtered.length}`);
458
+ assert(filtered[0].note === 72, `expected 72, got ${filtered[0].note}`);
459
+ });
460
+ test("harmony picks lowest note", () => {
461
+ const chord = [
462
+ { note: 48, velocity: 80, time: 0, duration: 0.5, channel: 0 },
463
+ { note: 72, velocity: 80, time: 0, duration: 0.5, channel: 0 },
464
+ ];
465
+ const filtered = filterClusterForVoice(chord, "harmony");
466
+ assert(filtered.length === 1, `expected 1, got ${filtered.length}`);
467
+ assert(filtered[0].note === 48, `expected 48, got ${filtered[0].note}`);
468
+ });
469
+ // ─── Test 15: Live MIDI Feedback ──────────────────────────────────────────
470
+ console.log("\nLive MIDI feedback:");
471
+ test("createLiveMidiFeedbackHook provides tracker", () => {
472
+ const buf = buildSmokeMidi([{ note: 60, velocity: 80, startTick: 0, endTick: 480 }], 120, 480);
473
+ const parsed = parseMidiBuffer(buf);
474
+ const hook = createLiveMidiFeedbackHook(async () => { }, async () => { }, parsed);
475
+ assert(hook.tracker instanceof PositionTracker, "should expose PositionTracker");
476
+ assert(hook.tracker.totalMeasures >= 1, "should have measures");
477
+ });
478
+ test("live feedback emits completion", async () => {
479
+ const buf = buildSmokeMidi([{ note: 60, velocity: 80, startTick: 0, endTick: 480 }], 120, 480);
480
+ const parsed = parseMidiBuffer(buf);
481
+ const voiceD = [];
482
+ const asideD = [];
483
+ const hook = createLiveMidiFeedbackHook(async (d) => { voiceD.push(d); }, async (d) => { asideD.push(d); }, parsed);
484
+ await hook.onSongComplete(10, "Smoke Song");
485
+ assert(voiceD.some(d => d.text.includes("Smoke Song")), "should mention song name");
486
+ assert(asideD.some(d => d.reason === "session-complete"), "should emit session-complete");
487
+ });
488
+ test("composed sing + live feedback on PlaybackController", async () => {
489
+ const buf = buildSmokeMidi([
490
+ { note: 60, velocity: 40, startTick: 0, endTick: 480 },
491
+ { note: 64, velocity: 110, startTick: 480, endTick: 960 },
492
+ ]);
493
+ const parsed = parseMidiBuffer(buf);
494
+ const connector = createSmokeMockConnector();
495
+ const controller = new PlaybackController(connector, parsed);
496
+ const singD = [];
497
+ const feedbackA = [];
498
+ const singHook = createSingOnMidiHook(async (d) => { singD.push(d); }, parsed, { mode: "solfege" });
499
+ const fbHook = createLiveMidiFeedbackHook(async () => { }, async (d) => { feedbackA.push(d); }, parsed, { voiceInterval: 100 });
500
+ const composed = composeTeachingHooks(singHook, fbHook);
501
+ await controller.play({ speed: 100, teachingHook: composed });
502
+ assert(singD.length > 0, "sing hook should produce directives");
503
+ });
504
+ // ─── Summary ────────────────────────────────────────────────────────────────
505
+ Promise.all(pending).then(() => {
506
+ console.log(`\n${"─".repeat(40)}`);
507
+ console.log(`Smoke: ${passed} passed, ${failed} failed`);
508
+ if (failed > 0)
509
+ process.exit(1);
510
+ console.log("All smoke tests passed\n");
511
+ });
512
+ //# sourceMappingURL=smoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"smoke.js","sourceRoot":"","sources":["../src/smoke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { type SongConfig } from "./schema.js";
2
+ /**
3
+ * Load and validate all song configs from a directory.
4
+ */
5
+ export declare function loadSongConfigs(dir: string): SongConfig[];
6
+ /**
7
+ * Load a single song config by ID from a directory.
8
+ */
9
+ export declare function loadSongConfig(id: string, dir: string): SongConfig;
10
+ /**
11
+ * List available config IDs (slugs) in a directory.
12
+ */
13
+ export declare function listConfigIds(dir: string): string[];
14
+ //# sourceMappingURL=loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/songs/config/loader.ts"],"names":[],"mappings":"AAQA,OAAO,EAAoB,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAEhE;;GAEG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,EAAE,CAwBzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAQlE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAKnD"}
@@ -0,0 +1,53 @@
1
+ // ─── Song Config Loader ──────────────────────────────────────────────────────
2
+ //
3
+ // Reads .json files from a config directory, validates each with Zod,
4
+ // and returns typed SongConfig objects.
5
+ // ─────────────────────────────────────────────────────────────────────────────
6
+ import { readdirSync, readFileSync, existsSync } from "node:fs";
7
+ import { join, basename } from "node:path";
8
+ import { SongConfigSchema } from "./schema.js";
9
+ /**
10
+ * Load and validate all song configs from a directory.
11
+ */
12
+ export function loadSongConfigs(dir) {
13
+ if (!existsSync(dir)) {
14
+ throw new Error(`Config directory not found: ${dir}`);
15
+ }
16
+ const files = readdirSync(dir).filter(f => f.endsWith(".json"));
17
+ const configs = [];
18
+ for (const file of files) {
19
+ const filePath = join(dir, file);
20
+ const raw = JSON.parse(readFileSync(filePath, "utf8"));
21
+ const result = SongConfigSchema.safeParse(raw);
22
+ if (!result.success) {
23
+ const issues = result.error.issues
24
+ .map(i => ` ${i.path.join(".")}: ${i.message}`)
25
+ .join("\n");
26
+ throw new Error(`Invalid config ${file}:\n${issues}`);
27
+ }
28
+ configs.push(result.data);
29
+ }
30
+ return configs;
31
+ }
32
+ /**
33
+ * Load a single song config by ID from a directory.
34
+ */
35
+ export function loadSongConfig(id, dir) {
36
+ const filePath = join(dir, `${id}.json`);
37
+ if (!existsSync(filePath)) {
38
+ throw new Error(`Config not found: ${filePath}`);
39
+ }
40
+ const raw = JSON.parse(readFileSync(filePath, "utf8"));
41
+ return SongConfigSchema.parse(raw);
42
+ }
43
+ /**
44
+ * List available config IDs (slugs) in a directory.
45
+ */
46
+ export function listConfigIds(dir) {
47
+ if (!existsSync(dir))
48
+ return [];
49
+ return readdirSync(dir)
50
+ .filter(f => f.endsWith(".json"))
51
+ .map(f => basename(f, ".json"));
52
+ }
53
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/songs/config/loader.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,EAAE;AACF,sEAAsE;AACtE,wCAAwC;AACxC,gFAAgF;AAEhF,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAChE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAmB,MAAM,aAAa,CAAC;AAEhE;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,GAAW;IACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,EAAE,CAAC,CAAC;IACxD,CAAC;IAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;IAChE,MAAM,OAAO,GAAiB,EAAE,CAAC;IAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,gBAAgB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAE/C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM;iBAC/B,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC;iBAC/C,IAAI,CAAC,IAAI,CAAC,CAAC;YACd,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,MAAM,MAAM,EAAE,CAAC,CAAC;QACxD,CAAC;QAED,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAAU,EAAE,GAAW;IACpD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACzC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,OAAO,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,OAAO,WAAW,CAAC,GAAG,CAAC;SACpB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;AACpC,CAAC"}