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.
- package/LICENSE +661 -0
- package/README.md +230 -0
- package/dist/__tests__/checker.test.d.ts +2 -0
- package/dist/__tests__/checker.test.d.ts.map +1 -0
- package/dist/__tests__/checker.test.js +316 -0
- package/dist/__tests__/checker.test.js.map +1 -0
- package/dist/__tests__/compiler.test.d.ts +2 -0
- package/dist/__tests__/compiler.test.d.ts.map +1 -0
- package/dist/__tests__/compiler.test.js +260 -0
- package/dist/__tests__/compiler.test.js.map +1 -0
- package/dist/__tests__/generators.test.d.ts +2 -0
- package/dist/__tests__/generators.test.d.ts.map +1 -0
- package/dist/__tests__/generators.test.js +283 -0
- package/dist/__tests__/generators.test.js.map +1 -0
- package/dist/__tests__/interpreter.test.d.ts +2 -0
- package/dist/__tests__/interpreter.test.d.ts.map +1 -0
- package/dist/__tests__/interpreter.test.js +298 -0
- package/dist/__tests__/interpreter.test.js.map +1 -0
- package/dist/__tests__/lexer.test.d.ts +2 -0
- package/dist/__tests__/lexer.test.d.ts.map +1 -0
- package/dist/__tests__/lexer.test.js +89 -0
- package/dist/__tests__/lexer.test.js.map +1 -0
- package/dist/__tests__/parser.test.d.ts +2 -0
- package/dist/__tests__/parser.test.d.ts.map +1 -0
- package/dist/__tests__/parser.test.js +116 -0
- package/dist/__tests__/parser.test.js.map +1 -0
- package/dist/checker/checker.d.ts +37 -0
- package/dist/checker/checker.d.ts.map +1 -0
- package/dist/checker/checker.js +428 -0
- package/dist/checker/checker.js.map +1 -0
- package/dist/checker/index.d.ts +3 -0
- package/dist/checker/index.d.ts.map +1 -0
- package/dist/checker/index.js +2 -0
- package/dist/checker/index.js.map +1 -0
- package/dist/cli/commands/build.d.ts +2 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +173 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/check.d.ts +2 -0
- package/dist/cli/commands/check.d.ts.map +1 -0
- package/dist/cli/commands/check.js +79 -0
- package/dist/cli/commands/check.js.map +1 -0
- package/dist/cli/commands/doctor.d.ts +2 -0
- package/dist/cli/commands/doctor.d.ts.map +1 -0
- package/dist/cli/commands/doctor.js +187 -0
- package/dist/cli/commands/doctor.js.map +1 -0
- package/dist/cli/commands/fmt.d.ts +2 -0
- package/dist/cli/commands/fmt.d.ts.map +1 -0
- package/dist/cli/commands/fmt.js +73 -0
- package/dist/cli/commands/fmt.js.map +1 -0
- package/dist/cli/commands/import.d.ts +2 -0
- package/dist/cli/commands/import.d.ts.map +1 -0
- package/dist/cli/commands/import.js +99 -0
- package/dist/cli/commands/import.js.map +1 -0
- package/dist/cli/commands/init.d.ts +2 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +514 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/play.d.ts +2 -0
- package/dist/cli/commands/play.d.ts.map +1 -0
- package/dist/cli/commands/play.js +216 -0
- package/dist/cli/commands/play.js.map +1 -0
- package/dist/cli/commands/record.d.ts +2 -0
- package/dist/cli/commands/record.d.ts.map +1 -0
- package/dist/cli/commands/record.js +393 -0
- package/dist/cli/commands/record.js.map +1 -0
- package/dist/cli/commands/render.d.ts +2 -0
- package/dist/cli/commands/render.d.ts.map +1 -0
- package/dist/cli/commands/render.js +278 -0
- package/dist/cli/commands/render.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +93 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/compiler/compiler.d.ts +12 -0
- package/dist/compiler/compiler.d.ts.map +1 -0
- package/dist/compiler/compiler.js +146 -0
- package/dist/compiler/compiler.js.map +1 -0
- package/dist/compiler/index.d.ts +2 -0
- package/dist/compiler/index.d.ts.map +1 -0
- package/dist/compiler/index.js +2 -0
- package/dist/compiler/index.js.map +1 -0
- package/dist/config/config.d.ts +43 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +200 -0
- package/dist/config/config.js.map +1 -0
- package/dist/config/index.d.ts +2 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +2 -0
- package/dist/config/index.js.map +1 -0
- package/dist/errors.d.ts +49 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +168 -0
- package/dist/errors.js.map +1 -0
- package/dist/formatter/formatter.d.ts +13 -0
- package/dist/formatter/formatter.d.ts.map +1 -0
- package/dist/formatter/formatter.js +242 -0
- package/dist/formatter/formatter.js.map +1 -0
- package/dist/formatter/index.d.ts +2 -0
- package/dist/formatter/index.d.ts.map +1 -0
- package/dist/formatter/index.js +2 -0
- package/dist/formatter/index.js.map +1 -0
- package/dist/generators/index.d.ts +5 -0
- package/dist/generators/index.d.ts.map +1 -0
- package/dist/generators/index.js +5 -0
- package/dist/generators/index.js.map +1 -0
- package/dist/generators/midi.d.ts +3 -0
- package/dist/generators/midi.d.ts.map +1 -0
- package/dist/generators/midi.js +360 -0
- package/dist/generators/midi.js.map +1 -0
- package/dist/generators/musicxml.d.ts +3 -0
- package/dist/generators/musicxml.d.ts.map +1 -0
- package/dist/generators/musicxml.js +332 -0
- package/dist/generators/musicxml.js.map +1 -0
- package/dist/generators/tempo-midi.d.ts +3 -0
- package/dist/generators/tempo-midi.d.ts.map +1 -0
- package/dist/generators/tempo-midi.js +123 -0
- package/dist/generators/tempo-midi.js.map +1 -0
- package/dist/generators/vsqx.d.ts +3 -0
- package/dist/generators/vsqx.d.ts.map +1 -0
- package/dist/generators/vsqx.js +354 -0
- package/dist/generators/vsqx.js.map +1 -0
- package/dist/importers/index.d.ts +2 -0
- package/dist/importers/index.d.ts.map +1 -0
- package/dist/importers/index.js +3 -0
- package/dist/importers/index.js.map +1 -0
- package/dist/importers/musicxml.d.ts +4 -0
- package/dist/importers/musicxml.d.ts.map +1 -0
- package/dist/importers/musicxml.js +392 -0
- package/dist/importers/musicxml.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/interpreter/builtins/algorithmic.d.ts +12 -0
- package/dist/interpreter/builtins/algorithmic.d.ts.map +1 -0
- package/dist/interpreter/builtins/algorithmic.js +244 -0
- package/dist/interpreter/builtins/algorithmic.js.map +1 -0
- package/dist/interpreter/builtins/audio.d.ts +10 -0
- package/dist/interpreter/builtins/audio.d.ts.map +1 -0
- package/dist/interpreter/builtins/audio.js +169 -0
- package/dist/interpreter/builtins/audio.js.map +1 -0
- package/dist/interpreter/builtins/core.d.ts +15 -0
- package/dist/interpreter/builtins/core.d.ts.map +1 -0
- package/dist/interpreter/builtins/core.js +265 -0
- package/dist/interpreter/builtins/core.js.map +1 -0
- package/dist/interpreter/builtins/dynamics.d.ts +8 -0
- package/dist/interpreter/builtins/dynamics.d.ts.map +1 -0
- package/dist/interpreter/builtins/dynamics.js +86 -0
- package/dist/interpreter/builtins/dynamics.js.map +1 -0
- package/dist/interpreter/builtins/effects.d.ts +16 -0
- package/dist/interpreter/builtins/effects.d.ts.map +1 -0
- package/dist/interpreter/builtins/effects.js +220 -0
- package/dist/interpreter/builtins/effects.js.map +1 -0
- package/dist/interpreter/builtins/index.d.ts +16 -0
- package/dist/interpreter/builtins/index.d.ts.map +1 -0
- package/dist/interpreter/builtins/index.js +17 -0
- package/dist/interpreter/builtins/index.js.map +1 -0
- package/dist/interpreter/builtins/layout.d.ts +12 -0
- package/dist/interpreter/builtins/layout.d.ts.map +1 -0
- package/dist/interpreter/builtins/layout.js +175 -0
- package/dist/interpreter/builtins/layout.js.map +1 -0
- package/dist/interpreter/builtins/live.d.ts +11 -0
- package/dist/interpreter/builtins/live.d.ts.map +1 -0
- package/dist/interpreter/builtins/live.js +125 -0
- package/dist/interpreter/builtins/live.js.map +1 -0
- package/dist/interpreter/builtins/midi.d.ts +16 -0
- package/dist/interpreter/builtins/midi.d.ts.map +1 -0
- package/dist/interpreter/builtins/midi.js +320 -0
- package/dist/interpreter/builtins/midi.js.map +1 -0
- package/dist/interpreter/builtins/mixing.d.ts +6 -0
- package/dist/interpreter/builtins/mixing.d.ts.map +1 -0
- package/dist/interpreter/builtins/mixing.js +62 -0
- package/dist/interpreter/builtins/mixing.js.map +1 -0
- package/dist/interpreter/builtins/notation.d.ts +24 -0
- package/dist/interpreter/builtins/notation.d.ts.map +1 -0
- package/dist/interpreter/builtins/notation.js +251 -0
- package/dist/interpreter/builtins/notation.js.map +1 -0
- package/dist/interpreter/builtins/ornaments.d.ts +8 -0
- package/dist/interpreter/builtins/ornaments.d.ts.map +1 -0
- package/dist/interpreter/builtins/ornaments.js +155 -0
- package/dist/interpreter/builtins/ornaments.js.map +1 -0
- package/dist/interpreter/builtins/techniques.d.ts +11 -0
- package/dist/interpreter/builtins/techniques.d.ts.map +1 -0
- package/dist/interpreter/builtins/techniques.js +234 -0
- package/dist/interpreter/builtins/techniques.js.map +1 -0
- package/dist/interpreter/builtins/tuning.d.ts +7 -0
- package/dist/interpreter/builtins/tuning.d.ts.map +1 -0
- package/dist/interpreter/builtins/tuning.js +52 -0
- package/dist/interpreter/builtins/tuning.js.map +1 -0
- package/dist/interpreter/builtins/types.d.ts +27 -0
- package/dist/interpreter/builtins/types.d.ts.map +1 -0
- package/dist/interpreter/builtins/types.js +3 -0
- package/dist/interpreter/builtins/types.js.map +1 -0
- package/dist/interpreter/builtins/vocaloid.d.ts +10 -0
- package/dist/interpreter/builtins/vocaloid.d.ts.map +1 -0
- package/dist/interpreter/builtins/vocaloid.js +165 -0
- package/dist/interpreter/builtins/vocaloid.js.map +1 -0
- package/dist/interpreter/index.d.ts +4 -0
- package/dist/interpreter/index.d.ts.map +1 -0
- package/dist/interpreter/index.js +4 -0
- package/dist/interpreter/index.js.map +1 -0
- package/dist/interpreter/interpreter.d.ts +305 -0
- package/dist/interpreter/interpreter.d.ts.map +1 -0
- package/dist/interpreter/interpreter.js +8463 -0
- package/dist/interpreter/interpreter.js.map +1 -0
- package/dist/interpreter/runtime.d.ts +67 -0
- package/dist/interpreter/runtime.d.ts.map +1 -0
- package/dist/interpreter/runtime.js +88 -0
- package/dist/interpreter/runtime.js.map +1 -0
- package/dist/interpreter/scope.d.ts +21 -0
- package/dist/interpreter/scope.d.ts.map +1 -0
- package/dist/interpreter/scope.js +60 -0
- package/dist/interpreter/scope.js.map +1 -0
- package/dist/interpreter/trackState.d.ts +205 -0
- package/dist/interpreter/trackState.d.ts.map +1 -0
- package/dist/interpreter/trackState.js +12 -0
- package/dist/interpreter/trackState.js.map +1 -0
- package/dist/lexer/index.d.ts +2 -0
- package/dist/lexer/index.d.ts.map +1 -0
- package/dist/lexer/index.js +2 -0
- package/dist/lexer/index.js.map +1 -0
- package/dist/lexer/lexer.d.ts +30 -0
- package/dist/lexer/lexer.d.ts.map +1 -0
- package/dist/lexer/lexer.js +385 -0
- package/dist/lexer/lexer.js.map +1 -0
- package/dist/parser/index.d.ts +2 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +2 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/parser.d.ts +55 -0
- package/dist/parser/parser.d.ts.map +1 -0
- package/dist/parser/parser.js +896 -0
- package/dist/parser/parser.js.map +1 -0
- package/dist/types/ast.d.ts +220 -0
- package/dist/types/ast.d.ts.map +1 -0
- package/dist/types/ast.js +3 -0
- package/dist/types/ast.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/ir/advanced.d.ts +491 -0
- package/dist/types/ir/advanced.d.ts.map +1 -0
- package/dist/types/ir/advanced.js +3 -0
- package/dist/types/ir/advanced.js.map +1 -0
- package/dist/types/ir/algorithmic.d.ts +48 -0
- package/dist/types/ir/algorithmic.d.ts.map +1 -0
- package/dist/types/ir/algorithmic.js +3 -0
- package/dist/types/ir/algorithmic.js.map +1 -0
- package/dist/types/ir/analysis.d.ts +34 -0
- package/dist/types/ir/analysis.d.ts.map +1 -0
- package/dist/types/ir/analysis.js +3 -0
- package/dist/types/ir/analysis.js.map +1 -0
- package/dist/types/ir/audio.d.ts +249 -0
- package/dist/types/ir/audio.d.ts.map +1 -0
- package/dist/types/ir/audio.js +3 -0
- package/dist/types/ir/audio.js.map +1 -0
- package/dist/types/ir/automation.d.ts +46 -0
- package/dist/types/ir/automation.d.ts.map +1 -0
- package/dist/types/ir/automation.js +3 -0
- package/dist/types/ir/automation.js.map +1 -0
- package/dist/types/ir/collaboration.d.ts +20 -0
- package/dist/types/ir/collaboration.d.ts.map +1 -0
- package/dist/types/ir/collaboration.js +3 -0
- package/dist/types/ir/collaboration.js.map +1 -0
- package/dist/types/ir/core.d.ts +153 -0
- package/dist/types/ir/core.d.ts.map +1 -0
- package/dist/types/ir/core.js +3 -0
- package/dist/types/ir/core.js.map +1 -0
- package/dist/types/ir/effects.d.ts +169 -0
- package/dist/types/ir/effects.d.ts.map +1 -0
- package/dist/types/ir/effects.js +3 -0
- package/dist/types/ir/effects.js.map +1 -0
- package/dist/types/ir/extended.d.ts +104 -0
- package/dist/types/ir/extended.d.ts.map +1 -0
- package/dist/types/ir/extended.js +3 -0
- package/dist/types/ir/extended.js.map +1 -0
- package/dist/types/ir/index.d.ts +16 -0
- package/dist/types/ir/index.d.ts.map +1 -0
- package/dist/types/ir/index.js +17 -0
- package/dist/types/ir/index.js.map +1 -0
- package/dist/types/ir/mastering.d.ts +86 -0
- package/dist/types/ir/mastering.d.ts.map +1 -0
- package/dist/types/ir/mastering.js +3 -0
- package/dist/types/ir/mastering.js.map +1 -0
- package/dist/types/ir/midi.d.ts +79 -0
- package/dist/types/ir/midi.d.ts.map +1 -0
- package/dist/types/ir/midi.js +3 -0
- package/dist/types/ir/midi.js.map +1 -0
- package/dist/types/ir/notation.d.ts +963 -0
- package/dist/types/ir/notation.d.ts.map +1 -0
- package/dist/types/ir/notation.js +3 -0
- package/dist/types/ir/notation.js.map +1 -0
- package/dist/types/ir/recording.d.ts +48 -0
- package/dist/types/ir/recording.d.ts.map +1 -0
- package/dist/types/ir/recording.js +3 -0
- package/dist/types/ir/recording.js.map +1 -0
- package/dist/types/ir/sampling.d.ts +59 -0
- package/dist/types/ir/sampling.d.ts.map +1 -0
- package/dist/types/ir/sampling.js +3 -0
- package/dist/types/ir/sampling.js.map +1 -0
- package/dist/types/ir/sequencing.d.ts +118 -0
- package/dist/types/ir/sequencing.d.ts.map +1 -0
- package/dist/types/ir/sequencing.js +3 -0
- package/dist/types/ir/sequencing.js.map +1 -0
- package/dist/types/ir/sync.d.ts +39 -0
- package/dist/types/ir/sync.d.ts.map +1 -0
- package/dist/types/ir/sync.js +3 -0
- package/dist/types/ir/sync.js.map +1 -0
- package/dist/types/ir.d.ts +2 -0
- package/dist/types/ir.d.ts.map +1 -0
- package/dist/types/ir.js +3 -0
- package/dist/types/ir.js.map +1 -0
- package/dist/types/token.d.ts +72 -0
- package/dist/types/token.d.ts.map +1 -0
- package/dist/types/token.js +90 -0
- package/dist/types/token.js.map +1 -0
- package/dist/utils/stdlib.d.ts +18 -0
- package/dist/utils/stdlib.d.ts.map +1 -0
- package/dist/utils/stdlib.js +51 -0
- package/dist/utils/stdlib.js.map +1 -0
- package/lib/articulation.mf +46 -0
- package/lib/composition.mf +299 -0
- package/lib/curves.mf +183 -0
- package/lib/dynamics.mf +141 -0
- package/lib/expression.mf +221 -0
- package/lib/genres.mf +348 -0
- package/lib/notation.mf +224 -0
- package/lib/ornaments.mf +98 -0
- package/lib/patterns.mf +170 -0
- package/lib/rhythm.mf +269 -0
- package/lib/theory.mf +257 -0
- package/lib/utils.mf +140 -0
- 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
|
+
}
|