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
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
// Core builtin functions: title, ppq, tempo, timeSig, at, advance, note, rest, chord, drum
|
|
2
|
+
import { makeNull, toNumber } from '../runtime.js';
|
|
3
|
+
import { MFError, createError } from '../../errors.js';
|
|
4
|
+
import { DRUM_MAP } from '../trackState.js';
|
|
5
|
+
// Using 'any' for 'this' to avoid circular dependency and private member issues
|
|
6
|
+
export function builtinTitle(args, position) {
|
|
7
|
+
this.checkGlobalPhase(position);
|
|
8
|
+
const val = this.evaluate(args[0]);
|
|
9
|
+
if (val.type !== 'string') {
|
|
10
|
+
throw new MFError('TYPE', 'title() expects string', position, this.filePath);
|
|
11
|
+
}
|
|
12
|
+
this.ir.title = val.value;
|
|
13
|
+
return makeNull();
|
|
14
|
+
}
|
|
15
|
+
export function builtinPpq(args, position) {
|
|
16
|
+
this.checkGlobalPhase(position);
|
|
17
|
+
const val = this.evaluate(args[0]);
|
|
18
|
+
if (val.type !== 'int') {
|
|
19
|
+
throw new MFError('TYPE', 'ppq() expects int', position, this.filePath);
|
|
20
|
+
}
|
|
21
|
+
this.ir.ppq = val.value;
|
|
22
|
+
return makeNull();
|
|
23
|
+
}
|
|
24
|
+
export function builtinTempo(args, position) {
|
|
25
|
+
this.checkGlobalPhase(position);
|
|
26
|
+
if (args.length === 1) {
|
|
27
|
+
// tempo(bpm)
|
|
28
|
+
const bpm = this.evaluate(args[0]);
|
|
29
|
+
const bpmVal = toNumber(bpm);
|
|
30
|
+
this.ir.tempos.push({ tick: 0, bpm: bpmVal });
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// tempo(time, bpm)
|
|
34
|
+
const time = this.evaluate(args[0]);
|
|
35
|
+
const bpm = this.evaluate(args[1]);
|
|
36
|
+
if (time.type !== 'time') {
|
|
37
|
+
throw new MFError('TYPE', 'tempo() time must be Time', position, this.filePath);
|
|
38
|
+
}
|
|
39
|
+
const tick = this.timeToTick(time, position);
|
|
40
|
+
this.ir.tempos.push({ tick, bpm: toNumber(bpm) });
|
|
41
|
+
}
|
|
42
|
+
return makeNull();
|
|
43
|
+
}
|
|
44
|
+
export function builtinTimeSig(args, position) {
|
|
45
|
+
this.checkGlobalPhase(position);
|
|
46
|
+
if (args.length === 2) {
|
|
47
|
+
// timeSig(num, den)
|
|
48
|
+
const num = this.evaluate(args[0]);
|
|
49
|
+
const den = this.evaluate(args[1]);
|
|
50
|
+
if (num.type !== 'int' || den.type !== 'int') {
|
|
51
|
+
throw new MFError('TYPE', 'timeSig() expects int, int', position, this.filePath);
|
|
52
|
+
}
|
|
53
|
+
this.ir.timeSigs.push({ tick: 0, numerator: num.value, denominator: den.value });
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
// timeSig(time, num, den)
|
|
57
|
+
const time = this.evaluate(args[0]);
|
|
58
|
+
const num = this.evaluate(args[1]);
|
|
59
|
+
const den = this.evaluate(args[2]);
|
|
60
|
+
if (time.type !== 'time') {
|
|
61
|
+
throw new MFError('TYPE', 'timeSig() time must be Time', position, this.filePath);
|
|
62
|
+
}
|
|
63
|
+
// Must be at bar start
|
|
64
|
+
if (time.beat !== 1 || time.sub !== 0) {
|
|
65
|
+
throw createError('E020', 'timeSig must be at bar start (beat=1, sub=0)', position, this.filePath);
|
|
66
|
+
}
|
|
67
|
+
const tick = this.timeToTick(time, position);
|
|
68
|
+
if (num.type !== 'int' || den.type !== 'int') {
|
|
69
|
+
throw new MFError('TYPE', 'timeSig() expects int, int', position, this.filePath);
|
|
70
|
+
}
|
|
71
|
+
this.ir.timeSigs.push({ tick, numerator: num.value, denominator: den.value });
|
|
72
|
+
}
|
|
73
|
+
return makeNull();
|
|
74
|
+
}
|
|
75
|
+
export function builtinAt(args, position) {
|
|
76
|
+
this.checkTrackPhase(position);
|
|
77
|
+
const time = this.evaluate(args[0]);
|
|
78
|
+
if (time.type !== 'time') {
|
|
79
|
+
throw new MFError('TYPE', 'at() expects Time', position, this.filePath);
|
|
80
|
+
}
|
|
81
|
+
const tick = this.timeToTick(time, position);
|
|
82
|
+
this.currentTrack.cursor = tick;
|
|
83
|
+
return makeNull();
|
|
84
|
+
}
|
|
85
|
+
export function builtinAtTick(args, position) {
|
|
86
|
+
this.checkTrackPhase(position);
|
|
87
|
+
const tick = this.evaluate(args[0]);
|
|
88
|
+
if (tick.type !== 'int') {
|
|
89
|
+
throw new MFError('TYPE', 'atTick() expects int', position, this.filePath);
|
|
90
|
+
}
|
|
91
|
+
this.currentTrack.cursor = tick.value;
|
|
92
|
+
return makeNull();
|
|
93
|
+
}
|
|
94
|
+
export function builtinAdvance(args, position) {
|
|
95
|
+
this.checkTrackPhase(position);
|
|
96
|
+
const dur = this.evaluate(args[0]);
|
|
97
|
+
if (dur.type !== 'dur') {
|
|
98
|
+
throw new MFError('TYPE', 'advance() expects Dur', position, this.filePath);
|
|
99
|
+
}
|
|
100
|
+
const ticks = this.durToTicks(dur, position);
|
|
101
|
+
this.currentTrack.cursor += ticks;
|
|
102
|
+
return makeNull();
|
|
103
|
+
}
|
|
104
|
+
export function builtinAdvanceTick(args, position) {
|
|
105
|
+
this.checkTrackPhase(position);
|
|
106
|
+
const dt = this.evaluate(args[0]);
|
|
107
|
+
if (dt.type !== 'int') {
|
|
108
|
+
throw new MFError('TYPE', 'advanceTick() expects int', position, this.filePath);
|
|
109
|
+
}
|
|
110
|
+
this.currentTrack.cursor += dt.value;
|
|
111
|
+
return makeNull();
|
|
112
|
+
}
|
|
113
|
+
export function builtinNote(args, position) {
|
|
114
|
+
this.checkTrackPhase(position);
|
|
115
|
+
const track = this.currentTrack;
|
|
116
|
+
const pitch = this.evaluate(args[0]);
|
|
117
|
+
const dur = this.evaluate(args[1]);
|
|
118
|
+
if (pitch.type !== 'pitch') {
|
|
119
|
+
throw new MFError('TYPE', 'note() pitch must be Pitch', position, this.filePath);
|
|
120
|
+
}
|
|
121
|
+
if (dur.type !== 'dur') {
|
|
122
|
+
throw new MFError('TYPE', 'note() duration must be Dur', position, this.filePath);
|
|
123
|
+
}
|
|
124
|
+
// Validate pitch range
|
|
125
|
+
if (pitch.midi < 0 || pitch.midi > 127) {
|
|
126
|
+
throw createError('E110', `Pitch ${pitch.midi} out of range 0..127`, position, this.filePath);
|
|
127
|
+
}
|
|
128
|
+
const durTicks = this.durToTicks(dur, position);
|
|
129
|
+
const tick = track.cursor;
|
|
130
|
+
if (track.kind === 'vocal') {
|
|
131
|
+
// Vocal needs lyric
|
|
132
|
+
if (args.length < 3) {
|
|
133
|
+
throw createError('E210', 'Vocal note requires lyric', position, this.filePath);
|
|
134
|
+
}
|
|
135
|
+
const lyric = this.evaluate(args[2]);
|
|
136
|
+
if (lyric.type !== 'string' || lyric.value === '') {
|
|
137
|
+
throw createError('E210', 'Vocal lyric must be non-empty string', position, this.filePath);
|
|
138
|
+
}
|
|
139
|
+
// Check for overlap
|
|
140
|
+
this.checkVocalOverlap(track, tick, durTicks, position);
|
|
141
|
+
const event = {
|
|
142
|
+
type: 'note',
|
|
143
|
+
tick,
|
|
144
|
+
dur: durTicks,
|
|
145
|
+
key: pitch.midi,
|
|
146
|
+
lyric: lyric.value,
|
|
147
|
+
};
|
|
148
|
+
track.events.push(event);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// MIDI track
|
|
152
|
+
const vel = args.length >= 3
|
|
153
|
+
? toNumber(this.evaluate(args[2]))
|
|
154
|
+
: track.defaultVel ?? 96;
|
|
155
|
+
const event = {
|
|
156
|
+
type: 'note',
|
|
157
|
+
tick,
|
|
158
|
+
dur: durTicks,
|
|
159
|
+
key: pitch.midi,
|
|
160
|
+
vel,
|
|
161
|
+
};
|
|
162
|
+
track.events.push(event);
|
|
163
|
+
}
|
|
164
|
+
track.cursor += durTicks;
|
|
165
|
+
return makeNull();
|
|
166
|
+
}
|
|
167
|
+
export function builtinRest(args, position) {
|
|
168
|
+
this.checkTrackPhase(position);
|
|
169
|
+
const track = this.currentTrack;
|
|
170
|
+
const dur = this.evaluate(args[0]);
|
|
171
|
+
if (dur.type !== 'dur') {
|
|
172
|
+
throw new MFError('TYPE', 'rest() expects Dur', position, this.filePath);
|
|
173
|
+
}
|
|
174
|
+
const durTicks = this.durToTicks(dur, position);
|
|
175
|
+
const tick = track.cursor;
|
|
176
|
+
const event = {
|
|
177
|
+
type: 'rest',
|
|
178
|
+
tick,
|
|
179
|
+
dur: durTicks,
|
|
180
|
+
};
|
|
181
|
+
track.events.push(event);
|
|
182
|
+
track.cursor += durTicks;
|
|
183
|
+
return makeNull();
|
|
184
|
+
}
|
|
185
|
+
export function builtinChord(args, position) {
|
|
186
|
+
this.checkTrackPhase(position);
|
|
187
|
+
const track = this.currentTrack;
|
|
188
|
+
const pitchArr = this.evaluate(args[0]);
|
|
189
|
+
const dur = this.evaluate(args[1]);
|
|
190
|
+
if (pitchArr.type !== 'array') {
|
|
191
|
+
throw new MFError('TYPE', 'chord() expects array of pitches', position, this.filePath);
|
|
192
|
+
}
|
|
193
|
+
if (dur.type !== 'dur') {
|
|
194
|
+
throw new MFError('TYPE', 'chord() duration must be Dur', position, this.filePath);
|
|
195
|
+
}
|
|
196
|
+
const durTicks = this.durToTicks(dur, position);
|
|
197
|
+
const tick = track.cursor;
|
|
198
|
+
const vel = args.length >= 3
|
|
199
|
+
? toNumber(this.evaluate(args[2]))
|
|
200
|
+
: track.defaultVel ?? 96;
|
|
201
|
+
for (const p of pitchArr.elements) {
|
|
202
|
+
if (p.type !== 'pitch') {
|
|
203
|
+
throw new MFError('TYPE', 'chord() array must contain only Pitch', position, this.filePath);
|
|
204
|
+
}
|
|
205
|
+
if (p.midi < 0 || p.midi > 127) {
|
|
206
|
+
throw createError('E110', `Pitch ${p.midi} out of range 0..127`, position, this.filePath);
|
|
207
|
+
}
|
|
208
|
+
const event = {
|
|
209
|
+
type: 'note',
|
|
210
|
+
tick,
|
|
211
|
+
dur: durTicks,
|
|
212
|
+
key: p.midi,
|
|
213
|
+
vel,
|
|
214
|
+
};
|
|
215
|
+
track.events.push(event);
|
|
216
|
+
}
|
|
217
|
+
track.cursor += durTicks;
|
|
218
|
+
return makeNull();
|
|
219
|
+
}
|
|
220
|
+
export function builtinDrum(args, position, rawArgs) {
|
|
221
|
+
this.checkTrackPhase(position);
|
|
222
|
+
const track = this.currentTrack;
|
|
223
|
+
// Get drum name from raw AST to get the identifier name
|
|
224
|
+
const drumNameExpr = rawArgs[0];
|
|
225
|
+
let drumName;
|
|
226
|
+
if (drumNameExpr.kind === 'Identifier') {
|
|
227
|
+
drumName = drumNameExpr.name;
|
|
228
|
+
}
|
|
229
|
+
else if (drumNameExpr.kind === 'StringLiteral') {
|
|
230
|
+
drumName = drumNameExpr.value;
|
|
231
|
+
}
|
|
232
|
+
else {
|
|
233
|
+
const evaluated = this.evaluate(drumNameExpr);
|
|
234
|
+
if (evaluated.type === 'string') {
|
|
235
|
+
drumName = evaluated.value;
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
throw new MFError('TYPE', 'drum() expects drum name identifier or string', position, this.filePath);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
const dur = this.evaluate(args[1]);
|
|
242
|
+
if (dur.type !== 'dur') {
|
|
243
|
+
throw new MFError('TYPE', 'drum() duration must be Dur', position, this.filePath);
|
|
244
|
+
}
|
|
245
|
+
const midiNote = DRUM_MAP[drumName];
|
|
246
|
+
if (midiNote === undefined) {
|
|
247
|
+
throw createError('E110', `Unknown drum name: ${drumName}`, position, this.filePath);
|
|
248
|
+
}
|
|
249
|
+
const durTicks = this.durToTicks(dur, position);
|
|
250
|
+
const tick = track.cursor;
|
|
251
|
+
const vel = args.length >= 3
|
|
252
|
+
? toNumber(this.evaluate(args[2]))
|
|
253
|
+
: track.defaultVel ?? 96;
|
|
254
|
+
const event = {
|
|
255
|
+
type: 'note',
|
|
256
|
+
tick,
|
|
257
|
+
dur: durTicks,
|
|
258
|
+
key: midiNote,
|
|
259
|
+
vel,
|
|
260
|
+
};
|
|
261
|
+
track.events.push(event);
|
|
262
|
+
track.cursor += durTicks;
|
|
263
|
+
return makeNull();
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.js","sourceRoot":"","sources":["../../../src/interpreter/builtins/core.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Expression } from '../../types/ast.js';
|
|
2
|
+
import type { Articulation } from '../../types/ir.js';
|
|
3
|
+
import { RuntimeValue } from '../runtime.js';
|
|
4
|
+
export declare function builtinDynamic(this: any, args: Expression[], position: any): RuntimeValue;
|
|
5
|
+
export declare function builtinCrescendo(this: any, args: Expression[], position: any): RuntimeValue;
|
|
6
|
+
export declare function builtinDecrescendo(this: any, args: Expression[], position: any): RuntimeValue;
|
|
7
|
+
export declare function builtinArticulatedNote(this: any, args: Expression[], position: any, articulation: Articulation): RuntimeValue;
|
|
8
|
+
//# sourceMappingURL=dynamics.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamics.d.ts","sourceRoot":"","sources":["../../../src/interpreter/builtins/dynamics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAA6C,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjG,OAAO,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC;AAGjE,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAiCzF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAsB3F;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAsB7F;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,GAAG,EACT,IAAI,EAAE,UAAU,EAAE,EAClB,QAAQ,EAAE,GAAG,EACb,YAAY,EAAE,YAAY,GACzB,YAAY,CAgBd"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// Dynamics builtin functions: dynamic, crescendo, decrescendo, articulations
|
|
2
|
+
import { makeNull } from '../runtime.js';
|
|
3
|
+
import { MFError } from '../../errors.js';
|
|
4
|
+
export function builtinDynamic(args, position) {
|
|
5
|
+
this.checkTrackPhase(position);
|
|
6
|
+
const track = this.currentTrack;
|
|
7
|
+
const markExpr = args[0];
|
|
8
|
+
let markStr;
|
|
9
|
+
if (markExpr.kind === 'Identifier') {
|
|
10
|
+
markStr = markExpr.name;
|
|
11
|
+
}
|
|
12
|
+
else {
|
|
13
|
+
const mark = this.evaluate(args[0]);
|
|
14
|
+
if (mark.type !== 'string') {
|
|
15
|
+
throw new MFError('TYPE', 'dynamic() mark must be string or identifier', position, this.filePath);
|
|
16
|
+
}
|
|
17
|
+
markStr = mark.value;
|
|
18
|
+
}
|
|
19
|
+
const validMarks = ['ppp', 'pp', 'p', 'mp', 'mf', 'f', 'ff', 'fff', 'sfz', 'fp'];
|
|
20
|
+
if (!validMarks.includes(markStr)) {
|
|
21
|
+
throw new MFError('TYPE', `Unknown dynamic mark: ${markStr}. Valid: ${validMarks.join(', ')}`, position, this.filePath);
|
|
22
|
+
}
|
|
23
|
+
if (!track.notation) {
|
|
24
|
+
track.notation = { dynamics: [], slurs: [], crescendos: [], ties: [], hairpins: [], articulations: [] };
|
|
25
|
+
}
|
|
26
|
+
const event = {
|
|
27
|
+
type: 'dynamic',
|
|
28
|
+
tick: track.cursor,
|
|
29
|
+
mark: markStr,
|
|
30
|
+
};
|
|
31
|
+
track.notation.dynamics.push(event);
|
|
32
|
+
return makeNull();
|
|
33
|
+
}
|
|
34
|
+
export function builtinCrescendo(args, position) {
|
|
35
|
+
this.checkTrackPhase(position);
|
|
36
|
+
const track = this.currentTrack;
|
|
37
|
+
const dur = this.evaluate(args[0]);
|
|
38
|
+
if (dur.type !== 'dur') {
|
|
39
|
+
throw new MFError('TYPE', 'crescendo() duration must be Dur', position, this.filePath);
|
|
40
|
+
}
|
|
41
|
+
const durTicks = this.durToTicks(dur, position);
|
|
42
|
+
if (!track.notation) {
|
|
43
|
+
track.notation = { dynamics: [], slurs: [], crescendos: [], ties: [], hairpins: [], articulations: [] };
|
|
44
|
+
}
|
|
45
|
+
const event = {
|
|
46
|
+
type: 'crescendo',
|
|
47
|
+
tick: track.cursor,
|
|
48
|
+
endTick: track.cursor + durTicks,
|
|
49
|
+
};
|
|
50
|
+
track.notation.crescendos.push(event);
|
|
51
|
+
return makeNull();
|
|
52
|
+
}
|
|
53
|
+
export function builtinDecrescendo(args, position) {
|
|
54
|
+
this.checkTrackPhase(position);
|
|
55
|
+
const track = this.currentTrack;
|
|
56
|
+
const dur = this.evaluate(args[0]);
|
|
57
|
+
if (dur.type !== 'dur') {
|
|
58
|
+
throw new MFError('TYPE', 'decrescendo() duration must be Dur', position, this.filePath);
|
|
59
|
+
}
|
|
60
|
+
const durTicks = this.durToTicks(dur, position);
|
|
61
|
+
if (!track.notation) {
|
|
62
|
+
track.notation = { dynamics: [], slurs: [], crescendos: [], ties: [], hairpins: [], articulations: [] };
|
|
63
|
+
}
|
|
64
|
+
const event = {
|
|
65
|
+
type: 'decrescendo',
|
|
66
|
+
tick: track.cursor,
|
|
67
|
+
endTick: track.cursor + durTicks,
|
|
68
|
+
};
|
|
69
|
+
track.notation.crescendos.push(event);
|
|
70
|
+
return makeNull();
|
|
71
|
+
}
|
|
72
|
+
export function builtinArticulatedNote(args, position, articulation) {
|
|
73
|
+
this.checkTrackPhase(position);
|
|
74
|
+
const track = this.currentTrack;
|
|
75
|
+
// Set articulation for next note
|
|
76
|
+
if (!track.notation) {
|
|
77
|
+
track.notation = { dynamics: [], slurs: [], crescendos: [], ties: [], hairpins: [], articulations: [] };
|
|
78
|
+
}
|
|
79
|
+
track.notation.articulations.push({
|
|
80
|
+
type: 'articulation',
|
|
81
|
+
tick: track.cursor,
|
|
82
|
+
kind: articulation,
|
|
83
|
+
});
|
|
84
|
+
return makeNull();
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=dynamics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dynamics.js","sourceRoot":"","sources":["../../../src/interpreter/builtins/dynamics.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Expression } from '../../types/ast.js';
|
|
2
|
+
import { RuntimeValue } from '../runtime.js';
|
|
3
|
+
export declare function builtinReverb(this: any, args: Expression[], position: any): RuntimeValue;
|
|
4
|
+
export declare function builtinDelay(this: any, args: Expression[], position: any): RuntimeValue;
|
|
5
|
+
export declare function builtinEQ(this: any, args: Expression[], position: any): RuntimeValue;
|
|
6
|
+
export declare function builtinCompressor(this: any, args: Expression[], position: any): RuntimeValue;
|
|
7
|
+
export declare function builtinPhaser(this: any, args: Expression[], position: any): RuntimeValue;
|
|
8
|
+
export declare function builtinFlanger(this: any, args: Expression[], position: any): RuntimeValue;
|
|
9
|
+
export declare function builtinChorus(this: any, args: Expression[], position: any): RuntimeValue;
|
|
10
|
+
export declare function builtinDistortion(this: any, args: Expression[], position: any): RuntimeValue;
|
|
11
|
+
export declare function builtinFilter(this: any, args: Expression[], position: any): RuntimeValue;
|
|
12
|
+
export declare function builtinSidechain(this: any, args: Expression[], position: any): RuntimeValue;
|
|
13
|
+
export declare function builtinLimiter(this: any, args: Expression[], position: any): RuntimeValue;
|
|
14
|
+
export declare function builtinMaximizer(this: any, args: Expression[], position: any): RuntimeValue;
|
|
15
|
+
export declare function builtinEQBand(this: any, args: Expression[], position: any): RuntimeValue;
|
|
16
|
+
//# sourceMappingURL=effects.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"effects.d.ts","sourceRoot":"","sources":["../../../src/interpreter/builtins/effects.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAsB,MAAM,eAAe,CAAC;AAGjE,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAmBxF;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAmBvF;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAmBpF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAoB5F;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAiBxF;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAiBzF;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAiBxF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAgB5F;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAoBxF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAuB3F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAmBzF;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAkB3F;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,GAAG,GAAG,YAAY,CAoBxF"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
// Effects builtin functions: reverb, delay, eq, compressor, phaser, flanger, chorus, distortion, filter, sidechain, limiter, maximizer, eqBand
|
|
2
|
+
import { makeNull, toNumber } from '../runtime.js';
|
|
3
|
+
import { MFError } from '../../errors.js';
|
|
4
|
+
export function builtinReverb(args, position) {
|
|
5
|
+
this.checkTrackPhase(position);
|
|
6
|
+
const track = this.currentTrack;
|
|
7
|
+
const roomSize = args.length > 0 ? toNumber(this.evaluate(args[0])) / 127 : 0.5;
|
|
8
|
+
const damping = args.length > 1 ? toNumber(this.evaluate(args[1])) / 127 : 0.5;
|
|
9
|
+
const wetDry = args.length > 2 ? toNumber(this.evaluate(args[2])) / 127 : 0.3;
|
|
10
|
+
if (!track.effects) {
|
|
11
|
+
track.effects = [];
|
|
12
|
+
}
|
|
13
|
+
track.effects.push({
|
|
14
|
+
type: 'effect',
|
|
15
|
+
effectType: 'reverb',
|
|
16
|
+
params: { roomSize, damping, wetDry },
|
|
17
|
+
});
|
|
18
|
+
return makeNull();
|
|
19
|
+
}
|
|
20
|
+
export function builtinDelay(args, position) {
|
|
21
|
+
this.checkTrackPhase(position);
|
|
22
|
+
const track = this.currentTrack;
|
|
23
|
+
const time = args.length > 0 ? toNumber(this.evaluate(args[0])) : 250; // ms
|
|
24
|
+
const feedback = args.length > 1 ? toNumber(this.evaluate(args[1])) / 127 : 0.4;
|
|
25
|
+
const wetDry = args.length > 2 ? toNumber(this.evaluate(args[2])) / 127 : 0.3;
|
|
26
|
+
if (!track.effects) {
|
|
27
|
+
track.effects = [];
|
|
28
|
+
}
|
|
29
|
+
track.effects.push({
|
|
30
|
+
type: 'effect',
|
|
31
|
+
effectType: 'delay',
|
|
32
|
+
params: { time, feedback, wetDry },
|
|
33
|
+
});
|
|
34
|
+
return makeNull();
|
|
35
|
+
}
|
|
36
|
+
export function builtinEQ(args, position) {
|
|
37
|
+
this.checkTrackPhase(position);
|
|
38
|
+
const track = this.currentTrack;
|
|
39
|
+
const lowGain = args.length > 0 ? toNumber(this.evaluate(args[0])) - 64 : 0;
|
|
40
|
+
const midGain = args.length > 1 ? toNumber(this.evaluate(args[1])) - 64 : 0;
|
|
41
|
+
const highGain = args.length > 2 ? toNumber(this.evaluate(args[2])) - 64 : 0;
|
|
42
|
+
if (!track.effects) {
|
|
43
|
+
track.effects = [];
|
|
44
|
+
}
|
|
45
|
+
track.effects.push({
|
|
46
|
+
type: 'effect',
|
|
47
|
+
effectType: 'eq',
|
|
48
|
+
params: { lowGain, midGain, highGain },
|
|
49
|
+
});
|
|
50
|
+
return makeNull();
|
|
51
|
+
}
|
|
52
|
+
export function builtinCompressor(args, position) {
|
|
53
|
+
this.checkTrackPhase(position);
|
|
54
|
+
const track = this.currentTrack;
|
|
55
|
+
const threshold = args.length > 0 ? toNumber(this.evaluate(args[0])) : -20; // dB
|
|
56
|
+
const ratio = args.length > 1 ? toNumber(this.evaluate(args[1])) : 4;
|
|
57
|
+
const attack = args.length > 2 ? toNumber(this.evaluate(args[2])) : 10; // ms
|
|
58
|
+
const release = args.length > 3 ? toNumber(this.evaluate(args[3])) : 100; // ms
|
|
59
|
+
if (!track.effects) {
|
|
60
|
+
track.effects = [];
|
|
61
|
+
}
|
|
62
|
+
track.effects.push({
|
|
63
|
+
type: 'effect',
|
|
64
|
+
effectType: 'compressor',
|
|
65
|
+
params: { threshold, ratio, attack, release },
|
|
66
|
+
});
|
|
67
|
+
return makeNull();
|
|
68
|
+
}
|
|
69
|
+
export function builtinPhaser(args, position) {
|
|
70
|
+
this.checkTrackPhase(position);
|
|
71
|
+
const track = this.currentTrack;
|
|
72
|
+
const rate = args.length > 0 ? toNumber(this.evaluate(args[0])) : 0.5;
|
|
73
|
+
const depth = args.length > 1 ? toNumber(this.evaluate(args[1])) : 50;
|
|
74
|
+
const feedback = args.length > 2 ? toNumber(this.evaluate(args[2])) : 50;
|
|
75
|
+
const stages = args.length > 3 ? Math.floor(toNumber(this.evaluate(args[3]))) : 4;
|
|
76
|
+
if (!track.effects)
|
|
77
|
+
track.effects = [];
|
|
78
|
+
track.effects.push({
|
|
79
|
+
type: 'effect',
|
|
80
|
+
effectType: 'phaser',
|
|
81
|
+
params: { rate, depth, feedback, stages },
|
|
82
|
+
});
|
|
83
|
+
return makeNull();
|
|
84
|
+
}
|
|
85
|
+
export function builtinFlanger(args, position) {
|
|
86
|
+
this.checkTrackPhase(position);
|
|
87
|
+
const track = this.currentTrack;
|
|
88
|
+
const rate = args.length > 0 ? toNumber(this.evaluate(args[0])) : 0.25;
|
|
89
|
+
const depth = args.length > 1 ? toNumber(this.evaluate(args[1])) : 50;
|
|
90
|
+
const feedback = args.length > 2 ? toNumber(this.evaluate(args[2])) : 50;
|
|
91
|
+
const mix = args.length > 3 ? toNumber(this.evaluate(args[3])) : 50;
|
|
92
|
+
if (!track.effects)
|
|
93
|
+
track.effects = [];
|
|
94
|
+
track.effects.push({
|
|
95
|
+
type: 'effect',
|
|
96
|
+
effectType: 'flanger',
|
|
97
|
+
params: { rate, depth, feedback, mix },
|
|
98
|
+
});
|
|
99
|
+
return makeNull();
|
|
100
|
+
}
|
|
101
|
+
export function builtinChorus(args, position) {
|
|
102
|
+
this.checkTrackPhase(position);
|
|
103
|
+
const track = this.currentTrack;
|
|
104
|
+
const rate = args.length > 0 ? toNumber(this.evaluate(args[0])) : 1.0;
|
|
105
|
+
const depth = args.length > 1 ? toNumber(this.evaluate(args[1])) : 50;
|
|
106
|
+
const voices = args.length > 2 ? Math.floor(toNumber(this.evaluate(args[2]))) : 3;
|
|
107
|
+
const mix = args.length > 3 ? toNumber(this.evaluate(args[3])) : 50;
|
|
108
|
+
if (!track.effects)
|
|
109
|
+
track.effects = [];
|
|
110
|
+
track.effects.push({
|
|
111
|
+
type: 'effect',
|
|
112
|
+
effectType: 'chorus',
|
|
113
|
+
params: { rate, depth, voices, mix },
|
|
114
|
+
});
|
|
115
|
+
return makeNull();
|
|
116
|
+
}
|
|
117
|
+
export function builtinDistortion(args, position) {
|
|
118
|
+
this.checkTrackPhase(position);
|
|
119
|
+
const track = this.currentTrack;
|
|
120
|
+
const drive = args.length > 0 ? toNumber(this.evaluate(args[0])) : 50;
|
|
121
|
+
const tone = args.length > 1 ? toNumber(this.evaluate(args[1])) : 50;
|
|
122
|
+
const mix = args.length > 2 ? toNumber(this.evaluate(args[2])) : 100;
|
|
123
|
+
if (!track.effects)
|
|
124
|
+
track.effects = [];
|
|
125
|
+
track.effects.push({
|
|
126
|
+
type: 'effect',
|
|
127
|
+
effectType: 'distortion',
|
|
128
|
+
params: { drive, tone, mix },
|
|
129
|
+
});
|
|
130
|
+
return makeNull();
|
|
131
|
+
}
|
|
132
|
+
export function builtinFilter(args, position) {
|
|
133
|
+
this.checkTrackPhase(position);
|
|
134
|
+
const track = this.currentTrack;
|
|
135
|
+
const filterType = this.evaluate(args[0]);
|
|
136
|
+
const cutoff = args.length > 1 ? toNumber(this.evaluate(args[1])) : 1000;
|
|
137
|
+
const resonance = args.length > 2 ? toNumber(this.evaluate(args[2])) : 50;
|
|
138
|
+
if (filterType.type !== 'string') {
|
|
139
|
+
throw new MFError('TYPE', 'filter() type must be string', position, this.filePath);
|
|
140
|
+
}
|
|
141
|
+
if (!track.effects)
|
|
142
|
+
track.effects = [];
|
|
143
|
+
track.effects.push({
|
|
144
|
+
type: 'effect',
|
|
145
|
+
effectType: 'filter',
|
|
146
|
+
params: { filterType: filterType.value, cutoff, resonance },
|
|
147
|
+
});
|
|
148
|
+
return makeNull();
|
|
149
|
+
}
|
|
150
|
+
export function builtinSidechain(args, position) {
|
|
151
|
+
this.checkTrackPhase(position);
|
|
152
|
+
const track = this.currentTrack;
|
|
153
|
+
const sourceTrack = this.evaluate(args[0]);
|
|
154
|
+
const threshold = args.length > 1 ? toNumber(this.evaluate(args[1])) : -20;
|
|
155
|
+
const ratio = args.length > 2 ? toNumber(this.evaluate(args[2])) : 4;
|
|
156
|
+
const attack = args.length > 3 ? toNumber(this.evaluate(args[3])) : 10;
|
|
157
|
+
const release = args.length > 4 ? toNumber(this.evaluate(args[4])) : 100;
|
|
158
|
+
if (sourceTrack.type !== 'string') {
|
|
159
|
+
throw new MFError('TYPE', 'sidechain() source must be string', position, this.filePath);
|
|
160
|
+
}
|
|
161
|
+
// Store as effect with sidechain params
|
|
162
|
+
if (!track.effects)
|
|
163
|
+
track.effects = [];
|
|
164
|
+
track.effects.push({
|
|
165
|
+
type: 'effect',
|
|
166
|
+
effectType: 'compressor',
|
|
167
|
+
params: { threshold, ratio, attack, release, sidechain: sourceTrack.value },
|
|
168
|
+
});
|
|
169
|
+
return makeNull();
|
|
170
|
+
}
|
|
171
|
+
export function builtinLimiter(args, position) {
|
|
172
|
+
this.checkTrackPhase(position);
|
|
173
|
+
const track = this.currentTrack;
|
|
174
|
+
const threshold = toNumber(this.evaluate(args[0]));
|
|
175
|
+
const ceiling = toNumber(this.evaluate(args[1]));
|
|
176
|
+
const release = args.length > 2 ? toNumber(this.evaluate(args[2])) : 100;
|
|
177
|
+
if (!track.effects) {
|
|
178
|
+
track.effects = [];
|
|
179
|
+
}
|
|
180
|
+
track.effects.push({
|
|
181
|
+
type: 'effect',
|
|
182
|
+
effectType: 'limiter',
|
|
183
|
+
params: { threshold, ceiling, release },
|
|
184
|
+
});
|
|
185
|
+
return makeNull();
|
|
186
|
+
}
|
|
187
|
+
export function builtinMaximizer(args, position) {
|
|
188
|
+
this.checkTrackPhase(position);
|
|
189
|
+
const track = this.currentTrack;
|
|
190
|
+
const threshold = toNumber(this.evaluate(args[0]));
|
|
191
|
+
const ceiling = toNumber(this.evaluate(args[1]));
|
|
192
|
+
if (!track.effects) {
|
|
193
|
+
track.effects = [];
|
|
194
|
+
}
|
|
195
|
+
track.effects.push({
|
|
196
|
+
type: 'effect',
|
|
197
|
+
effectType: 'limiter',
|
|
198
|
+
params: { threshold, ceiling, release: 50, isMaximizer: 1 },
|
|
199
|
+
});
|
|
200
|
+
return makeNull();
|
|
201
|
+
}
|
|
202
|
+
export function builtinEQBand(args, position) {
|
|
203
|
+
this.checkTrackPhase(position);
|
|
204
|
+
const track = this.currentTrack;
|
|
205
|
+
const freq = toNumber(this.evaluate(args[0]));
|
|
206
|
+
const gain = toNumber(this.evaluate(args[1]));
|
|
207
|
+
const q = args.length > 2 ? toNumber(this.evaluate(args[2])) : 1;
|
|
208
|
+
const bandType = args.length > 3 ? this.evaluate(args[3]) : { type: 'string', value: 'peak' };
|
|
209
|
+
if (track.linearPhaseEQs && track.linearPhaseEQs.length > 0) {
|
|
210
|
+
const eq = track.linearPhaseEQs[track.linearPhaseEQs.length - 1];
|
|
211
|
+
eq.bands.push({
|
|
212
|
+
frequency: freq,
|
|
213
|
+
gain,
|
|
214
|
+
q,
|
|
215
|
+
type: bandType.value || 'peak',
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
return makeNull();
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=effects.js.map
|