takomusic 1.2.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 (335) hide show
  1. package/LICENSE +661 -0
  2. package/README.md +230 -0
  3. package/dist/__tests__/checker.test.d.ts +2 -0
  4. package/dist/__tests__/checker.test.d.ts.map +1 -0
  5. package/dist/__tests__/checker.test.js +316 -0
  6. package/dist/__tests__/checker.test.js.map +1 -0
  7. package/dist/__tests__/compiler.test.d.ts +2 -0
  8. package/dist/__tests__/compiler.test.d.ts.map +1 -0
  9. package/dist/__tests__/compiler.test.js +260 -0
  10. package/dist/__tests__/compiler.test.js.map +1 -0
  11. package/dist/__tests__/generators.test.d.ts +2 -0
  12. package/dist/__tests__/generators.test.d.ts.map +1 -0
  13. package/dist/__tests__/generators.test.js +283 -0
  14. package/dist/__tests__/generators.test.js.map +1 -0
  15. package/dist/__tests__/interpreter.test.d.ts +2 -0
  16. package/dist/__tests__/interpreter.test.d.ts.map +1 -0
  17. package/dist/__tests__/interpreter.test.js +298 -0
  18. package/dist/__tests__/interpreter.test.js.map +1 -0
  19. package/dist/__tests__/lexer.test.d.ts +2 -0
  20. package/dist/__tests__/lexer.test.d.ts.map +1 -0
  21. package/dist/__tests__/lexer.test.js +89 -0
  22. package/dist/__tests__/lexer.test.js.map +1 -0
  23. package/dist/__tests__/parser.test.d.ts +2 -0
  24. package/dist/__tests__/parser.test.d.ts.map +1 -0
  25. package/dist/__tests__/parser.test.js +116 -0
  26. package/dist/__tests__/parser.test.js.map +1 -0
  27. package/dist/checker/checker.d.ts +37 -0
  28. package/dist/checker/checker.d.ts.map +1 -0
  29. package/dist/checker/checker.js +428 -0
  30. package/dist/checker/checker.js.map +1 -0
  31. package/dist/checker/index.d.ts +3 -0
  32. package/dist/checker/index.d.ts.map +1 -0
  33. package/dist/checker/index.js +2 -0
  34. package/dist/checker/index.js.map +1 -0
  35. package/dist/cli/commands/build.d.ts +2 -0
  36. package/dist/cli/commands/build.d.ts.map +1 -0
  37. package/dist/cli/commands/build.js +173 -0
  38. package/dist/cli/commands/build.js.map +1 -0
  39. package/dist/cli/commands/check.d.ts +2 -0
  40. package/dist/cli/commands/check.d.ts.map +1 -0
  41. package/dist/cli/commands/check.js +79 -0
  42. package/dist/cli/commands/check.js.map +1 -0
  43. package/dist/cli/commands/doctor.d.ts +2 -0
  44. package/dist/cli/commands/doctor.d.ts.map +1 -0
  45. package/dist/cli/commands/doctor.js +187 -0
  46. package/dist/cli/commands/doctor.js.map +1 -0
  47. package/dist/cli/commands/fmt.d.ts +2 -0
  48. package/dist/cli/commands/fmt.d.ts.map +1 -0
  49. package/dist/cli/commands/fmt.js +73 -0
  50. package/dist/cli/commands/fmt.js.map +1 -0
  51. package/dist/cli/commands/import.d.ts +2 -0
  52. package/dist/cli/commands/import.d.ts.map +1 -0
  53. package/dist/cli/commands/import.js +99 -0
  54. package/dist/cli/commands/import.js.map +1 -0
  55. package/dist/cli/commands/init.d.ts +2 -0
  56. package/dist/cli/commands/init.d.ts.map +1 -0
  57. package/dist/cli/commands/init.js +514 -0
  58. package/dist/cli/commands/init.js.map +1 -0
  59. package/dist/cli/commands/play.d.ts +2 -0
  60. package/dist/cli/commands/play.d.ts.map +1 -0
  61. package/dist/cli/commands/play.js +216 -0
  62. package/dist/cli/commands/play.js.map +1 -0
  63. package/dist/cli/commands/record.d.ts +2 -0
  64. package/dist/cli/commands/record.d.ts.map +1 -0
  65. package/dist/cli/commands/record.js +393 -0
  66. package/dist/cli/commands/record.js.map +1 -0
  67. package/dist/cli/commands/render.d.ts +2 -0
  68. package/dist/cli/commands/render.d.ts.map +1 -0
  69. package/dist/cli/commands/render.js +278 -0
  70. package/dist/cli/commands/render.js.map +1 -0
  71. package/dist/cli/index.d.ts +3 -0
  72. package/dist/cli/index.d.ts.map +1 -0
  73. package/dist/cli/index.js +93 -0
  74. package/dist/cli/index.js.map +1 -0
  75. package/dist/compiler/compiler.d.ts +12 -0
  76. package/dist/compiler/compiler.d.ts.map +1 -0
  77. package/dist/compiler/compiler.js +146 -0
  78. package/dist/compiler/compiler.js.map +1 -0
  79. package/dist/compiler/index.d.ts +2 -0
  80. package/dist/compiler/index.d.ts.map +1 -0
  81. package/dist/compiler/index.js +2 -0
  82. package/dist/compiler/index.js.map +1 -0
  83. package/dist/config/config.d.ts +43 -0
  84. package/dist/config/config.d.ts.map +1 -0
  85. package/dist/config/config.js +200 -0
  86. package/dist/config/config.js.map +1 -0
  87. package/dist/config/index.d.ts +2 -0
  88. package/dist/config/index.d.ts.map +1 -0
  89. package/dist/config/index.js +2 -0
  90. package/dist/config/index.js.map +1 -0
  91. package/dist/errors.d.ts +49 -0
  92. package/dist/errors.d.ts.map +1 -0
  93. package/dist/errors.js +168 -0
  94. package/dist/errors.js.map +1 -0
  95. package/dist/formatter/formatter.d.ts +13 -0
  96. package/dist/formatter/formatter.d.ts.map +1 -0
  97. package/dist/formatter/formatter.js +242 -0
  98. package/dist/formatter/formatter.js.map +1 -0
  99. package/dist/formatter/index.d.ts +2 -0
  100. package/dist/formatter/index.d.ts.map +1 -0
  101. package/dist/formatter/index.js +2 -0
  102. package/dist/formatter/index.js.map +1 -0
  103. package/dist/generators/index.d.ts +5 -0
  104. package/dist/generators/index.d.ts.map +1 -0
  105. package/dist/generators/index.js +5 -0
  106. package/dist/generators/index.js.map +1 -0
  107. package/dist/generators/midi.d.ts +3 -0
  108. package/dist/generators/midi.d.ts.map +1 -0
  109. package/dist/generators/midi.js +360 -0
  110. package/dist/generators/midi.js.map +1 -0
  111. package/dist/generators/musicxml.d.ts +3 -0
  112. package/dist/generators/musicxml.d.ts.map +1 -0
  113. package/dist/generators/musicxml.js +332 -0
  114. package/dist/generators/musicxml.js.map +1 -0
  115. package/dist/generators/tempo-midi.d.ts +3 -0
  116. package/dist/generators/tempo-midi.d.ts.map +1 -0
  117. package/dist/generators/tempo-midi.js +123 -0
  118. package/dist/generators/tempo-midi.js.map +1 -0
  119. package/dist/generators/vsqx.d.ts +3 -0
  120. package/dist/generators/vsqx.d.ts.map +1 -0
  121. package/dist/generators/vsqx.js +354 -0
  122. package/dist/generators/vsqx.js.map +1 -0
  123. package/dist/importers/index.d.ts +2 -0
  124. package/dist/importers/index.d.ts.map +1 -0
  125. package/dist/importers/index.js +3 -0
  126. package/dist/importers/index.js.map +1 -0
  127. package/dist/importers/musicxml.d.ts +4 -0
  128. package/dist/importers/musicxml.d.ts.map +1 -0
  129. package/dist/importers/musicxml.js +392 -0
  130. package/dist/importers/musicxml.js.map +1 -0
  131. package/dist/index.d.ts +11 -0
  132. package/dist/index.d.ts.map +1 -0
  133. package/dist/index.js +12 -0
  134. package/dist/index.js.map +1 -0
  135. package/dist/interpreter/builtins/algorithmic.d.ts +12 -0
  136. package/dist/interpreter/builtins/algorithmic.d.ts.map +1 -0
  137. package/dist/interpreter/builtins/algorithmic.js +244 -0
  138. package/dist/interpreter/builtins/algorithmic.js.map +1 -0
  139. package/dist/interpreter/builtins/audio.d.ts +10 -0
  140. package/dist/interpreter/builtins/audio.d.ts.map +1 -0
  141. package/dist/interpreter/builtins/audio.js +169 -0
  142. package/dist/interpreter/builtins/audio.js.map +1 -0
  143. package/dist/interpreter/builtins/core.d.ts +15 -0
  144. package/dist/interpreter/builtins/core.d.ts.map +1 -0
  145. package/dist/interpreter/builtins/core.js +265 -0
  146. package/dist/interpreter/builtins/core.js.map +1 -0
  147. package/dist/interpreter/builtins/dynamics.d.ts +8 -0
  148. package/dist/interpreter/builtins/dynamics.d.ts.map +1 -0
  149. package/dist/interpreter/builtins/dynamics.js +86 -0
  150. package/dist/interpreter/builtins/dynamics.js.map +1 -0
  151. package/dist/interpreter/builtins/effects.d.ts +16 -0
  152. package/dist/interpreter/builtins/effects.d.ts.map +1 -0
  153. package/dist/interpreter/builtins/effects.js +220 -0
  154. package/dist/interpreter/builtins/effects.js.map +1 -0
  155. package/dist/interpreter/builtins/index.d.ts +16 -0
  156. package/dist/interpreter/builtins/index.d.ts.map +1 -0
  157. package/dist/interpreter/builtins/index.js +17 -0
  158. package/dist/interpreter/builtins/index.js.map +1 -0
  159. package/dist/interpreter/builtins/layout.d.ts +12 -0
  160. package/dist/interpreter/builtins/layout.d.ts.map +1 -0
  161. package/dist/interpreter/builtins/layout.js +175 -0
  162. package/dist/interpreter/builtins/layout.js.map +1 -0
  163. package/dist/interpreter/builtins/live.d.ts +11 -0
  164. package/dist/interpreter/builtins/live.d.ts.map +1 -0
  165. package/dist/interpreter/builtins/live.js +125 -0
  166. package/dist/interpreter/builtins/live.js.map +1 -0
  167. package/dist/interpreter/builtins/midi.d.ts +16 -0
  168. package/dist/interpreter/builtins/midi.d.ts.map +1 -0
  169. package/dist/interpreter/builtins/midi.js +320 -0
  170. package/dist/interpreter/builtins/midi.js.map +1 -0
  171. package/dist/interpreter/builtins/mixing.d.ts +6 -0
  172. package/dist/interpreter/builtins/mixing.d.ts.map +1 -0
  173. package/dist/interpreter/builtins/mixing.js +62 -0
  174. package/dist/interpreter/builtins/mixing.js.map +1 -0
  175. package/dist/interpreter/builtins/notation.d.ts +24 -0
  176. package/dist/interpreter/builtins/notation.d.ts.map +1 -0
  177. package/dist/interpreter/builtins/notation.js +251 -0
  178. package/dist/interpreter/builtins/notation.js.map +1 -0
  179. package/dist/interpreter/builtins/ornaments.d.ts +8 -0
  180. package/dist/interpreter/builtins/ornaments.d.ts.map +1 -0
  181. package/dist/interpreter/builtins/ornaments.js +155 -0
  182. package/dist/interpreter/builtins/ornaments.js.map +1 -0
  183. package/dist/interpreter/builtins/techniques.d.ts +11 -0
  184. package/dist/interpreter/builtins/techniques.d.ts.map +1 -0
  185. package/dist/interpreter/builtins/techniques.js +234 -0
  186. package/dist/interpreter/builtins/techniques.js.map +1 -0
  187. package/dist/interpreter/builtins/tuning.d.ts +7 -0
  188. package/dist/interpreter/builtins/tuning.d.ts.map +1 -0
  189. package/dist/interpreter/builtins/tuning.js +52 -0
  190. package/dist/interpreter/builtins/tuning.js.map +1 -0
  191. package/dist/interpreter/builtins/types.d.ts +27 -0
  192. package/dist/interpreter/builtins/types.d.ts.map +1 -0
  193. package/dist/interpreter/builtins/types.js +3 -0
  194. package/dist/interpreter/builtins/types.js.map +1 -0
  195. package/dist/interpreter/builtins/vocaloid.d.ts +10 -0
  196. package/dist/interpreter/builtins/vocaloid.d.ts.map +1 -0
  197. package/dist/interpreter/builtins/vocaloid.js +165 -0
  198. package/dist/interpreter/builtins/vocaloid.js.map +1 -0
  199. package/dist/interpreter/index.d.ts +4 -0
  200. package/dist/interpreter/index.d.ts.map +1 -0
  201. package/dist/interpreter/index.js +4 -0
  202. package/dist/interpreter/index.js.map +1 -0
  203. package/dist/interpreter/interpreter.d.ts +305 -0
  204. package/dist/interpreter/interpreter.d.ts.map +1 -0
  205. package/dist/interpreter/interpreter.js +8463 -0
  206. package/dist/interpreter/interpreter.js.map +1 -0
  207. package/dist/interpreter/runtime.d.ts +67 -0
  208. package/dist/interpreter/runtime.d.ts.map +1 -0
  209. package/dist/interpreter/runtime.js +88 -0
  210. package/dist/interpreter/runtime.js.map +1 -0
  211. package/dist/interpreter/scope.d.ts +21 -0
  212. package/dist/interpreter/scope.d.ts.map +1 -0
  213. package/dist/interpreter/scope.js +60 -0
  214. package/dist/interpreter/scope.js.map +1 -0
  215. package/dist/interpreter/trackState.d.ts +205 -0
  216. package/dist/interpreter/trackState.d.ts.map +1 -0
  217. package/dist/interpreter/trackState.js +12 -0
  218. package/dist/interpreter/trackState.js.map +1 -0
  219. package/dist/lexer/index.d.ts +2 -0
  220. package/dist/lexer/index.d.ts.map +1 -0
  221. package/dist/lexer/index.js +2 -0
  222. package/dist/lexer/index.js.map +1 -0
  223. package/dist/lexer/lexer.d.ts +30 -0
  224. package/dist/lexer/lexer.d.ts.map +1 -0
  225. package/dist/lexer/lexer.js +385 -0
  226. package/dist/lexer/lexer.js.map +1 -0
  227. package/dist/parser/index.d.ts +2 -0
  228. package/dist/parser/index.d.ts.map +1 -0
  229. package/dist/parser/index.js +2 -0
  230. package/dist/parser/index.js.map +1 -0
  231. package/dist/parser/parser.d.ts +55 -0
  232. package/dist/parser/parser.d.ts.map +1 -0
  233. package/dist/parser/parser.js +896 -0
  234. package/dist/parser/parser.js.map +1 -0
  235. package/dist/types/ast.d.ts +220 -0
  236. package/dist/types/ast.d.ts.map +1 -0
  237. package/dist/types/ast.js +3 -0
  238. package/dist/types/ast.js.map +1 -0
  239. package/dist/types/index.d.ts +4 -0
  240. package/dist/types/index.d.ts.map +1 -0
  241. package/dist/types/index.js +4 -0
  242. package/dist/types/index.js.map +1 -0
  243. package/dist/types/ir/advanced.d.ts +491 -0
  244. package/dist/types/ir/advanced.d.ts.map +1 -0
  245. package/dist/types/ir/advanced.js +3 -0
  246. package/dist/types/ir/advanced.js.map +1 -0
  247. package/dist/types/ir/algorithmic.d.ts +48 -0
  248. package/dist/types/ir/algorithmic.d.ts.map +1 -0
  249. package/dist/types/ir/algorithmic.js +3 -0
  250. package/dist/types/ir/algorithmic.js.map +1 -0
  251. package/dist/types/ir/analysis.d.ts +34 -0
  252. package/dist/types/ir/analysis.d.ts.map +1 -0
  253. package/dist/types/ir/analysis.js +3 -0
  254. package/dist/types/ir/analysis.js.map +1 -0
  255. package/dist/types/ir/audio.d.ts +249 -0
  256. package/dist/types/ir/audio.d.ts.map +1 -0
  257. package/dist/types/ir/audio.js +3 -0
  258. package/dist/types/ir/audio.js.map +1 -0
  259. package/dist/types/ir/automation.d.ts +46 -0
  260. package/dist/types/ir/automation.d.ts.map +1 -0
  261. package/dist/types/ir/automation.js +3 -0
  262. package/dist/types/ir/automation.js.map +1 -0
  263. package/dist/types/ir/collaboration.d.ts +20 -0
  264. package/dist/types/ir/collaboration.d.ts.map +1 -0
  265. package/dist/types/ir/collaboration.js +3 -0
  266. package/dist/types/ir/collaboration.js.map +1 -0
  267. package/dist/types/ir/core.d.ts +153 -0
  268. package/dist/types/ir/core.d.ts.map +1 -0
  269. package/dist/types/ir/core.js +3 -0
  270. package/dist/types/ir/core.js.map +1 -0
  271. package/dist/types/ir/effects.d.ts +169 -0
  272. package/dist/types/ir/effects.d.ts.map +1 -0
  273. package/dist/types/ir/effects.js +3 -0
  274. package/dist/types/ir/effects.js.map +1 -0
  275. package/dist/types/ir/extended.d.ts +104 -0
  276. package/dist/types/ir/extended.d.ts.map +1 -0
  277. package/dist/types/ir/extended.js +3 -0
  278. package/dist/types/ir/extended.js.map +1 -0
  279. package/dist/types/ir/index.d.ts +16 -0
  280. package/dist/types/ir/index.d.ts.map +1 -0
  281. package/dist/types/ir/index.js +17 -0
  282. package/dist/types/ir/index.js.map +1 -0
  283. package/dist/types/ir/mastering.d.ts +86 -0
  284. package/dist/types/ir/mastering.d.ts.map +1 -0
  285. package/dist/types/ir/mastering.js +3 -0
  286. package/dist/types/ir/mastering.js.map +1 -0
  287. package/dist/types/ir/midi.d.ts +79 -0
  288. package/dist/types/ir/midi.d.ts.map +1 -0
  289. package/dist/types/ir/midi.js +3 -0
  290. package/dist/types/ir/midi.js.map +1 -0
  291. package/dist/types/ir/notation.d.ts +963 -0
  292. package/dist/types/ir/notation.d.ts.map +1 -0
  293. package/dist/types/ir/notation.js +3 -0
  294. package/dist/types/ir/notation.js.map +1 -0
  295. package/dist/types/ir/recording.d.ts +48 -0
  296. package/dist/types/ir/recording.d.ts.map +1 -0
  297. package/dist/types/ir/recording.js +3 -0
  298. package/dist/types/ir/recording.js.map +1 -0
  299. package/dist/types/ir/sampling.d.ts +59 -0
  300. package/dist/types/ir/sampling.d.ts.map +1 -0
  301. package/dist/types/ir/sampling.js +3 -0
  302. package/dist/types/ir/sampling.js.map +1 -0
  303. package/dist/types/ir/sequencing.d.ts +118 -0
  304. package/dist/types/ir/sequencing.d.ts.map +1 -0
  305. package/dist/types/ir/sequencing.js +3 -0
  306. package/dist/types/ir/sequencing.js.map +1 -0
  307. package/dist/types/ir/sync.d.ts +39 -0
  308. package/dist/types/ir/sync.d.ts.map +1 -0
  309. package/dist/types/ir/sync.js +3 -0
  310. package/dist/types/ir/sync.js.map +1 -0
  311. package/dist/types/ir.d.ts +2 -0
  312. package/dist/types/ir.d.ts.map +1 -0
  313. package/dist/types/ir.js +3 -0
  314. package/dist/types/ir.js.map +1 -0
  315. package/dist/types/token.d.ts +72 -0
  316. package/dist/types/token.d.ts.map +1 -0
  317. package/dist/types/token.js +90 -0
  318. package/dist/types/token.js.map +1 -0
  319. package/dist/utils/stdlib.d.ts +18 -0
  320. package/dist/utils/stdlib.d.ts.map +1 -0
  321. package/dist/utils/stdlib.js +51 -0
  322. package/dist/utils/stdlib.js.map +1 -0
  323. package/lib/articulation.mf +46 -0
  324. package/lib/composition.mf +299 -0
  325. package/lib/curves.mf +183 -0
  326. package/lib/dynamics.mf +141 -0
  327. package/lib/expression.mf +221 -0
  328. package/lib/genres.mf +348 -0
  329. package/lib/notation.mf +224 -0
  330. package/lib/ornaments.mf +98 -0
  331. package/lib/patterns.mf +170 -0
  332. package/lib/rhythm.mf +269 -0
  333. package/lib/theory.mf +257 -0
  334. package/lib/utils.mf +140 -0
  335. package/package.json +49 -0
