@devaloop/devalang 0.0.1-beta.2 → 0.1.1
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/README.md +177 -146
- package/out-tsc/api.d.ts +180 -0
- package/out-tsc/api.d.ts.map +1 -0
- package/out-tsc/api.js +286 -0
- package/out-tsc/api.js.map +1 -0
- package/out-tsc/bin/index.d.ts +12 -0
- package/out-tsc/bin/index.d.ts.map +1 -0
- package/out-tsc/bin/index.js +20 -54
- package/out-tsc/bin/index.js.map +1 -0
- package/out-tsc/examples/basic-usage.d.ts +8 -0
- package/out-tsc/examples/basic-usage.d.ts.map +1 -0
- package/out-tsc/examples/basic-usage.js +113 -0
- package/out-tsc/examples/basic-usage.js.map +1 -0
- package/out-tsc/index.d.ts +19 -5
- package/out-tsc/index.d.ts.map +1 -0
- package/out-tsc/index.js +24 -6
- package/out-tsc/index.js.map +1 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts +7 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts.map +1 -0
- package/out-tsc/scripts/copy-wasm-dts.js +36 -32
- package/out-tsc/scripts/copy-wasm-dts.js.map +1 -0
- package/out-tsc/scripts/postinstall.d.ts +1 -0
- package/out-tsc/scripts/postinstall.d.ts.map +1 -0
- package/out-tsc/scripts/postinstall.js +4 -1
- package/out-tsc/scripts/postinstall.js.map +1 -0
- package/out-tsc/scripts/version/bump.d.ts +5 -1
- package/out-tsc/scripts/version/bump.d.ts.map +1 -0
- package/out-tsc/scripts/version/bump.js +114 -44
- package/out-tsc/scripts/version/bump.js.map +1 -0
- package/out-tsc/scripts/version/fetch.d.ts +12 -1
- package/out-tsc/scripts/version/fetch.d.ts.map +1 -0
- package/out-tsc/scripts/version/fetch.js +68 -24
- package/out-tsc/scripts/version/fetch.js.map +1 -0
- package/out-tsc/scripts/version/index.d.ts +6 -0
- package/out-tsc/scripts/version/index.d.ts.map +1 -0
- package/out-tsc/scripts/version/index.js +44 -22
- package/out-tsc/scripts/version/index.js.map +1 -0
- package/out-tsc/scripts/version/sync.d.ts +5 -1
- package/out-tsc/scripts/version/sync.d.ts.map +1 -0
- package/out-tsc/scripts/version/sync.js +78 -29
- package/out-tsc/scripts/version/sync.js.map +1 -0
- package/out-tsc/types.d.ts +68 -0
- package/out-tsc/types.d.ts.map +1 -0
- package/out-tsc/{core/types/value.js → types.js} +4 -0
- package/out-tsc/types.js.map +1 -0
- package/out-tsc/wasm.d.ts +8 -0
- package/out-tsc/wasm.d.ts.map +1 -0
- package/out-tsc/{core/index.js → wasm.js} +9 -6
- package/out-tsc/wasm.js.map +1 -0
- package/package.json +50 -37
- package/.cargo/config.toml +0 -2
- package/.devalang +0 -9
- package/.github/workflows/ci.yml +0 -103
- package/Cargo.toml +0 -81
- package/docs/CHANGELOG.md +0 -581
- package/docs/CONTRIBUTING.md +0 -101
- package/docs/ROADMAP.md +0 -38
- package/docs/TODO.md +0 -71
- package/examples/automation.deva +0 -42
- package/examples/bank.deva +0 -7
- package/examples/bus.deva +0 -10
- package/examples/condition.deva +0 -20
- package/examples/duration.deva +0 -9
- package/examples/effect.deva +0 -2
- package/examples/events.deva +0 -12
- package/examples/filter.deva +0 -11
- package/examples/function.deva +0 -15
- package/examples/group.deva +0 -12
- package/examples/index.deva +0 -63
- package/examples/lfo.deva +0 -9
- package/examples/loop.deva +0 -10
- package/examples/pattern.deva +0 -8
- package/examples/plugin.deva +0 -16
- package/examples/samples/hat-808.wav +0 -0
- package/examples/samples/kick-808.wav +0 -0
- package/examples/synth.deva +0 -24
- package/examples/synth_types.deva +0 -17
- package/examples/variables.deva +0 -9
- package/out-tsc/core/functions/index.d.ts +0 -42
- package/out-tsc/core/functions/index.js +0 -87
- package/out-tsc/core/index.d.ts +0 -6
- package/out-tsc/core/types/index.d.ts +0 -4
- package/out-tsc/core/types/index.js +0 -20
- package/out-tsc/core/types/plugin.d.ts +0 -18
- package/out-tsc/core/types/plugin.js +0 -2
- package/out-tsc/core/types/result.d.ts +0 -27
- package/out-tsc/core/types/result.js +0 -2
- package/out-tsc/core/types/statement.d.ts +0 -106
- package/out-tsc/core/types/statement.js +0 -2
- package/out-tsc/core/types/value.d.ts +0 -43
- package/out-tsc/pkg/devalang_core.d.ts +0 -15
- package/out-tsc/pkg/devalang_core.js +0 -65
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +0 -34
- package/project-version.json +0 -6
- package/rust/cli/bank/api.rs +0 -122
- package/rust/cli/bank/commands.rs +0 -306
- package/rust/cli/bank/mod.rs +0 -29
- package/rust/cli/build/commands.rs +0 -153
- package/rust/cli/build/mod.rs +0 -2
- package/rust/cli/build/process.rs +0 -165
- package/rust/cli/check/mod.rs +0 -208
- package/rust/cli/discover/commands.rs +0 -253
- package/rust/cli/discover/config.rs +0 -111
- package/rust/cli/discover/fs.rs +0 -19
- package/rust/cli/discover/install.rs +0 -103
- package/rust/cli/discover/metadata.rs +0 -48
- package/rust/cli/discover/mod.rs +0 -5
- package/rust/cli/init/commands.rs +0 -88
- package/rust/cli/init/mod.rs +0 -1
- package/rust/cli/install/addon.rs +0 -118
- package/rust/cli/install/bank.rs +0 -72
- package/rust/cli/install/commands.rs +0 -35
- package/rust/cli/install/mod.rs +0 -4
- package/rust/cli/install/plugin.rs +0 -80
- package/rust/cli/login/commands.rs +0 -124
- package/rust/cli/login/mod.rs +0 -1
- package/rust/cli/mod.rs +0 -12
- package/rust/cli/parser.rs +0 -359
- package/rust/cli/play/commands.rs +0 -375
- package/rust/cli/play/io.rs +0 -17
- package/rust/cli/play/mod.rs +0 -5
- package/rust/cli/play/process.rs +0 -159
- package/rust/cli/play/realtime.rs +0 -91
- package/rust/cli/play/utils.rs +0 -23
- package/rust/cli/telemetry/commands.rs +0 -22
- package/rust/cli/telemetry/event_creator.rs +0 -80
- package/rust/cli/telemetry/mod.rs +0 -3
- package/rust/cli/telemetry/send.rs +0 -51
- package/rust/cli/template/commands.rs +0 -69
- package/rust/cli/template/mod.rs +0 -1
- package/rust/cli/update/commands.rs +0 -6
- package/rust/cli/update/mod.rs +0 -1
- package/rust/config/driver.rs +0 -112
- package/rust/config/mod.rs +0 -3
- package/rust/config/ops.rs +0 -26
- package/rust/config/settings.rs +0 -101
- package/rust/core/audio/engine/driver.rs +0 -220
- package/rust/core/audio/engine/export.rs +0 -169
- package/rust/core/audio/engine/helpers.rs +0 -178
- package/rust/core/audio/engine/mod.rs +0 -56
- package/rust/core/audio/engine/notes/dsp.rs +0 -85
- package/rust/core/audio/engine/notes/mod.rs +0 -44
- package/rust/core/audio/engine/notes/params.rs +0 -294
- package/rust/core/audio/engine/sample/insert.rs +0 -199
- package/rust/core/audio/engine/sample/mod.rs +0 -40
- package/rust/core/audio/engine/sample/padding.rs +0 -170
- package/rust/core/audio/evaluator/condition.rs +0 -61
- package/rust/core/audio/evaluator/mod.rs +0 -9
- package/rust/core/audio/evaluator/numeric.rs +0 -152
- package/rust/core/audio/evaluator/rhs.rs +0 -16
- package/rust/core/audio/evaluator/string_expr.rs +0 -94
- package/rust/core/audio/interpreter/driver.rs +0 -574
- package/rust/core/audio/interpreter/mod.rs +0 -2
- package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +0 -175
- package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +0 -384
- package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +0 -2
- package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +0 -316
- package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +0 -3
- package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +0 -192
- package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +0 -24
- package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +0 -116
- package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +0 -97
- package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +0 -100
- package/rust/core/audio/interpreter/statements/automate.rs +0 -16
- package/rust/core/audio/interpreter/statements/call.rs +0 -295
- package/rust/core/audio/interpreter/statements/condition.rs +0 -72
- package/rust/core/audio/interpreter/statements/function.rs +0 -24
- package/rust/core/audio/interpreter/statements/let_.rs +0 -36
- package/rust/core/audio/interpreter/statements/load.rs +0 -17
- package/rust/core/audio/interpreter/statements/loop_.rs +0 -115
- package/rust/core/audio/interpreter/statements/mod.rs +0 -12
- package/rust/core/audio/interpreter/statements/sleep.rs +0 -28
- package/rust/core/audio/interpreter/statements/spawn.rs +0 -253
- package/rust/core/audio/interpreter/statements/tempo.rs +0 -40
- package/rust/core/audio/interpreter/statements/trigger.rs +0 -239
- package/rust/core/audio/loader/mod.rs +0 -1
- package/rust/core/audio/loader/trigger.rs +0 -98
- package/rust/core/audio/mod.rs +0 -6
- package/rust/core/audio/player.rs +0 -70
- package/rust/core/audio/special/easing.rs +0 -189
- package/rust/core/audio/special/env.rs +0 -45
- package/rust/core/audio/special/math.rs +0 -134
- package/rust/core/audio/special/mod.rs +0 -9
- package/rust/core/audio/special/modulator.rs +0 -143
- package/rust/core/builder/mod.rs +0 -129
- package/rust/core/debugger/lexer.rs +0 -27
- package/rust/core/debugger/logs.rs +0 -52
- package/rust/core/debugger/mod.rs +0 -30
- package/rust/core/debugger/preprocessor.rs +0 -27
- package/rust/core/debugger/store.rs +0 -38
- package/rust/core/error/mod.rs +0 -269
- package/rust/core/lexer/driver.rs +0 -59
- package/rust/core/lexer/handler/arrow.rs +0 -82
- package/rust/core/lexer/handler/at.rs +0 -21
- package/rust/core/lexer/handler/brace.rs +0 -41
- package/rust/core/lexer/handler/colon.rs +0 -21
- package/rust/core/lexer/handler/comment.rs +0 -30
- package/rust/core/lexer/handler/dot.rs +0 -21
- package/rust/core/lexer/handler/driver.rs +0 -337
- package/rust/core/lexer/handler/identifier.rs +0 -47
- package/rust/core/lexer/handler/indent.rs +0 -66
- package/rust/core/lexer/handler/mod.rs +0 -15
- package/rust/core/lexer/handler/newline.rs +0 -23
- package/rust/core/lexer/handler/number.rs +0 -31
- package/rust/core/lexer/handler/operator.rs +0 -46
- package/rust/core/lexer/handler/parenthesis.rs +0 -41
- package/rust/core/lexer/handler/slash.rs +0 -21
- package/rust/core/lexer/handler/string.rs +0 -63
- package/rust/core/lexer/mod.rs +0 -3
- package/rust/core/lexer/token.rs +0 -91
- package/rust/core/mod.rs +0 -9
- package/rust/core/parser/driver/block.rs +0 -111
- package/rust/core/parser/driver/cursor.rs +0 -82
- package/rust/core/parser/driver/driver_impl.rs +0 -139
- package/rust/core/parser/driver/mod.rs +0 -6
- package/rust/core/parser/driver/parse_array.rs +0 -120
- package/rust/core/parser/driver/parse_map.rs +0 -223
- package/rust/core/parser/driver/parser.rs +0 -160
- package/rust/core/parser/handler/arrow_call.rs +0 -277
- package/rust/core/parser/handler/at.rs +0 -279
- package/rust/core/parser/handler/bank.rs +0 -104
- package/rust/core/parser/handler/condition.rs +0 -83
- package/rust/core/parser/handler/dot.rs +0 -148
- package/rust/core/parser/handler/identifier/automate.rs +0 -254
- package/rust/core/parser/handler/identifier/call.rs +0 -91
- package/rust/core/parser/handler/identifier/emit.rs +0 -70
- package/rust/core/parser/handler/identifier/function.rs +0 -113
- package/rust/core/parser/handler/identifier/group.rs +0 -89
- package/rust/core/parser/handler/identifier/let_.rs +0 -173
- package/rust/core/parser/handler/identifier/mod.rs +0 -55
- package/rust/core/parser/handler/identifier/on.rs +0 -107
- package/rust/core/parser/handler/identifier/print.rs +0 -49
- package/rust/core/parser/handler/identifier/sleep.rs +0 -96
- package/rust/core/parser/handler/identifier/spawn.rs +0 -91
- package/rust/core/parser/handler/identifier/synth.rs +0 -135
- package/rust/core/parser/handler/loop_.rs +0 -194
- package/rust/core/parser/handler/mod.rs +0 -9
- package/rust/core/parser/handler/pattern.rs +0 -74
- package/rust/core/parser/handler/tempo.rs +0 -105
- package/rust/core/parser/mod.rs +0 -3
- package/rust/core/parser/statement.rs +0 -10
- package/rust/core/plugin/loader.rs +0 -137
- package/rust/core/plugin/mod.rs +0 -2
- package/rust/core/plugin/runner/mod.rs +0 -11
- package/rust/core/plugin/runner/non_wasm.rs +0 -297
- package/rust/core/plugin/runner/wasm32.rs +0 -43
- package/rust/core/preprocessor/loader/inject.rs +0 -278
- package/rust/core/preprocessor/loader/loader_helpers.rs +0 -110
- package/rust/core/preprocessor/loader/mod.rs +0 -235
- package/rust/core/preprocessor/mod.rs +0 -4
- package/rust/core/preprocessor/module.rs +0 -55
- package/rust/core/preprocessor/processor/handlers.rs +0 -107
- package/rust/core/preprocessor/processor/mod.rs +0 -1
- package/rust/core/preprocessor/resolver/bank.rs +0 -49
- package/rust/core/preprocessor/resolver/call.rs +0 -124
- package/rust/core/preprocessor/resolver/condition.rs +0 -95
- package/rust/core/preprocessor/resolver/driver.rs +0 -324
- package/rust/core/preprocessor/resolver/function.rs +0 -69
- package/rust/core/preprocessor/resolver/group.rs +0 -122
- package/rust/core/preprocessor/resolver/let_.rs +0 -32
- package/rust/core/preprocessor/resolver/loop_.rs +0 -318
- package/rust/core/preprocessor/resolver/mod.rs +0 -16
- package/rust/core/preprocessor/resolver/pattern.rs +0 -83
- package/rust/core/preprocessor/resolver/spawn.rs +0 -99
- package/rust/core/preprocessor/resolver/synth.rs +0 -54
- package/rust/core/preprocessor/resolver/tempo.rs +0 -48
- package/rust/core/preprocessor/resolver/trigger.rs +0 -116
- package/rust/core/preprocessor/resolver/value.rs +0 -176
- package/rust/core/store/global.rs +0 -57
- package/rust/core/store/mod.rs +0 -1
- package/rust/lib.rs +0 -323
- package/rust/main.rs +0 -388
- package/rust/types/Cargo.toml +0 -11
- package/rust/types/src/addons.rs +0 -55
- package/rust/types/src/ast.rs +0 -202
- package/rust/types/src/config.rs +0 -84
- package/rust/types/src/lib.rs +0 -15
- package/rust/types/src/plugin.rs +0 -20
- package/rust/types/src/store.rs +0 -139
- package/rust/types/src/telemetry.rs +0 -85
- package/rust/utils/Cargo.toml +0 -26
- package/rust/utils/src/error.rs +0 -186
- package/rust/utils/src/file.rs +0 -94
- package/rust/utils/src/first_usage.rs +0 -97
- package/rust/utils/src/lib.rs +0 -9
- package/rust/utils/src/logger.rs +0 -200
- package/rust/utils/src/path.rs +0 -129
- package/rust/utils/src/signature.rs +0 -41
- package/rust/utils/src/spinner.rs +0 -20
- package/rust/utils/src/version.rs +0 -27
- package/rust/utils/src/watcher.rs +0 -46
- package/rust/web/api.rs +0 -5
- package/rust/web/cdn.rs +0 -34
- package/rust/web/mod.rs +0 -3
- package/rust/web/sso.rs +0 -5
- package/templates/minimal/.devalang +0 -5
- package/templates/minimal/README.md +0 -218
- package/templates/minimal/src/index.deva +0 -2
- package/templates/welcome/.devalang +0 -5
- package/templates/welcome/README.md +0 -218
- package/templates/welcome/samples/kick-808.wav +0 -0
- package/templates/welcome/src/index.deva +0 -61
- package/templates/welcome/src/variables.deva +0 -3
- package/tests/integration.rs +0 -21
- package/tests/rust/cli_check_build.rs +0 -21
- package/tests/rust/cli_help.rs +0 -12
- package/tests/rust/cli_template_list.rs +0 -10
- package/tests/rust/cli_version.rs +0 -11
- package/tests/typescript/index.spec.ts +0 -136
- package/tests/typescript/playhead.spec.ts +0 -36
- package/tests/typescript/render_e2e.spec.ts +0 -77
- package/tsconfig.json +0 -115
- package/typescript/bin/index.ts +0 -28
- package/typescript/core/functions/index.ts +0 -94
- package/typescript/core/index.ts +0 -6
- package/typescript/core/types/index.ts +0 -4
- package/typescript/core/types/plugin.ts +0 -19
- package/typescript/core/types/result.ts +0 -29
- package/typescript/core/types/statement.ts +0 -47
- package/typescript/core/types/value.ts +0 -29
- package/typescript/index.ts +0 -8
- package/typescript/pkg/devalang_core.d.ts +0 -4
- package/typescript/pkg/devalang_core.ts +0 -65
- package/typescript/scripts/copy-wasm-dts.ts +0 -41
- package/typescript/scripts/postinstall.ts +0 -85
- package/typescript/scripts/version/bump.ts +0 -44
- package/typescript/scripts/version/fetch.ts +0 -18
- package/typescript/scripts/version/index.ts +0 -25
- package/typescript/scripts/version/sync.ts +0 -24
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
use devalang_types::Value;
|
|
2
|
-
use std::collections::HashMap;
|
|
3
|
-
|
|
4
|
-
pub fn apply_defaults(synth_params: &mut HashMap<String, Value>) {
|
|
5
|
-
use devalang_types::Value as DV;
|
|
6
|
-
// pluck: very short attack, short decay, very low sustain, short release
|
|
7
|
-
synth_params
|
|
8
|
-
.entry("attack".to_string())
|
|
9
|
-
.or_insert(DV::Number(2.0));
|
|
10
|
-
synth_params
|
|
11
|
-
.entry("decay".to_string())
|
|
12
|
-
.or_insert(DV::Number(80.0));
|
|
13
|
-
synth_params
|
|
14
|
-
.entry("sustain".to_string())
|
|
15
|
-
.or_insert(DV::Number(0.0));
|
|
16
|
-
synth_params
|
|
17
|
-
.entry("release".to_string())
|
|
18
|
-
.or_insert(DV::Number(120.0));
|
|
19
|
-
synth_params
|
|
20
|
-
.entry("glide".to_string())
|
|
21
|
-
.or_insert(DV::Boolean(false));
|
|
22
|
-
synth_params
|
|
23
|
-
.entry("slide".to_string())
|
|
24
|
-
.or_insert(DV::Boolean(false));
|
|
25
|
-
// small transient helper for plucks
|
|
26
|
-
synth_params
|
|
27
|
-
.entry("pluck_click".to_string())
|
|
28
|
-
.or_insert(DV::Number(0.08));
|
|
29
|
-
synth_params
|
|
30
|
-
.entry("pluck_click_ms".to_string())
|
|
31
|
-
.or_insert(DV::Number(8.0));
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Prepare per-note modifications for pluck: short attack/release, optional amp curve per-index
|
|
35
|
-
pub fn prepare_note(
|
|
36
|
-
_note_name: &str,
|
|
37
|
-
index: usize,
|
|
38
|
-
_total: usize,
|
|
39
|
-
_start_time_ms: f32,
|
|
40
|
-
_duration_ms: f32,
|
|
41
|
-
amp: f32,
|
|
42
|
-
_synth_params: &HashMap<String, Value>,
|
|
43
|
-
note_params: &HashMap<String, Value>,
|
|
44
|
-
_automation: &Option<HashMap<String, Value>>,
|
|
45
|
-
) -> (f32, f32, f32, HashMap<String, Value>) {
|
|
46
|
-
// pluck slightly reduces amp for later notes by a tiny fraction
|
|
47
|
-
let decay = 0.02 * (index as f32);
|
|
48
|
-
let amp_out = (amp * (1.0 - decay)).max(0.0);
|
|
49
|
-
let mut params_out = note_params.clone();
|
|
50
|
-
// ensure short attack & short release to sound plucky
|
|
51
|
-
params_out
|
|
52
|
-
.entry("attack".to_string())
|
|
53
|
-
.or_insert(Value::Number(1.0));
|
|
54
|
-
params_out
|
|
55
|
-
.entry("release".to_string())
|
|
56
|
-
.or_insert(Value::Number(100.0));
|
|
57
|
-
params_out
|
|
58
|
-
.entry("sustain".to_string())
|
|
59
|
-
.or_insert(Value::Number(0.0));
|
|
60
|
-
// add a small "click" transient and a light resonant filter to emphasize the pluck
|
|
61
|
-
use devalang_types::Value as DV;
|
|
62
|
-
let freq = note_to_freq(_note_name);
|
|
63
|
-
let mut filt: std::collections::HashMap<String, Value> = std::collections::HashMap::new();
|
|
64
|
-
filt.insert("type".to_string(), Value::String("bandpass".to_string()));
|
|
65
|
-
// center filter a bit above the note to give a bright pluck transient
|
|
66
|
-
// use more explicit filter parameter names requested by user
|
|
67
|
-
filt.insert(
|
|
68
|
-
"cutoff".to_string(),
|
|
69
|
-
Value::Number((freq * 2.0).min(10000.0)),
|
|
70
|
-
);
|
|
71
|
-
filt.insert("resonance".to_string(), Value::Number(6.0));
|
|
72
|
-
// only insert filters if not already present
|
|
73
|
-
if !params_out.contains_key("filters") {
|
|
74
|
-
params_out.insert("filters".to_string(), DV::Array(vec![DV::Map(filt)]));
|
|
75
|
-
}
|
|
76
|
-
// frequency unchanged here; caller computes freq
|
|
77
|
-
// stronger pitch drop for a plucky character
|
|
78
|
-
let freq_end = freq * 0.98;
|
|
79
|
-
(0.0, freq_end, amp_out, params_out)
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
fn note_to_freq(note: &str) -> f32 {
|
|
83
|
-
let notes = [
|
|
84
|
-
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
|
|
85
|
-
];
|
|
86
|
-
|
|
87
|
-
if note.len() < 2 || note.len() > 3 {
|
|
88
|
-
return 440.0;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
let (name, octave_str) = note.split_at(note.len() - 1);
|
|
92
|
-
let semitone = notes.iter().position(|&n| n == name).unwrap_or(9) as i32;
|
|
93
|
-
let octave = octave_str.parse::<i32>().unwrap_or(4);
|
|
94
|
-
let midi_note = (octave + 1) * 12 + semitone;
|
|
95
|
-
|
|
96
|
-
440.0 * (2.0_f32).powf(((midi_note as f32) - 69.0) / 12.0)
|
|
97
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
use devalang_types::Value;
|
|
2
|
-
use std::collections::HashMap;
|
|
3
|
-
|
|
4
|
-
pub fn apply_defaults(synth_params: &mut HashMap<String, Value>) {
|
|
5
|
-
use devalang_types::Value as DV;
|
|
6
|
-
// sub bass: strong sustain, lowpass emphasis
|
|
7
|
-
synth_params
|
|
8
|
-
.entry("attack".to_string())
|
|
9
|
-
.or_insert(DV::Number(10.0));
|
|
10
|
-
synth_params
|
|
11
|
-
.entry("decay".to_string())
|
|
12
|
-
.or_insert(DV::Number(80.0));
|
|
13
|
-
// sustain stored as 0.0-1.0 for consistency
|
|
14
|
-
synth_params
|
|
15
|
-
.entry("sustain".to_string())
|
|
16
|
-
.or_insert(DV::Number(1.0));
|
|
17
|
-
synth_params
|
|
18
|
-
.entry("release".to_string())
|
|
19
|
-
.or_insert(DV::Number(300.0));
|
|
20
|
-
synth_params
|
|
21
|
-
.entry("detune".to_string())
|
|
22
|
-
.or_insert(DV::Number(0.0));
|
|
23
|
-
synth_params
|
|
24
|
-
.entry("lowpass".to_string())
|
|
25
|
-
.or_insert(DV::Number(150.0));
|
|
26
|
-
// octave stacking and drive for extra body
|
|
27
|
-
synth_params
|
|
28
|
-
.entry("octaves".to_string())
|
|
29
|
-
.or_insert(DV::Number(1.0));
|
|
30
|
-
synth_params
|
|
31
|
-
.entry("drive".to_string())
|
|
32
|
-
.or_insert(DV::Number(0.0));
|
|
33
|
-
// encourage a lowpass default if none provided
|
|
34
|
-
synth_params
|
|
35
|
-
.entry("lowpass".to_string())
|
|
36
|
-
.or_insert(DV::Number(120.0));
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// prepare_note for sub: shift note one or two octaves down and set stronger amp
|
|
40
|
-
pub fn prepare_note(
|
|
41
|
-
note_name: &str,
|
|
42
|
-
_index: usize,
|
|
43
|
-
_total: usize,
|
|
44
|
-
_start_time_ms: f32,
|
|
45
|
-
_duration_ms: f32,
|
|
46
|
-
amp: f32,
|
|
47
|
-
_synth_params: &HashMap<String, Value>,
|
|
48
|
-
note_params: &HashMap<String, Value>,
|
|
49
|
-
_automation: &Option<HashMap<String, Value>>,
|
|
50
|
-
) -> (f32, f32, f32, HashMap<String, Value>) {
|
|
51
|
-
let mut params_out = note_params.clone();
|
|
52
|
-
params_out
|
|
53
|
-
.entry("attack".to_string())
|
|
54
|
-
.or_insert(Value::Number(5.0));
|
|
55
|
-
params_out
|
|
56
|
-
.entry("release".to_string())
|
|
57
|
-
.or_insert(Value::Number(200.0));
|
|
58
|
-
params_out
|
|
59
|
-
.entry("sustain".to_string())
|
|
60
|
-
.or_insert(Value::Number(1.0));
|
|
61
|
-
|
|
62
|
-
// compute deep-frequency one octave down by default
|
|
63
|
-
let freq = note_to_freq(note_name) * 0.5;
|
|
64
|
-
// allow stacking additional octaves for extra body
|
|
65
|
-
if let Some(Value::Number(o)) = _synth_params.get("octaves") {
|
|
66
|
-
let oct = (*o as i32).max(1);
|
|
67
|
-
if oct >= 2 {
|
|
68
|
-
// add lower harmonic by halving frequency again (engine may layer if octaves param is observed)
|
|
69
|
-
// we still return the primary frequency but advertise octaves in params
|
|
70
|
-
params_out.insert("octaves".to_string(), Value::Number(*o));
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// boost amplitude a little for sub
|
|
75
|
-
let amp_out = (amp * 1.5).min(1.0);
|
|
76
|
-
|
|
77
|
-
// advertise drive if present so engine/effects can apply soft clipping
|
|
78
|
-
if let Some(Value::Number(d)) = _synth_params.get("drive") {
|
|
79
|
-
params_out.insert("drive".to_string(), Value::Number(*d));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
(0.0, freq, amp_out, params_out)
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
fn note_to_freq(note: &str) -> f32 {
|
|
86
|
-
let notes = [
|
|
87
|
-
"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B",
|
|
88
|
-
];
|
|
89
|
-
|
|
90
|
-
if note.len() < 2 || note.len() > 3 {
|
|
91
|
-
return 440.0;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
let (name, octave_str) = note.split_at(note.len() - 1);
|
|
95
|
-
let semitone = notes.iter().position(|&n| n == name).unwrap_or(9) as i32;
|
|
96
|
-
let octave = octave_str.parse::<i32>().unwrap_or(4);
|
|
97
|
-
let midi_note = (octave + 1) * 12 + semitone;
|
|
98
|
-
|
|
99
|
-
440.0 * (2.0_f32).powf(((midi_note as f32) - 69.0) / 12.0)
|
|
100
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
use crate::core::parser::statement::{Statement, StatementKind};
|
|
2
|
-
use devalang_types::VariableTable;
|
|
3
|
-
|
|
4
|
-
// Store automation configuration into the variable table under a namespaced key
|
|
5
|
-
// Key: "<target>__automation" => Value::Map({ target, params })
|
|
6
|
-
pub fn interprete_automate_statement(
|
|
7
|
-
stmt: &Statement,
|
|
8
|
-
variable_table: &mut VariableTable,
|
|
9
|
-
) -> Option<VariableTable> {
|
|
10
|
-
if let StatementKind::Automate { target } = &stmt.kind {
|
|
11
|
-
let key = format!("{}__automation", target);
|
|
12
|
-
variable_table.set(key, stmt.value.clone());
|
|
13
|
-
return Some(variable_table.clone());
|
|
14
|
-
}
|
|
15
|
-
None
|
|
16
|
-
}
|
|
@@ -1,295 +0,0 @@
|
|
|
1
|
-
use devalang_types::{Duration, Value};
|
|
2
|
-
|
|
3
|
-
use crate::core::{
|
|
4
|
-
audio::{engine::AudioEngine, interpreter::driver::execute_audio_block},
|
|
5
|
-
parser::statement::{Statement, StatementKind},
|
|
6
|
-
store::global::GlobalStore,
|
|
7
|
-
};
|
|
8
|
-
use devalang_types::store::{FunctionTable, VariableTable};
|
|
9
|
-
|
|
10
|
-
pub fn interprete_call_statement(
|
|
11
|
-
stmt: &Statement,
|
|
12
|
-
audio_engine: &mut AudioEngine,
|
|
13
|
-
variable_table: &VariableTable,
|
|
14
|
-
functions: &FunctionTable,
|
|
15
|
-
global_store: &GlobalStore,
|
|
16
|
-
base_bpm: f32,
|
|
17
|
-
base_duration: f32,
|
|
18
|
-
max_end_time: f32,
|
|
19
|
-
cursor_time: f32,
|
|
20
|
-
) -> (f32, f32) {
|
|
21
|
-
if let StatementKind::Call { name, args } = &stmt.kind {
|
|
22
|
-
// Classic function call case
|
|
23
|
-
if let Some(func) = functions.functions.get(name) {
|
|
24
|
-
// function found
|
|
25
|
-
if func.parameters.len() != args.len() {
|
|
26
|
-
eprintln!(
|
|
27
|
-
"❌ Function '{}' expects {} args, got {}",
|
|
28
|
-
name,
|
|
29
|
-
func.parameters.len(),
|
|
30
|
-
args.len()
|
|
31
|
-
);
|
|
32
|
-
return (max_end_time, cursor_time);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
let mut local_vars = VariableTable::with_parent(variable_table.clone());
|
|
36
|
-
for (param, arg) in func.parameters.iter().zip(args) {
|
|
37
|
-
local_vars.set(param.clone(), arg.clone());
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return execute_audio_block(
|
|
41
|
-
audio_engine,
|
|
42
|
-
global_store,
|
|
43
|
-
local_vars,
|
|
44
|
-
functions.clone(),
|
|
45
|
-
&func.body,
|
|
46
|
-
base_bpm,
|
|
47
|
-
base_duration,
|
|
48
|
-
max_end_time,
|
|
49
|
-
cursor_time,
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// Group case
|
|
54
|
-
if let Some(group_stmt) = find_group(name, variable_table, global_store) {
|
|
55
|
-
// group found
|
|
56
|
-
if let Value::Map(map) = &group_stmt.value {
|
|
57
|
-
if let Some(Value::Block(body)) = map.get("body") {
|
|
58
|
-
return execute_audio_block(
|
|
59
|
-
audio_engine,
|
|
60
|
-
global_store,
|
|
61
|
-
variable_table.clone(),
|
|
62
|
-
functions.clone(),
|
|
63
|
-
body,
|
|
64
|
-
base_bpm,
|
|
65
|
-
base_duration,
|
|
66
|
-
max_end_time,
|
|
67
|
-
cursor_time,
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Pattern case
|
|
74
|
-
if let Some(pattern_stmt) = find_pattern(name, variable_table, global_store) {
|
|
75
|
-
// Extract pattern string from statement value
|
|
76
|
-
if let Value::String(pat) = &pattern_stmt.value {
|
|
77
|
-
// Determine target entity (explicit or inferred)
|
|
78
|
-
let mut target_entity = name.clone();
|
|
79
|
-
if let StatementKind::Pattern { name: _n, target } = &pattern_stmt.kind {
|
|
80
|
-
if let Some(t) = target {
|
|
81
|
-
target_entity = t.clone();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Build a variable table snapshot for resolution like triggers do
|
|
86
|
-
// Preserve the full parent chain so lookups behave the same as runtime
|
|
87
|
-
fn clone_with_parents(
|
|
88
|
-
orig: &devalang_types::VariableTable,
|
|
89
|
-
) -> devalang_types::VariableTable {
|
|
90
|
-
devalang_types::VariableTable {
|
|
91
|
-
variables: orig.variables.clone(),
|
|
92
|
-
parent: orig
|
|
93
|
-
.parent
|
|
94
|
-
.as_ref()
|
|
95
|
-
.map(|p| Box::new(clone_with_parents(p))),
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
let final_variable_table = clone_with_parents(variable_table);
|
|
100
|
-
|
|
101
|
-
// Normalize pattern: remove spaces and line breaks
|
|
102
|
-
let pattern_str: String = pat.chars().filter(|c| !c.is_whitespace()).collect();
|
|
103
|
-
if pattern_str.is_empty() {
|
|
104
|
-
return (max_end_time, cursor_time);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
let step_count = pattern_str.len() as f32;
|
|
108
|
-
// Assume pattern spans one bar (4 beats)
|
|
109
|
-
let total_bar = 4.0 * base_duration;
|
|
110
|
-
let step_duration = total_bar / step_count; // seconds per step
|
|
111
|
-
|
|
112
|
-
let mut updated_max = max_end_time;
|
|
113
|
-
|
|
114
|
-
for (i, ch) in pattern_str.chars().enumerate() {
|
|
115
|
-
if ch == '-' {
|
|
116
|
-
continue; // rest
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Schedule a trigger at cursor_time + offset
|
|
120
|
-
let event_time = cursor_time + (i as f32) * step_duration;
|
|
121
|
-
|
|
122
|
-
// Resolve trigger value similarly to interprete_trigger_statement
|
|
123
|
-
let mut trigger_val = Value::String(target_entity.clone());
|
|
124
|
-
if let Some(val) = variable_table.variables.get(&target_entity) {
|
|
125
|
-
match val {
|
|
126
|
-
Value::Identifier(id) => {
|
|
127
|
-
// resolve from parent if available
|
|
128
|
-
if let Some(parent) = &variable_table.parent {
|
|
129
|
-
if let Some(v) = parent.get(id) {
|
|
130
|
-
trigger_val = v.clone();
|
|
131
|
-
}
|
|
132
|
-
} else if let Some(v) = variable_table.get(id) {
|
|
133
|
-
trigger_val = v.clone();
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
Value::Map(map) => {
|
|
137
|
-
if let Some(Value::String(src)) = map.get("entity") {
|
|
138
|
-
trigger_val = Value::String(src.clone());
|
|
139
|
-
} else if let Some(Value::Identifier(src)) = map.get("entity") {
|
|
140
|
-
trigger_val = Value::Identifier(src.clone());
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
Value::Sample(sample_src) => {
|
|
144
|
-
trigger_val = Value::Sample(sample_src.clone());
|
|
145
|
-
}
|
|
146
|
-
_ => {
|
|
147
|
-
// leave as string
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Use loader to get sample path and sample length
|
|
153
|
-
let (src, sample_length) = crate::core::audio::loader::trigger::load_trigger(
|
|
154
|
-
&trigger_val,
|
|
155
|
-
&Duration::Number(step_duration),
|
|
156
|
-
&None,
|
|
157
|
-
base_duration,
|
|
158
|
-
final_variable_table.clone(),
|
|
159
|
-
);
|
|
160
|
-
|
|
161
|
-
let play_length = step_duration.min(sample_length);
|
|
162
|
-
|
|
163
|
-
let trigger_src = match trigger_val.get("entity") {
|
|
164
|
-
Some(Value::String(s)) => s.clone(),
|
|
165
|
-
Some(Value::Identifier(id)) => id.clone(),
|
|
166
|
-
Some(Value::Statement(stmt)) => {
|
|
167
|
-
if let StatementKind::Trigger { entity, .. } = &stmt.kind {
|
|
168
|
-
entity.clone()
|
|
169
|
-
} else {
|
|
170
|
-
src.clone()
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
_ => src.clone(),
|
|
174
|
-
};
|
|
175
|
-
|
|
176
|
-
audio_engine.insert_sample(
|
|
177
|
-
&trigger_src,
|
|
178
|
-
event_time,
|
|
179
|
-
play_length,
|
|
180
|
-
None,
|
|
181
|
-
&final_variable_table,
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
let end_time = event_time + play_length;
|
|
185
|
-
if end_time > updated_max {
|
|
186
|
-
updated_max = end_time;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return (updated_max, cursor_time);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
// Function or group not found; keep as debug-free fail path
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
(max_end_time, cursor_time)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
fn find_group(
|
|
201
|
-
name: &str,
|
|
202
|
-
variable_table: &VariableTable,
|
|
203
|
-
global_store: &GlobalStore,
|
|
204
|
-
) -> Option<Statement> {
|
|
205
|
-
use crate::core::parser::statement::Statement;
|
|
206
|
-
use crate::core::parser::statement::StatementKind;
|
|
207
|
-
|
|
208
|
-
if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
|
|
209
|
-
if let StatementKind::Group = stmt_box.kind {
|
|
210
|
-
return Some(*stmt_box.clone());
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
if let Some(val) = global_store.variables.variables.get(name) {
|
|
215
|
-
match val {
|
|
216
|
-
Value::Statement(stmt_box) => {
|
|
217
|
-
if let StatementKind::Group = stmt_box.kind {
|
|
218
|
-
return Some(*stmt_box.clone());
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
Value::Map(map) => {
|
|
222
|
-
// Try to rebuild a Group statement from the stored map
|
|
223
|
-
if let (Some(Value::String(_id)), Some(Value::Block(_body))) =
|
|
224
|
-
(map.get("identifier"), map.get("body"))
|
|
225
|
-
{
|
|
226
|
-
let stmt = Statement {
|
|
227
|
-
kind: StatementKind::Group,
|
|
228
|
-
value: Value::Map(map.clone()),
|
|
229
|
-
indent: 0,
|
|
230
|
-
line: 0,
|
|
231
|
-
column: 0,
|
|
232
|
-
};
|
|
233
|
-
return Some(stmt);
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
_ => {}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
None
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
fn find_pattern(
|
|
244
|
-
name: &str,
|
|
245
|
-
variable_table: &VariableTable,
|
|
246
|
-
global_store: &GlobalStore,
|
|
247
|
-
) -> Option<Statement> {
|
|
248
|
-
use crate::core::parser::statement::Statement;
|
|
249
|
-
use crate::core::parser::statement::StatementKind;
|
|
250
|
-
|
|
251
|
-
if let Some(Value::Statement(stmt_box)) = variable_table.get(name) {
|
|
252
|
-
if let StatementKind::Pattern { .. } = stmt_box.kind {
|
|
253
|
-
return Some(*stmt_box.clone());
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
if let Some(val) = global_store.variables.variables.get(name) {
|
|
258
|
-
match val {
|
|
259
|
-
Value::Statement(stmt_box) => {
|
|
260
|
-
if let StatementKind::Pattern { .. } = stmt_box.kind {
|
|
261
|
-
return Some(*stmt_box.clone());
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
Value::Map(map) => {
|
|
265
|
-
if let Some(Value::String(_pat)) = map.get("pattern") {
|
|
266
|
-
// Rebuild a Pattern statement from stored map if possible
|
|
267
|
-
let stmt = Statement {
|
|
268
|
-
kind: StatementKind::Pattern {
|
|
269
|
-
name: name.to_string(),
|
|
270
|
-
target: map.get("target").and_then(|v| match v {
|
|
271
|
-
Value::String(s) => Some(s.clone()),
|
|
272
|
-
_ => None,
|
|
273
|
-
}),
|
|
274
|
-
},
|
|
275
|
-
value: Value::String(
|
|
276
|
-
map.get("pattern")
|
|
277
|
-
.and_then(|v| match v {
|
|
278
|
-
Value::String(s) => Some(s.clone()),
|
|
279
|
-
_ => None,
|
|
280
|
-
})
|
|
281
|
-
.unwrap_or_default(),
|
|
282
|
-
),
|
|
283
|
-
indent: 0,
|
|
284
|
-
line: 0,
|
|
285
|
-
column: 0,
|
|
286
|
-
};
|
|
287
|
-
return Some(stmt);
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
_ => {}
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
None
|
|
295
|
-
}
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
use devalang_types::Value;
|
|
2
|
-
|
|
3
|
-
use crate::core::{
|
|
4
|
-
audio::{
|
|
5
|
-
engine::AudioEngine, evaluator::evaluate_condition_string,
|
|
6
|
-
interpreter::driver::execute_audio_block,
|
|
7
|
-
},
|
|
8
|
-
parser::statement::Statement,
|
|
9
|
-
store::global::GlobalStore,
|
|
10
|
-
};
|
|
11
|
-
use devalang_types::store::{FunctionTable, VariableTable};
|
|
12
|
-
|
|
13
|
-
pub fn interprete_condition_statement(
|
|
14
|
-
stmt: &Statement,
|
|
15
|
-
audio_engine: &mut AudioEngine,
|
|
16
|
-
global_store: &GlobalStore,
|
|
17
|
-
variable_table: &VariableTable,
|
|
18
|
-
functions_table: &FunctionTable,
|
|
19
|
-
base_bpm: f32,
|
|
20
|
-
base_duration: f32,
|
|
21
|
-
max_end_time: f32,
|
|
22
|
-
cursor_time: f32,
|
|
23
|
-
) -> (f32, f32) {
|
|
24
|
-
let cur_time = cursor_time;
|
|
25
|
-
let max_time = max_end_time;
|
|
26
|
-
|
|
27
|
-
let mut current = stmt.value.clone();
|
|
28
|
-
|
|
29
|
-
loop {
|
|
30
|
-
let Value::Map(map) = current else {
|
|
31
|
-
break;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
let should_execute = match map.get("condition") {
|
|
35
|
-
Some(Value::Boolean(b)) => *b,
|
|
36
|
-
Some(Value::String(expr)) => evaluate_condition_string(expr, &variable_table.clone()),
|
|
37
|
-
Some(_) => false,
|
|
38
|
-
None => true,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
if should_execute {
|
|
42
|
-
if let Some(Value::Block(block)) = map.get("body") {
|
|
43
|
-
let (new_max, cursor_time) = execute_audio_block(
|
|
44
|
-
audio_engine,
|
|
45
|
-
global_store,
|
|
46
|
-
variable_table.clone(),
|
|
47
|
-
functions_table.clone(),
|
|
48
|
-
block,
|
|
49
|
-
base_bpm,
|
|
50
|
-
base_duration,
|
|
51
|
-
max_time,
|
|
52
|
-
cur_time,
|
|
53
|
-
);
|
|
54
|
-
return (new_max, cursor_time);
|
|
55
|
-
} else {
|
|
56
|
-
break;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Advance to the next condition
|
|
61
|
-
match map.get("next") {
|
|
62
|
-
Some(Value::Map(next_map)) => {
|
|
63
|
-
current = Value::Map(next_map.clone());
|
|
64
|
-
}
|
|
65
|
-
_ => {
|
|
66
|
-
break;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
(max_end_time, cursor_time)
|
|
72
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
use crate::core::parser::statement::{Statement, StatementKind};
|
|
2
|
-
use devalang_types::store::{FunctionDef, FunctionTable};
|
|
3
|
-
|
|
4
|
-
pub fn interprete_function_statement(
|
|
5
|
-
stmt: &Statement,
|
|
6
|
-
functions_table: &mut FunctionTable,
|
|
7
|
-
) -> Option<FunctionTable> {
|
|
8
|
-
if let StatementKind::Function {
|
|
9
|
-
name,
|
|
10
|
-
parameters,
|
|
11
|
-
body,
|
|
12
|
-
} = &stmt.kind
|
|
13
|
-
{
|
|
14
|
-
functions_table.add_function(FunctionDef {
|
|
15
|
-
name: name.clone(),
|
|
16
|
-
parameters: parameters.clone(),
|
|
17
|
-
body: body.clone(),
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
return Some(functions_table.clone());
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
None
|
|
24
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
use crate::core::parser::statement::{Statement, StatementKind};
|
|
2
|
-
use devalang_types::Value;
|
|
3
|
-
use devalang_types::store::VariableTable;
|
|
4
|
-
|
|
5
|
-
pub fn interprete_let_statement(
|
|
6
|
-
stmt: &Statement,
|
|
7
|
-
variable_table: &mut VariableTable,
|
|
8
|
-
) -> Option<VariableTable> {
|
|
9
|
-
if let StatementKind::Let { name } = &stmt.kind {
|
|
10
|
-
// If RHS is a string and looks like an expression, evaluate it
|
|
11
|
-
let evaluated = match &stmt.value {
|
|
12
|
-
Value::String(s) if s.contains("$env") || s.contains("$math") => {
|
|
13
|
-
// We don't have direct env here; use defaults or infer from table
|
|
14
|
-
let bpm = if let Some(Value::Number(n)) = variable_table.get("bpm") {
|
|
15
|
-
*n
|
|
16
|
-
} else {
|
|
17
|
-
120.0
|
|
18
|
-
};
|
|
19
|
-
// Try to infer beat from time-based variables if any, else 0.0
|
|
20
|
-
let beat = if let Some(Value::Number(n)) = variable_table.get("beat") {
|
|
21
|
-
*n
|
|
22
|
-
} else {
|
|
23
|
-
0.0
|
|
24
|
-
};
|
|
25
|
-
crate::core::audio::evaluator::evaluate_rhs_into_value(s, variable_table, bpm, beat)
|
|
26
|
-
}
|
|
27
|
-
other => other.clone(),
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
variable_table.set(name.to_string(), evaluated);
|
|
31
|
-
|
|
32
|
-
return Some(variable_table.clone());
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
None
|
|
36
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
use devalang_types::Value;
|
|
2
|
-
|
|
3
|
-
use crate::core::parser::statement::{Statement, StatementKind};
|
|
4
|
-
use devalang_types::store::VariableTable;
|
|
5
|
-
|
|
6
|
-
pub fn interprete_load_statement(
|
|
7
|
-
stmt: &Statement,
|
|
8
|
-
variable_table: &mut VariableTable,
|
|
9
|
-
) -> Option<VariableTable> {
|
|
10
|
-
if let StatementKind::Load { source, alias } = &stmt.kind {
|
|
11
|
-
variable_table.set(alias.to_string(), Value::Sample(source.clone()));
|
|
12
|
-
|
|
13
|
-
return Some(variable_table.clone());
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
None
|
|
17
|
-
}
|