package/lib/rhythm.mf ADDED
@@ -0,0 +1,269 @@
1
+ // Rhythm generation functions for TakoMusic
2
+ // Algorithmic rhythm patterns and timing variations
3
+
4
+ // euclidean - generate Euclidean rhythm pattern
5
+ // Distributes pulses as evenly as possible across steps
6
+ export proc euclidean(steps, pulses, dur, pitch) {
7
+ let pattern = [];
8
+ let bucket = 0;
9
+
10
+ for (i in 0..steps) {
11
+ bucket = bucket + pulses;
12
+ if (bucket >= steps) {
13
+ bucket = bucket - steps;
14
+ push(pattern, true);
15
+ } else {
16
+ push(pattern, false);
17
+ }
18
+ }
19
+
20
+ forEach(pattern, (hit) => {
21
+ if (hit) {
22
+ note(pitch, dur);
23
+ } else {
24
+ rest(dur);
25
+ }
26
+ });
27
+ }
28
+
29
+ // swing - apply swing feel to note sequence
30
+ // amount: 0 = straight, 0.33 = triplet swing, 0.5 = extreme swing
31
+ export proc swing(notes, dur, amount) {
32
+ forEach(notes, (n, i) => {
33
+ if (i % 2 == 0) {
34
+ const swingDur = dur * (1 + amount);
35
+ note(n, swingDur);
36
+ } else {
37
+ const swingDur = dur * (1 - amount);
38
+ note(n, swingDur);
39
+ }
40
+ });
41
+ }
42
+
43
+ // humanize - add random timing variations
44
+ // Adds slight timing offsets to make rhythm feel more human
45
+ export proc humanize(notes, dur, amount) {
46
+ forEach(notes, (n) => {
47
+ const offset = (random() - 0.5) * amount;
48
+ const offsetTicks = floor(offset * durToTicks(dur));
49
+ advanceTick(offsetTicks);
50
+ note(n, dur);
51
+ });
52
+ }
53
+
54
+ // shuffle - shuffle rhythm (dotted eighth + sixteenth)
55
+ export proc shuffle(notes, dur) {
56
+ forEach(notes, (n, i) => {
57
+ if (i % 2 == 0) {
58
+ note(n, dur * 3/4);
59
+ } else {
60
+ note(n, dur * 1/4);
61
+ }
62
+ });
63
+ }
64
+
65
+ // clave - generate clave rhythm pattern
66
+ export proc clave32(pitch, dur) {
67
+ note(pitch, dur);
68
+ rest(dur);
69
+ rest(dur);
70
+ note(pitch, dur);
71
+ rest(dur);
72
+ rest(dur);
73
+ note(pitch, dur);
74
+ rest(dur);
75
+
76
+ rest(dur);
77
+ rest(dur);
78
+ note(pitch, dur);
79
+ rest(dur);
80
+ note(pitch, dur);
81
+ rest(dur);
82
+ rest(dur);
83
+ rest(dur);
84
+ }
85
+
86
+ // clave23 - 2-3 clave (reverse)
87
+ export proc clave23(pitch, dur) {
88
+ rest(dur);
89
+ rest(dur);
90
+ note(pitch, dur);
91
+ rest(dur);
92
+ note(pitch, dur);
93
+ rest(dur);
94
+ rest(dur);
95
+ rest(dur);
96
+
97
+ note(pitch, dur);
98
+ rest(dur);
99
+ rest(dur);
100
+ note(pitch, dur);
101
+ rest(dur);
102
+ rest(dur);
103
+ note(pitch, dur);
104
+ rest(dur);
105
+ }
106
+
107
+ // polyrhythm - play two different rhythms simultaneously
108
+ // Returns pattern array for manual track assignment
109
+ export proc polyrhythmPattern(steps1, steps2, totalSteps) {
110
+ let pattern1 = [];
111
+ let pattern2 = [];
112
+
113
+ for (i in 0..totalSteps) {
114
+ push(pattern1, i % steps1 == 0);
115
+ push(pattern2, i % steps2 == 0);
116
+ }
117
+
118
+ return [pattern1, pattern2];
119
+ }
120
+
121
+ // Generate basic drum patterns
122
+ export proc basicBeat(kickPitch, snarePitch, hatPitch, dur, bars) {
123
+ const steps = bars * 16;
124
+
125
+ for (i in 0..steps) {
126
+ const beat = i % 16;
127
+
128
+ // Kick on 1 and 3 (0, 8)
129
+ if (beat == 0 || beat == 8) {
130
+ drum(kickPitch, dur);
131
+ }
132
+
133
+ // Snare on 2 and 4 (4, 12)
134
+ if (beat == 4 || beat == 12) {
135
+ drum(snarePitch, dur);
136
+ }
137
+
138
+ // Hi-hat on every eighth note
139
+ if (beat % 2 == 0) {
140
+ drum(hatPitch, dur);
141
+ }
142
+
143
+ if (beat % 2 == 1) {
144
+ rest(dur);
145
+ }
146
+ }
147
+ }
148
+
149
+ // Apply groove template to notes
150
+ // template: array of timing offsets (-1.0 to 1.0)
151
+ export proc groove(notes, dur, template) {
152
+ for (i in 0..len(notes)) {
153
+ const templateIdx = i % len(template);
154
+ const offset = template[templateIdx];
155
+ const offsetTicks = floor(offset * durToTicks(dur) / 4);
156
+
157
+ if (offsetTicks > 0) {
158
+ advanceTick(offsetTicks);
159
+ }
160
+
161
+ note(notes[i], dur);
162
+
163
+ if (offsetTicks < 0) {
164
+ advanceTick(-offsetTicks);
165
+ }
166
+ }
167
+ }
168
+
169
+ // Common groove templates
170
+ export proc swingGroove() {
171
+ return [0.0, 0.33, 0.0, 0.33];
172
+ }
173
+
174
+ export proc laidBackGroove() {
175
+ return [0.0, 0.1, 0.05, 0.15];
176
+ }
177
+
178
+ export proc pushGroove() {
179
+ return [0.0, -0.1, 0.0, -0.1];
180
+ }
181
+
182
+ // Rubato - expressive timing variation
183
+ export proc rubato(notes, baseDur, variation) {
184
+ for (i in 0..len(notes)) {
185
+ const stretch = 1 + (random() - 0.5) * variation;
186
+ const dur = baseDur * stretch;
187
+ note(notes[i], dur);
188
+ }
189
+ }
190
+
191
+ // Accelerando - gradually speed up
192
+ export proc accelerando(notes, startDur, endDur) {
193
+ const count = len(notes);
194
+ for (i in 0..count) {
195
+ const t = i / (count - 1);
196
+ const dur = startDur + (endDur - startDur) * t;
197
+ note(notes[i], dur);
198
+ }
199
+ }
200
+
201
+ // Ritardando - gradually slow down
202
+ export proc ritardando(notes, startDur, endDur) {
203
+ accelerando(notes, startDur, endDur);
204
+ }
205
+
206
+ // Accelerando with tempo changes
207
+ export proc accelerandoTempo(startBpm, endBpm, dur, steps) {
208
+ const ticks = durToTicks(dur);
209
+ const ticksPerStep = floor(ticks / steps);
210
+
211
+ for (i in 0..=steps) {
212
+ const t = i / steps;
213
+ const bpm = floor(startBpm + (endBpm - startBpm) * t);
214
+ atTick(i * ticksPerStep);
215
+ tempo(bpm);
216
+ }
217
+ }
218
+
219
+ // Ritardando with tempo changes
220
+ export proc ritardandoTempo(startBpm, endBpm, dur, steps) {
221
+ accelerandoTempo(startBpm, endBpm, dur, steps);
222
+ }
223
+
224
+ // Fermata - pause/hold
225
+ export proc fermata(pitch, baseDur, holdMultiplier) {
226
+ note(pitch, baseDur * holdMultiplier);
227
+ }
228
+
229
+ // Metric modulation helper
230
+ // Returns the new tempo for metric modulation
231
+ export proc metricModulation(currentBpm, oldSubdivision, newSubdivision) {
232
+ return floor(currentBpm * oldSubdivision / newSubdivision);
233
+ }
234
+
235
+ // Tuplet rhythm generator
236
+ export proc tuplet(notes, totalDur, tupletRatio) {
237
+ const noteDur = totalDur / len(notes);
238
+ for (i in 0..len(notes)) {
239
+ note(notes[i], noteDur);
240
+ }
241
+ }
242
+
243
+ // Triplet
244
+ export proc triplet(notes, baseDur) {
245
+ const tripletDur = baseDur * 2 / 3;
246
+ for (i in 0..len(notes)) {
247
+ note(notes[i], tripletDur);
248
+ }
249
+ }
250
+
251
+ // Syncopation pattern
252
+ export proc syncopate(notes, dur) {
253
+ for (i in 0..len(notes)) {
254
+ if (i % 2 == 0) {
255
+ rest(dur / 2);
256
+ note(notes[i], dur / 2);
257
+ } else {
258
+ note(notes[i], dur);
259
+ }
260
+ }
261
+ }
262
+
263
+ // Hemiola - 3 against 2
264
+ export proc hemiola(notes, dur) {
265
+ const hemiolaDur = dur * 2 / 3;
266
+ for (i in 0..len(notes)) {
267
+ note(notes[i], hemiolaDur);
268
+ }
269
+ }
package/lib/theory.mf ADDED
@@ -0,0 +1,257 @@
1
+ // Music theory helper functions for TakoMusic
2
+ // Scales, chords, intervals, and harmonic functions
3
+
4
+ // Chord construction - returns array of pitches
5
+
6
+ export proc majorTriad(root) {
7
+ return [root, transpose(root, 4), transpose(root, 7)];
8
+ }
9
+
10
+ export proc minorTriad(root) {
11
+ return [root, transpose(root, 3), transpose(root, 7)];
12
+ }
13
+
14
+ export proc diminishedTriad(root) {
15
+ return [root, transpose(root, 3), transpose(root, 6)];
16
+ }
17
+
18
+ export proc augmentedTriad(root) {
19
+ return [root, transpose(root, 4), transpose(root, 8)];
20
+ }
21
+
22
+ export proc majorSeventh(root) {
23
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 11)];
24
+ }
25
+
26
+ export proc minorSeventh(root) {
27
+ return [root, transpose(root, 3), transpose(root, 7), transpose(root, 10)];
28
+ }
29
+
30
+ export proc dominantSeventh(root) {
31
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 10)];
32
+ }
33
+
34
+ export proc halfDiminishedSeventh(root) {
35
+ return [root, transpose(root, 3), transpose(root, 6), transpose(root, 10)];
36
+ }
37
+
38
+ export proc diminishedSeventh(root) {
39
+ return [root, transpose(root, 3), transpose(root, 6), transpose(root, 9)];
40
+ }
41
+
42
+ // Suspended chords
43
+ export proc sus2(root) {
44
+ return [root, transpose(root, 2), transpose(root, 7)];
45
+ }
46
+
47
+ export proc sus4(root) {
48
+ return [root, transpose(root, 5), transpose(root, 7)];
49
+ }
50
+
51
+ // Add chords
52
+ export proc add9(root) {
53
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 14)];
54
+ }
55
+
56
+ export proc minorAdd9(root) {
57
+ return [root, transpose(root, 3), transpose(root, 7), transpose(root, 14)];
58
+ }
59
+
60
+ // Extended chords
61
+ export proc ninth(root) {
62
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 10), transpose(root, 14)];
63
+ }
64
+
65
+ export proc minorNinth(root) {
66
+ return [root, transpose(root, 3), transpose(root, 7), transpose(root, 10), transpose(root, 14)];
67
+ }
68
+
69
+ export proc majorNinth(root) {
70
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 11), transpose(root, 14)];
71
+ }
72
+
73
+ export proc eleventh(root) {
74
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 10), transpose(root, 14), transpose(root, 17)];
75
+ }
76
+
77
+ export proc thirteenth(root) {
78
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 10), transpose(root, 14), transpose(root, 21)];
79
+ }
80
+
81
+ // Sixth chords
82
+ export proc sixth(root) {
83
+ return [root, transpose(root, 4), transpose(root, 7), transpose(root, 9)];
84
+ }
85
+
86
+ export proc minorSixth(root) {
87
+ return [root, transpose(root, 3), transpose(root, 7), transpose(root, 9)];
88
+ }
89
+
90
+ // Power chord (no third)
91
+ export proc powerChord(root) {
92
+ return [root, transpose(root, 7)];
93
+ }
94
+
95
+ export proc powerChordOctave(root) {
96
+ return [root, transpose(root, 7), transpose(root, 12)];
97
+ }
98
+
99
+ // Scale generation - returns array of pitches for one octave
100
+
101
+ export proc majorScale(root) {
102
+ const intervals = [0, 2, 4, 5, 7, 9, 11, 12];
103
+ return map(intervals, (i) => transpose(root, i));
104
+ }
105
+
106
+ export proc minorScale(root) {
107
+ const intervals = [0, 2, 3, 5, 7, 8, 10, 12];
108
+ return map(intervals, (i) => transpose(root, i));
109
+ }
110
+
111
+ export proc harmonicMinor(root) {
112
+ const intervals = [0, 2, 3, 5, 7, 8, 11, 12];
113
+ return map(intervals, (i) => transpose(root, i));
114
+ }
115
+
116
+ export proc melodicMinor(root) {
117
+ const intervals = [0, 2, 3, 5, 7, 9, 11, 12];
118
+ return map(intervals, (i) => transpose(root, i));
119
+ }
120
+
121
+ export proc pentatonicMajor(root) {
122
+ const intervals = [0, 2, 4, 7, 9, 12];
123
+ return map(intervals, (i) => transpose(root, i));
124
+ }
125
+
126
+ export proc pentatonicMinor(root) {
127
+ const intervals = [0, 3, 5, 7, 10, 12];
128
+ return map(intervals, (i) => transpose(root, i));
129
+ }
130
+
131
+ export proc bluesScale(root) {
132
+ const intervals = [0, 3, 5, 6, 7, 10, 12];
133
+ return map(intervals, (i) => transpose(root, i));
134
+ }
135
+
136
+ export proc dorianMode(root) {
137
+ const intervals = [0, 2, 3, 5, 7, 9, 10, 12];
138
+ return map(intervals, (i) => transpose(root, i));
139
+ }
140
+
141
+ export proc phrygianMode(root) {
142
+ const intervals = [0, 1, 3, 5, 7, 8, 10, 12];
143
+ return map(intervals, (i) => transpose(root, i));
144
+ }
145
+
146
+ export proc lydianMode(root) {
147
+ const intervals = [0, 2, 4, 6, 7, 9, 11, 12];
148
+ return map(intervals, (i) => transpose(root, i));
149
+ }
150
+
151
+ export proc mixolydianMode(root) {
152
+ const intervals = [0, 2, 4, 5, 7, 9, 10, 12];
153
+ return map(intervals, (i) => transpose(root, i));
154
+ }
155
+
156
+ export proc aeolianMode(root) {
157
+ // Same as natural minor
158
+ return minorScale(root);
159
+ }
160
+
161
+ export proc locrianMode(root) {
162
+ const intervals = [0, 1, 3, 5, 6, 8, 10, 12];
163
+ return map(intervals, (i) => transpose(root, i));
164
+ }
165
+
166
+ export proc wholeToneScale(root) {
167
+ const intervals = [0, 2, 4, 6, 8, 10, 12];
168
+ return map(intervals, (i) => transpose(root, i));
169
+ }
170
+
171
+ export proc chromaticScale(root) {
172
+ const intervals = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
173
+ return map(intervals, (i) => transpose(root, i));
174
+ }
175
+
176
+ // Chord voicings
177
+
178
+ export proc firstInversion(chordNotes) {
179
+ const root = chordNotes[0];
180
+ const rest = slice(chordNotes, 1, len(chordNotes));
181
+ return concat(rest, [transpose(root, 12)]);
182
+ }
183
+
184
+ export proc secondInversion(chordNotes) {
185
+ return firstInversion(firstInversion(chordNotes));
186
+ }
187
+
188
+ // Interval helpers
189
+
190
+ export const UNISON = 0;
191
+ export const MINOR_SECOND = 1;
192
+ export const MAJOR_SECOND = 2;
193
+ export const MINOR_THIRD = 3;
194
+ export const MAJOR_THIRD = 4;
195
+ export const PERFECT_FOURTH = 5;
196
+ export const TRITONE = 6;
197
+ export const PERFECT_FIFTH = 7;
198
+ export const MINOR_SIXTH = 8;
199
+ export const MAJOR_SIXTH = 9;
200
+ export const MINOR_SEVENTH = 10;
201
+ export const MAJOR_SEVENTH = 11;
202
+ export const OCTAVE = 12;
203
+
204
+ // Rhythm values (assuming 4/4 time signature)
205
+
206
+ export const WHOLE = 1/1;
207
+ export const HALF = 1/2;
208
+ export const QUARTER = 1/4;
209
+ export const EIGHTH = 1/8;
210
+ export const SIXTEENTH = 1/16;
211
+ export const THIRTY_SECOND = 1/32;
212
+
213
+ export const DOTTED_HALF = 3/4;
214
+ export const DOTTED_QUARTER = 3/8;
215
+ export const DOTTED_EIGHTH = 3/16;
216
+
217
+ // Helper to get scale degree
218
+ export proc scaleDegree(scale, degree) {
219
+ const idx = (degree - 1) % len(scale);
220
+ return scale[idx];
221
+ }
222
+
223
+ // Generate chord progression using scale degrees
224
+ export proc progression(scale, degrees, chordFunc) {
225
+ return map(degrees, (degree) => {
226
+ const root = scaleDegree(scale, degree);
227
+ return chordFunc(root);
228
+ });
229
+ }
230
+
231
+ // Common progressions
232
+ export proc majorIIVI(root) {
233
+ const scale = majorScale(root);
234
+ return [
235
+ minorSeventh(scaleDegree(scale, 2)),
236
+ dominantSeventh(scaleDegree(scale, 5)),
237
+ majorSeventh(scaleDegree(scale, 1))
238
+ ];
239
+ }
240
+
241
+ export proc major145(root) {
242
+ const scale = majorScale(root);
243
+ return [
244
+ majorTriad(scaleDegree(scale, 1)),
245
+ majorTriad(scaleDegree(scale, 4)),
246
+ majorTriad(scaleDegree(scale, 5))
247
+ ];
248
+ }
249
+
250
+ export proc minor145(root) {
251
+ const scale = minorScale(root);
252
+ return [
253
+ minorTriad(scaleDegree(scale, 1)),
254
+ minorTriad(scaleDegree(scale, 4)),
255
+ minorTriad(scaleDegree(scale, 5))
256
+ ];
257
+ }
package/lib/utils.mf ADDED
@@ -0,0 +1,140 @@
1
+ // Utility functions for TakoMusic
2
+ // General-purpose helper functions
3
+
4
+ // Constrain value between min and max
5
+ export proc clip(val, minVal, maxVal) {
6
+ return min(max(val, minVal), maxVal);
7
+ }
8
+
9
+ // Linear interpolation between a and b
10
+ export proc lerp(a, b, t) {
11
+ return a + (b - a) * t;
12
+ }
13
+
14
+ // Rescale value from input range to output range
15
+ export proc rescale(val, inMin, inMax, outMin, outMax) {
16
+ const t = (val - inMin) / (inMax - inMin);
17
+ return lerp(outMin, outMax, t);
18
+ }
19
+
20
+ // Quantize value to nearest step
21
+ export proc quantize(val, step) {
22
+ return floor(val / step) * step;
23
+ }
24
+
25
+ // Wrap value to range [min, max)
26
+ export proc wrap(val, minVal, maxVal) {
27
+ const range = maxVal - minVal;
28
+ let result = val;
29
+ if (result < minVal) {
30
+ result = result + range * ceil((minVal - result) / range);
31
+ }
32
+ if (result >= maxVal) {
33
+ result = result - range * floor((result - minVal) / range);
34
+ }
35
+ return result;
36
+ }
37
+
38
+ // Sign function: returns -1, 0, or 1
39
+ export proc sign(val) {
40
+ if (val > 0) { return 1; }
41
+ if (val < 0) { return -1; }
42
+ return 0;
43
+ }
44
+
45
+ // Randomize velocity with variation
46
+ export proc randomizeVel(baseVel, variation) {
47
+ const offset = floor((random() - 0.5) * variation * 2);
48
+ return clip(baseVel + offset, 1, 127);
49
+ }
50
+
51
+ // Random choice from array
52
+ export proc choice(arr) {
53
+ const idx = random(len(arr));
54
+ return arr[idx];
55
+ }
56
+
57
+ // Shuffle array (Fisher-Yates)
58
+ export proc shuffle(arr) {
59
+ let result = copy(arr);
60
+ for (i in 0..len(result) - 1) {
61
+ const j = i + random(len(result) - i);
62
+ const temp = result[i];
63
+ result[i] = result[j];
64
+ result[j] = temp;
65
+ }
66
+ return result;
67
+ }
68
+
69
+ // Sum of array elements
70
+ export proc sum(arr) {
71
+ return reduce(arr, (acc, x) => acc + x, 0);
72
+ }
73
+
74
+ // Average of array elements
75
+ export proc average(arr) {
76
+ if (len(arr) == 0) { return 0; }
77
+ return sum(arr) / len(arr);
78
+ }
79
+
80
+ // Normalize array to range [0, 1]
81
+ export proc normalize(arr) {
82
+ const minVal = reduce(arr, (a, b) => min(a, b), arr[0]);
83
+ const maxVal = reduce(arr, (a, b) => max(a, b), arr[0]);
84
+ const range = maxVal - minVal;
85
+ if (range == 0) { return fill(len(arr), 0.5); }
86
+ return map(arr, (x) => (x - minVal) / range);
87
+ }
88
+
89
+ // Zip two arrays into array of pairs
90
+ export proc zip(arr1, arr2) {
91
+ const minLen = min(len(arr1), len(arr2));
92
+ let result = [];
93
+ for (i in 0..minLen) {
94
+ push(result, [arr1[i], arr2[i]]);
95
+ }
96
+ return result;
97
+ }
98
+
99
+ // Repeat pattern n times
100
+ export proc repeatPattern(pattern, n) {
101
+ let result = [];
102
+ for (i in 0..n) {
103
+ for (j in 0..len(pattern)) {
104
+ push(result, pattern[j]);
105
+ }
106
+ }
107
+ return result;
108
+ }
109
+
110
+ // Rotate array by n positions
111
+ export proc rotate(arr, n) {
112
+ const len = len(arr);
113
+ if (len == 0) { return []; }
114
+ const shift = n % len;
115
+ const idx = (len - shift) % len;
116
+ return concat(slice(arr, idx, len), slice(arr, 0, idx));
117
+ }
118
+
119
+ // Take first n elements
120
+ export proc take(arr, n) {
121
+ return slice(arr, 0, min(n, len(arr)));
122
+ }
123
+
124
+ // Drop first n elements
125
+ export proc drop(arr, n) {
126
+ return slice(arr, min(n, len(arr)), len(arr));
127
+ }
128
+
129
+ // Chunk array into groups of size n
130
+ export proc chunk(arr, n) {
131
+ let result = [];
132
+ for (i in 0..len(arr)) {
133
+ if (i % n == 0) {
134
+ push(result, []);
135
+ }
136
+ const lastIdx = len(result) - 1;
137
+ push(result[lastIdx], arr[i]);
138
+ }
139
+ return result;
140
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "takomusic",
3
+ "version": "1.2.0",
4
+ "description": "TakoMusic - A domain-specific language for music composition that generates VSQX, MusicXML, and MIDI",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mf": "dist/cli/index.js"
9
+ },
10
+ "files": [
11
+ "dist",
12
+ "lib"
13
+ ],
14
+ "scripts": {
15
+ "build": "tsc",
16
+ "dev": "tsc --watch",
17
+ "test": "vitest",
18
+ "test:run": "vitest --run",
19
+ "lint": "eslint src",
20
+ "mf": "node dist/cli/index.js"
21
+ },
22
+ "keywords": [
23
+ "music",
24
+ "dsl",
25
+ "composition",
26
+ "midi",
27
+ "vsqx",
28
+ "musicxml",
29
+ "vocaloid",
30
+ "neutrino"
31
+ ],
32
+ "repository": {
33
+ "type": "git",
34
+ "url": "https://github.com/tako0614/takomusic"
35
+ },
36
+ "author": "",
37
+ "license": "AGPL-3.0",
38
+ "devDependencies": {
39
+ "@types/node": "^20.10.0",
40
+ "typescript": "^5.3.0",
41
+ "vitest": "^1.0.0"
42
+ },
43
+ "dependencies": {
44
+ "toml": "^3.0.0"
45
+ },
46
+ "engines": {
47
+ "node": ">=18.0.0"
48
+ }
49
+ }