@devaloop/devalang 0.0.1-alpha.16-hotfix.3 → 0.0.1-alpha.18
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/.cargo/config.toml +2 -0
- package/.devalang +10 -10
- package/.github/workflows/ci.yml +0 -1
- package/Cargo.toml +18 -2
- package/README.md +82 -34
- package/docs/CHANGELOG.md +91 -0
- package/docs/ROADMAP.md +7 -4
- package/docs/TODO.md +1 -1
- package/examples/index.deva +55 -35
- package/examples/pattern.deva +5 -5
- package/out-tsc/bin/index.d.ts +2 -0
- package/out-tsc/core/functions/index.d.ts +37 -0
- package/out-tsc/core/functions/index.js +76 -0
- package/out-tsc/core/index.d.ts +6 -0
- package/out-tsc/core/index.js +22 -0
- package/out-tsc/core/types/index.d.ts +4 -0
- package/out-tsc/core/types/index.js +20 -0
- package/out-tsc/core/types/plugin.d.ts +18 -0
- package/out-tsc/core/types/plugin.js +2 -0
- package/out-tsc/core/types/result.d.ts +27 -0
- package/out-tsc/core/types/result.js +2 -0
- package/out-tsc/core/types/statement.d.ts +106 -0
- package/out-tsc/core/types/statement.js +2 -0
- package/out-tsc/core/types/value.d.ts +43 -0
- package/out-tsc/core/types/value.js +2 -0
- package/out-tsc/index.d.ts +7 -0
- package/out-tsc/index.js +41 -2
- package/out-tsc/pkg/devalang_core.d.ts +7 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +33 -0
- package/out-tsc/scripts/copy-wasm-dts.d.ts +1 -0
- package/out-tsc/scripts/copy-wasm-dts.js +73 -0
- package/out-tsc/scripts/postinstall.d.ts +1 -0
- package/out-tsc/scripts/postinstall.js +33 -23
- package/out-tsc/scripts/version/bump.d.ts +1 -0
- package/out-tsc/scripts/version/fetch.d.ts +1 -0
- package/out-tsc/scripts/version/index.d.ts +1 -0
- package/out-tsc/scripts/version/sync.d.ts +1 -0
- package/package.json +16 -4
- package/project-version.json +3 -3
- package/rust/cli/bank/api.rs +122 -0
- package/rust/cli/bank/commands.rs +275 -0
- package/rust/cli/bank/mod.rs +29 -0
- package/rust/cli/build/commands.rs +107 -0
- package/rust/cli/build/mod.rs +2 -0
- package/rust/cli/build/process.rs +146 -0
- package/rust/cli/{check.rs → check/mod.rs} +18 -31
- package/rust/cli/discover/commands.rs +253 -0
- package/rust/cli/discover/config.rs +111 -0
- package/rust/cli/discover/fs.rs +19 -0
- package/rust/cli/discover/install.rs +103 -0
- package/rust/cli/discover/metadata.rs +48 -0
- package/rust/cli/discover/mod.rs +5 -0
- package/rust/cli/{init.rs → init/commands.rs} +88 -87
- package/rust/cli/init/mod.rs +1 -0
- package/rust/cli/install/addon.rs +126 -0
- package/rust/cli/install/bank.rs +53 -0
- package/rust/cli/{install.rs → install/commands.rs} +9 -9
- package/rust/{installer → cli/install}/mod.rs +2 -3
- package/rust/cli/install/plugin.rs +61 -0
- package/rust/cli/{login.rs → login/commands.rs} +8 -11
- package/rust/cli/login/mod.rs +1 -0
- package/rust/cli/mod.rs +2 -2
- package/rust/cli/{driver.rs → parser.rs} +7 -2
- package/rust/cli/play/commands.rs +324 -0
- package/rust/cli/play/io.rs +17 -0
- package/rust/cli/play/mod.rs +5 -0
- package/rust/cli/play/process.rs +150 -0
- package/rust/cli/play/realtime.rs +91 -0
- package/rust/cli/play/utils.rs +23 -0
- package/rust/cli/{telemetry.rs → telemetry/commands.rs} +4 -4
- package/rust/cli/telemetry/event_creator.rs +80 -0
- package/rust/cli/telemetry/mod.rs +3 -0
- package/rust/cli/telemetry/send.rs +51 -0
- package/rust/cli/{template.rs → template/commands.rs} +1 -1
- package/rust/cli/template/mod.rs +1 -0
- package/rust/cli/{update.rs → update/commands.rs} +6 -6
- package/rust/cli/update/mod.rs +1 -0
- package/rust/config/driver.rs +57 -72
- package/rust/config/mod.rs +1 -2
- package/rust/config/ops.rs +26 -0
- package/rust/config/settings.rs +40 -42
- package/rust/core/audio/engine/helpers.rs +158 -0
- package/rust/core/audio/engine/mod.rs +7 -0
- package/rust/core/audio/engine/sample.rs +359 -0
- package/rust/core/audio/engine/synth.rs +325 -0
- package/rust/core/audio/evaluator.rs +68 -27
- package/rust/core/audio/interpreter/arrow_call.rs +113 -33
- package/rust/core/audio/interpreter/call.rs +232 -56
- package/rust/core/audio/interpreter/condition.rs +3 -2
- package/rust/core/audio/interpreter/driver.rs +206 -151
- package/rust/core/audio/interpreter/let_.rs +1 -1
- package/rust/core/audio/interpreter/load.rs +2 -1
- package/rust/core/audio/interpreter/loop_.rs +7 -6
- package/rust/core/audio/interpreter/sleep.rs +2 -1
- package/rust/core/audio/interpreter/spawn.rs +186 -54
- package/rust/core/audio/interpreter/tempo.rs +31 -10
- package/rust/core/audio/interpreter/trigger.rs +2 -2
- package/rust/core/audio/loader/trigger.rs +4 -7
- package/rust/core/audio/player.rs +6 -0
- package/rust/core/audio/renderer.rs +5 -7
- package/rust/core/audio/special/env.rs +3 -1
- package/rust/core/audio/special/math.rs +26 -6
- package/rust/core/audio/special/modulator.rs +2 -2
- package/rust/core/builder/mod.rs +9 -3
- package/rust/core/debugger/lexer.rs +1 -1
- package/rust/core/debugger/mod.rs +6 -0
- package/rust/core/debugger/module.rs +4 -4
- package/rust/core/debugger/preprocessor.rs +1 -1
- package/rust/core/debugger/store.rs +2 -2
- package/rust/core/error/mod.rs +189 -0
- package/rust/core/lexer/driver.rs +61 -0
- package/rust/core/lexer/handler/arrow.rs +1 -1
- package/rust/core/lexer/handler/at.rs +1 -1
- package/rust/core/lexer/handler/brace.rs +2 -2
- package/rust/core/lexer/handler/colon.rs +1 -1
- package/rust/core/lexer/handler/comment.rs +1 -1
- package/rust/core/lexer/handler/dot.rs +1 -1
- package/rust/core/lexer/handler/driver.rs +1 -1
- package/rust/core/lexer/handler/identifier.rs +4 -3
- package/rust/core/lexer/handler/mod.rs +1 -2
- package/rust/core/lexer/handler/number.rs +1 -1
- package/rust/core/lexer/handler/operator.rs +1 -1
- package/rust/core/lexer/handler/parenthesis.rs +2 -2
- package/rust/core/lexer/handler/slash.rs +1 -1
- package/rust/core/lexer/handler/string.rs +1 -1
- package/rust/core/lexer/mod.rs +1 -52
- package/rust/core/lexer/token.rs +91 -97
- package/rust/core/mod.rs +0 -1
- package/rust/core/parser/driver.rs +78 -22
- package/rust/core/parser/handler/arrow_call.rs +28 -8
- package/rust/core/parser/handler/at.rs +55 -21
- package/rust/core/parser/handler/bank.rs +14 -4
- package/rust/core/parser/handler/condition.rs +6 -3
- package/rust/core/parser/handler/dot.rs +5 -3
- package/rust/core/parser/handler/identifier/automate.rs +13 -16
- package/rust/core/parser/handler/identifier/call.rs +4 -4
- package/rust/core/parser/handler/identifier/emit.rs +9 -5
- package/rust/core/parser/handler/identifier/function.rs +20 -7
- package/rust/core/parser/handler/identifier/group.rs +11 -7
- package/rust/core/parser/handler/identifier/let_.rs +24 -9
- package/rust/core/parser/handler/identifier/mod.rs +6 -5
- package/rust/core/parser/handler/identifier/on.rs +16 -7
- package/rust/core/parser/handler/identifier/print.rs +6 -9
- package/rust/core/parser/handler/identifier/sleep.rs +12 -5
- package/rust/core/parser/handler/identifier/spawn.rs +4 -4
- package/rust/core/parser/handler/identifier/synth.rs +79 -9
- package/rust/core/parser/handler/loop_.rs +38 -13
- package/rust/core/parser/handler/mod.rs +1 -0
- package/rust/core/parser/handler/pattern.rs +74 -0
- package/rust/core/parser/handler/tempo.rs +9 -5
- package/rust/core/parser/mod.rs +0 -1
- package/rust/core/parser/statement.rs +6 -137
- package/rust/core/plugin/loader.rs +41 -27
- package/rust/core/plugin/runner.rs +68 -17
- package/rust/core/preprocessor/loader.rs +181 -99
- package/rust/core/preprocessor/processor.rs +9 -9
- package/rust/core/preprocessor/resolver/bank.rs +6 -8
- package/rust/core/preprocessor/resolver/call.rs +47 -23
- package/rust/core/preprocessor/resolver/condition.rs +6 -8
- package/rust/core/preprocessor/resolver/driver.rs +28 -28
- package/rust/core/preprocessor/resolver/function.rs +6 -6
- package/rust/core/preprocessor/resolver/group.rs +6 -8
- package/rust/core/preprocessor/resolver/loop_.rs +8 -10
- package/rust/core/preprocessor/resolver/mod.rs +1 -0
- package/rust/core/preprocessor/resolver/pattern.rs +75 -0
- package/rust/core/preprocessor/resolver/spawn.rs +45 -22
- package/rust/core/preprocessor/resolver/synth.rs +6 -8
- package/rust/core/preprocessor/resolver/tempo.rs +6 -8
- package/rust/core/preprocessor/resolver/trigger.rs +22 -19
- package/rust/core/preprocessor/resolver/value.rs +99 -4
- package/rust/core/store/export.rs +28 -28
- package/rust/core/store/function.rs +6 -0
- package/rust/core/store/global.rs +7 -1
- package/rust/core/store/import.rs +28 -28
- package/rust/core/store/variable.rs +16 -2
- package/rust/core/utils/mod.rs +0 -1
- package/rust/lib.rs +102 -9
- package/rust/main.rs +159 -45
- package/rust/types/Cargo.toml +11 -0
- package/rust/types/src/addons.rs +55 -0
- package/rust/types/src/ast.rs +202 -0
- package/rust/types/src/config.rs +74 -0
- package/rust/types/src/lib.rs +12 -0
- package/rust/types/src/telemetry.rs +85 -0
- package/rust/utils/Cargo.toml +26 -0
- package/rust/utils/{error.rs → src/error.rs} +186 -200
- package/rust/utils/src/file.rs +94 -0
- package/rust/utils/src/first_usage.rs +97 -0
- package/rust/utils/{mod.rs → src/lib.rs} +1 -1
- package/rust/utils/{logger.rs → src/logger.rs} +17 -12
- package/rust/utils/src/path.rs +88 -0
- package/rust/utils/src/signature.rs +41 -0
- package/rust/utils/{spinner.rs → src/spinner.rs} +3 -5
- package/rust/utils/src/version.rs +27 -0
- package/rust/utils/{watcher.rs → src/watcher.rs} +13 -1
- package/rust/web/cdn.rs +34 -0
- package/templates/minimal/README.md +98 -54
- package/templates/welcome/README.md +98 -54
- package/templates/welcome/src/index.deva +56 -8
- package/templates/welcome/src/variables.deva +2 -4
- package/tests/rust/TODO.md +0 -0
- package/tests/typescript/index.spec.ts +136 -0
- package/tests/typescript/playhead.spec.ts +36 -0
- package/tests/typescript/render_e2e.spec.ts +77 -0
- package/tsconfig.json +1 -1
- package/typescript/core/functions/index.ts +83 -0
- package/typescript/core/index.ts +6 -0
- package/typescript/core/types/index.ts +4 -0
- package/typescript/core/types/plugin.ts +19 -0
- package/typescript/core/types/result.ts +29 -0
- package/typescript/core/types/statement.ts +47 -0
- package/typescript/core/types/value.ts +29 -0
- package/typescript/index.ts +7 -2
- package/typescript/pkg/devalang_core.d.ts +4 -0
- package/typescript/scripts/copy-wasm-dts.ts +41 -0
- package/rust/cli/bank.rs +0 -462
- package/rust/cli/build.rs +0 -252
- package/rust/cli/play.rs +0 -1123
- package/rust/common/cdn.rs +0 -5
- package/rust/config/loader.rs +0 -165
- package/rust/config/stats.rs +0 -257
- package/rust/core/audio/engine.rs +0 -696
- package/rust/core/shared/bank.rs +0 -21
- package/rust/core/shared/duration.rs +0 -9
- package/rust/core/shared/mod.rs +0 -3
- package/rust/core/shared/value.rs +0 -35
- package/rust/core/utils/validation.rs +0 -35
- package/rust/installer/addon.rs +0 -84
- package/rust/installer/bank.rs +0 -62
- package/rust/installer/plugin.rs +0 -54
- package/rust/installer/utils.rs +0 -56
- package/rust/utils/file.rs +0 -38
- package/rust/utils/first_usage.rs +0 -83
- package/rust/utils/signature.rs +0 -19
- package/rust/utils/telemetry.rs +0 -292
- package/rust/utils/version.rs +0 -15
- /package/rust/{common → web}/api.rs +0 -0
- /package/rust/{common → web}/mod.rs +0 -0
- /package/rust/{common → web}/sso.rs +0 -0
package/.devalang
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
[defaults]
|
|
2
|
-
entry = "./examples"
|
|
3
|
-
output = "./output"
|
|
4
|
-
watch = false
|
|
5
|
-
debug = true
|
|
6
|
-
compress = true
|
|
7
|
-
|
|
8
|
-
[[banks]]
|
|
9
|
-
path = "devalang://bank/devaloop.808"
|
|
10
|
-
version = "0.0.
|
|
1
|
+
[defaults]
|
|
2
|
+
entry = "./examples"
|
|
3
|
+
output = "./output"
|
|
4
|
+
watch = false
|
|
5
|
+
debug = true
|
|
6
|
+
compress = true
|
|
7
|
+
|
|
8
|
+
[[banks]]
|
|
9
|
+
path = "devalang://bank/devaloop.808"
|
|
10
|
+
version = "0.0.1"
|
package/.github/workflows/ci.yml
CHANGED
package/Cargo.toml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "devalang"
|
|
3
|
-
version = "0.0.1-alpha.
|
|
3
|
+
version = "0.0.1-alpha.18"
|
|
4
4
|
authors = ["Devaloop <contact@devaloop.com>"]
|
|
5
5
|
description = "Write music like code. Devalang is a domain-specific language (DSL) for sound designers and music hackers. Compose, automate, and control sound — in plain text."
|
|
6
6
|
license = "MIT"
|
|
@@ -30,6 +30,7 @@ default = ["cli"]
|
|
|
30
30
|
cli = ["crossterm", "indicatif", "inquire", "zip", "reqwest", "flate2", "tokio"]
|
|
31
31
|
|
|
32
32
|
[dependencies]
|
|
33
|
+
devalang_types = { path = "rust/types", version = "0.0.1" }
|
|
33
34
|
clap = { version = "4.5", features = ["derive"] }
|
|
34
35
|
serde = { version = "1.0", features = ["derive"] }
|
|
35
36
|
serde_json = "1.0"
|
|
@@ -47,6 +48,7 @@ crossterm = { version = "0.27", optional = true }
|
|
|
47
48
|
indicatif = { version = "0.17", optional = true }
|
|
48
49
|
inquire = { version = "0.7.5", optional = true }
|
|
49
50
|
js-sys = "0.3"
|
|
51
|
+
getrandom = { version = "0.3", features = ["wasm_js"] }
|
|
50
52
|
reqwest = { version = "0.12.22", optional = true, features = ["json"] }
|
|
51
53
|
flate2 = { version = "1.0", optional = true }
|
|
52
54
|
tokio = { version = "1", features = ["full"], optional = true }
|
|
@@ -57,4 +59,18 @@ tiny_http = "0.9.0"
|
|
|
57
59
|
dirs = "5"
|
|
58
60
|
urlencoding = "2.1"
|
|
59
61
|
uuid = { version = "1.18.0", features = ["v4"] }
|
|
60
|
-
|
|
62
|
+
console_error_panic_hook = "0.1.7"
|
|
63
|
+
|
|
64
|
+
# For wasm32, enable wasm-friendly randomness backends and avoid
|
|
65
|
+
# pulling in native-only CLI dependencies.
|
|
66
|
+
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
|
67
|
+
getrandom = { version = "0.3", features = ["wasm_js"] }
|
|
68
|
+
uuid = { version = "1.18.0", features = ["v4", "js", "rng-getrandom"] }
|
|
69
|
+
# Keep a lightweight linkage to the utils crate for wasm builds without
|
|
70
|
+
# enabling native CLI features.
|
|
71
|
+
devalang_utils = { path = "rust/utils", default-features = false, version = "0.0.1" }
|
|
72
|
+
|
|
73
|
+
# devalang_utils with CLI and wasmtime are only needed for native targets.
|
|
74
|
+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
|
75
|
+
devalang_utils = { path = "rust/utils", features = ["cli"], version = "0.0.1" }
|
|
76
|
+
wasmtime = "19"
|
package/README.md
CHANGED
|
@@ -28,13 +28,13 @@ Whether you're building a track, shaping textures, or performing live, Devalang
|
|
|
28
28
|
|
|
29
29
|
From studio sketches to live sets, Devalang gives you rhythmic control — with the elegance of code.
|
|
30
30
|
|
|
31
|
-
>
|
|
31
|
+
> **🚧 Notice 🚧**
|
|
32
32
|
>
|
|
33
|
-
> Includes synthesis, playback, and rendering features, but is still in early development.
|
|
33
|
+
> Includes synthesis, playback, and rendering features, but is still in early development, and breaking changes may occur.
|
|
34
34
|
>
|
|
35
|
-
> NEW
|
|
35
|
+
> **NEW**: [Devaforge is now available for creating addons](https://github.com/devaloop-labs/devaforge).
|
|
36
36
|
>
|
|
37
|
-
> NEW
|
|
37
|
+
> **NEW**: Now available for Windows, Linux, and macOS.
|
|
38
38
|
|
|
39
39
|
## 📚 Quick Access
|
|
40
40
|
|
|
@@ -52,24 +52,50 @@ From studio sketches to live sets, Devalang gives you rhythmic control — with
|
|
|
52
52
|
|
|
53
53
|
### Try Devalang in your browser
|
|
54
54
|
|
|
55
|
-
> Have a look at the
|
|
55
|
+
> [Have a look at the Playground to try Devalang directly in your browser](https://playground.devalang.com)
|
|
56
56
|
|
|
57
|
-
### Try Devalang
|
|
57
|
+
### Try Devalang in your terminal
|
|
58
|
+
|
|
59
|
+
#### With Node.js
|
|
58
60
|
|
|
59
61
|
```bash
|
|
60
|
-
# Install Devalang CLI globally
|
|
61
62
|
npm install -g @devaloop/devalang@latest
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
#### With Rust
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cargo install devalang
|
|
69
|
+
```
|
|
62
70
|
|
|
63
|
-
|
|
71
|
+
#### Initialize a new project
|
|
72
|
+
|
|
73
|
+
```bash
|
|
64
74
|
devalang init --name my-project --template minimal
|
|
65
75
|
```
|
|
66
76
|
|
|
77
|
+
#### Write your first script
|
|
78
|
+
|
|
67
79
|
Create a new Devalang file `src/index.deva` in the project directory:
|
|
68
80
|
|
|
69
81
|
```deva
|
|
70
82
|
# src/index.deva
|
|
71
83
|
|
|
84
|
+
# BPM definition
|
|
85
|
+
bpm 125
|
|
86
|
+
|
|
87
|
+
# Bank picking (make sure you've installed it)
|
|
88
|
+
bank devaloop.808 as my808Bank
|
|
89
|
+
|
|
90
|
+
# Pattern literal without options
|
|
91
|
+
pattern kickPattern with my808Bank.kick = "x--- x--- x--- x---"
|
|
92
|
+
|
|
72
93
|
group myGroup:
|
|
94
|
+
# Rhythmic (each beat playing a kick)
|
|
95
|
+
# on beat:
|
|
96
|
+
# .my808Bank.kick 1/4
|
|
97
|
+
|
|
98
|
+
# Synth definition with ADSR
|
|
73
99
|
let myLead = synth sine {
|
|
74
100
|
attack: 0,
|
|
75
101
|
decay: 100,
|
|
@@ -77,12 +103,27 @@ group myGroup:
|
|
|
77
103
|
release: 100
|
|
78
104
|
}
|
|
79
105
|
|
|
106
|
+
# Global automation
|
|
80
107
|
automate myLead:
|
|
108
|
+
param volume {
|
|
109
|
+
0% = 0.0
|
|
110
|
+
100% = 0.5
|
|
111
|
+
}
|
|
81
112
|
param pitch {
|
|
82
113
|
0% = -12.0
|
|
83
114
|
100% = 12.0
|
|
84
115
|
}
|
|
85
116
|
|
|
117
|
+
# Notes in a loop with condition
|
|
118
|
+
for i in [1, 2, 3]:
|
|
119
|
+
if i == 3:
|
|
120
|
+
myLead -> note(C5, { duration: 200 })
|
|
121
|
+
print "Playing note C5 for " + i
|
|
122
|
+
|
|
123
|
+
# Pause runtime for 500ms
|
|
124
|
+
sleep 500
|
|
125
|
+
|
|
126
|
+
# Note with automation
|
|
86
127
|
myLead -> note(C4, {
|
|
87
128
|
duration: 400,
|
|
88
129
|
velocity: 0.8,
|
|
@@ -94,27 +135,26 @@ group myGroup:
|
|
|
94
135
|
}
|
|
95
136
|
})
|
|
96
137
|
|
|
97
|
-
|
|
138
|
+
# Notes with params
|
|
98
139
|
myLead -> note(G4, { duration: 600, glide: true, target_freq: 659.25 })
|
|
99
140
|
myLead -> note(B3, { duration: 400, slide: true, target_amp: 0.3 })
|
|
100
141
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
call myGroup
|
|
142
|
+
# Spawning the group & the pattern to play them in parallel
|
|
143
|
+
spawn myGroup
|
|
144
|
+
spawn kickPattern
|
|
106
145
|
```
|
|
107
146
|
|
|
108
147
|
### And the best part ? You can play it directly from the command line:
|
|
109
148
|
|
|
149
|
+
#### Play the script once
|
|
150
|
+
|
|
110
151
|
```bash
|
|
111
|
-
# Play the Devalang file
|
|
112
152
|
devalang play
|
|
153
|
+
```
|
|
113
154
|
|
|
114
|
-
|
|
115
|
-
devalang play --watch
|
|
155
|
+
#### **LIVE mode** (repeat the playback + watch mode)
|
|
116
156
|
|
|
117
|
-
|
|
157
|
+
```bash
|
|
118
158
|
devalang play --repeat
|
|
119
159
|
```
|
|
120
160
|
|
|
@@ -124,7 +164,7 @@ devalang play --repeat
|
|
|
124
164
|
|
|
125
165
|
## ❓ Why Devalang ?
|
|
126
166
|
|
|
127
|
-
- 🎹 Prototype audio ideas without opening a DAW, even VSCode
|
|
167
|
+
- 🎹 Prototype audio ideas without opening a DAW, even VSCode with our Playground
|
|
128
168
|
- 💻 Integrate sound into code-based workflows
|
|
129
169
|
- 🎛️ Control audio parameters through readable syntax
|
|
130
170
|
- 🧪 Build musical logic with variables and conditions
|
|
@@ -132,31 +172,39 @@ devalang play --repeat
|
|
|
132
172
|
|
|
133
173
|
## 🚀 Features
|
|
134
174
|
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
175
|
+
- ⚡ **Fast Build & Hot Reload** — optimized build process for quicker iteration.
|
|
176
|
+
- 🎵 **Audio Engine & Real-time runner** — low-latency playback, render-to-file, and a realtime runner used by `devalang play` for live feedback.
|
|
177
|
+
- ▶️ **Live mode (watch + repeat)** — edit and hear changes instantly with `devalang play --repeat` and watch mode.
|
|
178
|
+
- 🧩 **Language primitives** — synths, notes, ADSR, maps, arrays, loops, conditionals and functions for expressive musical logic.
|
|
179
|
+
- 🎛️ **Per-note automation & modulators** — `automate` maps, `$mod.*`, `$easing.*` and `$math.*` helpers for envelopes and LFOs.
|
|
180
|
+
- 🧩 **Module system & structured AST** — import/export variables, stable AST output for debugging and tooling.
|
|
181
|
+
- 🧰 **Plugins & Addons (WASM-ready)** — install plugins/banks, `@use` directive, and WASM plugin integration so plugins can render or process audio at runtime.
|
|
182
|
+
- 📦 **Addon manager & Devaforge** — CLI commands to discover/install banks, plugins and templates; `devaforge` helps create addons.
|
|
183
|
+
- ⚙️ **CLI tooling** — `build`, `check`, `play`, `install`, `init`, `discover`, `telemetry` and more with consistent flags (`--watch`, `--debug`, `--compress`).
|
|
184
|
+
- 📂 **Project templates & examples** — quick-start templates and many example projects in `examples/`.
|
|
185
|
+
- 🧑💻 **TypeScript API & WASM distribution** — Node-friendly package with TypeScript bindings and a WASM build for browser/Node usage.
|
|
186
|
+
- 🧰 **Editor & formatting support** — VSCode extension and Prettier plugin to edit Devalang with syntax and formatting support.
|
|
187
|
+
- 🎵 **Custom samples & banks** — drop samples into `.deva` and reference them from code; banks of sounds for fast composition.
|
|
188
|
+
- 🔄 **Looping, grouping & scheduling** — precise beat-tied scheduling primitives for complex rhythmic patterns.
|
|
144
189
|
|
|
145
190
|
## 📄 Documentation
|
|
146
191
|
|
|
147
|
-
### Please refer to the
|
|
192
|
+
### [Please refer to the online documentation](https://docs.devalang.com) for detailed information on syntax, features, and usage examples
|
|
148
193
|
|
|
149
|
-
##
|
|
194
|
+
## 📰 What's new
|
|
150
195
|
|
|
151
|
-
-
|
|
152
|
-
-
|
|
196
|
+
- **Devaforge**: Introduced a new system for creating and managing addons, including a CLI for addon generation.
|
|
197
|
+
- **Documentation updates**: Improved documentation for clarity and completeness.
|
|
198
|
+
- **Discovering addons**: Introduced a new command to detect addons.
|
|
199
|
+
- **Public TypeScript API**: Added a public TypeScript API for easier integration.
|
|
200
|
+
- **Improved error messages**: Enhanced error messages for better debugging.
|
|
201
|
+
- **Bug fixes**: Various bug fixes and stability improvements.
|
|
153
202
|
|
|
154
203
|
## 🧪 Roadmap Highlights
|
|
155
204
|
|
|
156
205
|
For more info, see [docs/ROADMAP.md](./docs/ROADMAP.md)
|
|
157
206
|
|
|
158
|
-
- ⏳
|
|
159
|
-
- ⏳ Addon generator
|
|
207
|
+
- ⏳ Smart modules
|
|
160
208
|
|
|
161
209
|
## 🛡️ License
|
|
162
210
|
|
package/docs/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,97 @@
|
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
+
## Version 0.0.1-alpha.18 (2025-09-02)
|
|
8
|
+
|
|
9
|
+
### ✨ Language Features
|
|
10
|
+
|
|
11
|
+
- New `pattern` statement to define rhythmic patterns with an optional target entity.
|
|
12
|
+
- Example: `pattern kickPattern with my808.kick = "x--- x--- x--- x---"`
|
|
13
|
+
- Patterns can be invoked with `call` or `spawn` just like functions or groups.
|
|
14
|
+
|
|
15
|
+
### 🧠 Core Engine
|
|
16
|
+
|
|
17
|
+
- Pattern playback: schedules steps across one bar (4 beats), computing per-step duration and triggering the target on non-rest characters.
|
|
18
|
+
- ADSR envelope: improved interpolation at segment boundaries to avoid clicks and handle 0/1-sample edge cases.
|
|
19
|
+
- Sample engine: robust stereo-to-mono mixdown with RMS-preserving scaling; applies a tiny automatic fade (~1 ms) when samples start/end abruptly to reduce clicks.
|
|
20
|
+
|
|
21
|
+
### 🧩 Parser & Lexer
|
|
22
|
+
|
|
23
|
+
- Added `Pattern` token and parser handler; supports `pattern <name> [with <bank.trigger>] = "..."`.
|
|
24
|
+
- Introduced a dedicated lexer driver (`rust/core/lexer/driver.rs`) to separate file resolution from tokenization.
|
|
25
|
+
- Map/array parsing now logs structured errors via the shared logger instead of printing to stdout.
|
|
26
|
+
|
|
27
|
+
### 🔁 Preprocessor & Resolution
|
|
28
|
+
|
|
29
|
+
- Pattern resolver stores definitions in the variable table, enabling later `call`/`spawn` usage.
|
|
30
|
+
- Variable lookup now walks parent scopes, fixing missed resolutions for outer-scope identifiers.
|
|
31
|
+
|
|
32
|
+
### 🛠️ CLI & Telemetry
|
|
33
|
+
|
|
34
|
+
- `build`: non-watch mode now executes and surfaces errors correctly.
|
|
35
|
+
- `install`: requires authentication and reports API/JSON errors with clear messages.
|
|
36
|
+
- Telemetry: generates a stable UUID when missing; consistently records CLI version, OS, and args.
|
|
37
|
+
- Ensures the `.deva` directory exists at startup.
|
|
38
|
+
|
|
39
|
+
### 📚 Examples
|
|
40
|
+
|
|
41
|
+
- Added `examples/pattern.deva`; updated `examples/index.deva` to demonstrate `pattern` and `spawn`.
|
|
42
|
+
|
|
43
|
+
### 📦 Packaging
|
|
44
|
+
|
|
45
|
+
- Added crate metadata (description, license, authors) and pinned internal versions for `devalang_types` and `devalang_utils`.
|
|
46
|
+
|
|
47
|
+
### 🐛 Fixes & Stability
|
|
48
|
+
|
|
49
|
+
- Safer `$math` parsing with diagnostics for malformed calls and argument evaluation failures.
|
|
50
|
+
- Minor parser fixes (loop body collection, clearer error messages) and logging cleanups across modules.
|
|
51
|
+
|
|
52
|
+
## Version 0.0.1-alpha.17 (2025-08-30)
|
|
53
|
+
|
|
54
|
+
### ✨ Addons
|
|
55
|
+
|
|
56
|
+
- Discovering addons: use the CLI to discover plugins or banks : place compiled addons (.devabank, .devaplugin) anywhere into your `.deva` folder, then run:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
devalang discover
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
- Installing external addons: use the CLI to install addons:
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
devalang install <plugin | bank> user.myPlugin
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
- Plugin usage: you can now reference installed plugins directly from Devalang source
|
|
69
|
+
using the `@use` directive and an optional alias. Examples:
|
|
70
|
+
|
|
71
|
+
- `@use user.myPlugin` — exposes the plugin under its default name
|
|
72
|
+
- `@use user.myPlugin as myAlias` — expose the plugin as `myAlias` for shorter calls
|
|
73
|
+
|
|
74
|
+
### 🧩 Packaging & TypeScript
|
|
75
|
+
|
|
76
|
+
- Improved packaging and postinstall logic for the TypeScript/WASM distribution; the
|
|
77
|
+
Node package now avoids hard-failing when optional native binaries are not available.
|
|
78
|
+
- `out-tsc` postinstall now performs guarded downloads and better logging to help consumers diagnose installation issues on CI or constrained environments.
|
|
79
|
+
|
|
80
|
+
### 🧠 Architecture & Refactor
|
|
81
|
+
|
|
82
|
+
- Introduced a shared `devalang_types` crate to centralize project types and config structures — this simplifies cross-crate typing between the CLI, core, utils and WASM artifacts.
|
|
83
|
+
- Split utilities into a reusable `devalang_utils` crate (logger, watcher, spinner, file helpers, telemetry) and moved several helpers (path resolution, file copying, safe archive extraction) to that crate.
|
|
84
|
+
- Modularized CLI features, clean separation between build/process, realtime runner, IO helpers and stats collection.
|
|
85
|
+
|
|
86
|
+
### 🐛 Bug fixes & stability
|
|
87
|
+
|
|
88
|
+
- Multiple robustness fixes across the parser, preprocessor and audio engine:
|
|
89
|
+
- dotted identifiers and synth/provider resolution improvements,
|
|
90
|
+
- safer path resolution for `.deva` resources (banks, plugins, presets),
|
|
91
|
+
- improved error collection and logging with annotated stacks for better debug output.
|
|
92
|
+
- Audio runtime: better BPM/duration estimation and loop handling in the realtime runner to avoid premature termination of periodic handlers while loops execute.
|
|
93
|
+
|
|
94
|
+
### 🧪 Tests & CI
|
|
95
|
+
|
|
96
|
+
- Added test scaffolding and types to centralize cross-crate tests (test harness and lightweight types prepared in `devalang_types`); this enables adding unit tests incrementally without duplicating type definitions. (Full test coverage is ongoing.)
|
|
97
|
+
|
|
7
98
|
## Version 0.0.1-alpha.16-hotfix.2 (2025-08-29)
|
|
8
99
|
|
|
9
100
|
### 🌎 Ecosystem
|
package/docs/ROADMAP.md
CHANGED
|
@@ -22,10 +22,13 @@ Devalang is a work in progress. Here’s what we’re planning next:
|
|
|
22
22
|
- ✅ **Sample loading**: Add `@load` assignment to load samples (.mp3, .wav) for use as values.
|
|
23
23
|
- ✅ **WASM support**: Compile Devalang to WebAssembly for use in web applications and other environments.
|
|
24
24
|
- ✅ **VSCode extension**: Create a VSCode extension for syntax highlighting and code completion.
|
|
25
|
-
- ✅ **Addon generator**: Implement addon generation for creating reusable plugins, banks and presets.
|
|
26
25
|
|
|
27
|
-
##
|
|
26
|
+
## In Progress
|
|
27
|
+
|
|
28
|
+
- ⏳ **Addon generator**: Implement addon generation for creating reusable plugins, banks and presets.
|
|
29
|
+
- ⏳ **Testing**: Expand test coverage for all features.
|
|
30
|
+
|
|
31
|
+
## Planned
|
|
28
32
|
|
|
29
33
|
- ⏳ **Smart modules**: Let Devalang detect and use groups, samples, and variables without needing to import them manually.
|
|
30
|
-
- ⏳ **Other statements**: Implement `pattern`, and other control structures.
|
|
31
|
-
- ⏳ **Testing**: Expand test coverage for all features.
|
|
34
|
+
- ⏳ **Other statements**: Implement `pattern`, and other control structures.
|
package/docs/TODO.md
CHANGED
package/examples/index.deva
CHANGED
|
@@ -1,43 +1,63 @@
|
|
|
1
|
-
# This file demonstrates general
|
|
1
|
+
# This file demonstrates general use cases of Devalang.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
# BPM definition
|
|
4
|
+
bpm 125
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
# Bank picking (make sure you've installed it)
|
|
7
|
+
bank devaloop.808 as my808Bank
|
|
8
|
+
|
|
9
|
+
# Pattern literal without options
|
|
10
|
+
pattern kickPattern with my808Bank.kick = "x--- x--- x--- x---"
|
|
11
|
+
|
|
12
|
+
group myGroup:
|
|
13
|
+
# Rhythmic (each beat playing a kick)
|
|
14
|
+
# on beat:
|
|
15
|
+
# .my808Bank.kick 1/4
|
|
16
|
+
|
|
17
|
+
# Synth definition with ADSR
|
|
18
|
+
let myLead = synth sine {
|
|
7
19
|
attack: 0,
|
|
8
20
|
decay: 100,
|
|
9
21
|
sustain: 100,
|
|
10
22
|
release: 100
|
|
11
23
|
}
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
25
|
+
# Global automation
|
|
26
|
+
automate myLead:
|
|
27
|
+
param volume {
|
|
28
|
+
0% = 0.0
|
|
29
|
+
100% = 0.5
|
|
30
|
+
}
|
|
31
|
+
param pitch {
|
|
32
|
+
0% = -12.0
|
|
33
|
+
100% = 12.0
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Notes in a loop with condition
|
|
37
|
+
for i in [1, 2, 3]:
|
|
38
|
+
if i == 3:
|
|
39
|
+
myLead -> note(C5, { duration: 200 })
|
|
40
|
+
print "Playing note C5 for " + i
|
|
41
|
+
|
|
42
|
+
# Pause runtime for 500ms
|
|
43
|
+
sleep 500
|
|
44
|
+
|
|
45
|
+
# Note with automation
|
|
46
|
+
myLead -> note(C4, {
|
|
47
|
+
duration: 400,
|
|
48
|
+
velocity: 0.8,
|
|
49
|
+
automate: {
|
|
50
|
+
pan: {
|
|
51
|
+
0%: -1.0,
|
|
52
|
+
100%: 0.0
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
# Notes with params
|
|
58
|
+
myLead -> note(G4, { duration: 600, glide: true, target_freq: 659.25 })
|
|
59
|
+
myLead -> note(B3, { duration: 400, slide: true, target_amp: 0.3 })
|
|
60
|
+
|
|
61
|
+
# Spawning the group & the pattern to play them in parallel
|
|
62
|
+
spawn myGroup
|
|
63
|
+
spawn kickPattern
|
package/examples/pattern.deva
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# This file demonstrates the usage of patterns in Devaloop
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
bank devaloop.808 as my808
|
|
4
4
|
|
|
5
|
-
#
|
|
6
|
-
|
|
5
|
+
# Pattern literal without options
|
|
6
|
+
pattern kickPattern with my808.kick = "x--- x--- x--- x---"
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
call kickPattern
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ParseResult } from "../types/result";
|
|
2
|
+
import { DebugResult } from "../types/result";
|
|
3
|
+
/**
|
|
4
|
+
* Parses the user code.
|
|
5
|
+
* @param entry_path The entry path for the code.
|
|
6
|
+
* @param source The source code to parse.
|
|
7
|
+
* @returns ParseResult | any
|
|
8
|
+
*/
|
|
9
|
+
export declare function parse(entry_path: string, source: string): ParseResult | any;
|
|
10
|
+
/**
|
|
11
|
+
* Renders the debug information for the user code.
|
|
12
|
+
* @param user_code The user-provided code to render debug information for.
|
|
13
|
+
* @returns DebugResult | any
|
|
14
|
+
*/
|
|
15
|
+
export declare function debug_render(user_code: string): DebugResult | any;
|
|
16
|
+
/**
|
|
17
|
+
* Renders audio from the user code.
|
|
18
|
+
* @param user_code The user-provided code to render audio from.
|
|
19
|
+
* @returns Float32Array
|
|
20
|
+
*/
|
|
21
|
+
export declare function render_audio(user_code: string): Float32Array;
|
|
22
|
+
/**
|
|
23
|
+
* Register a JS callback to receive playhead events { time, line, column } during playback.
|
|
24
|
+
* The callback will be called with a single object argument.
|
|
25
|
+
* @param cb The callback function to register.
|
|
26
|
+
* @returns void
|
|
27
|
+
*/
|
|
28
|
+
export declare function register_playhead_callback(cb: (ev: {
|
|
29
|
+
time: number;
|
|
30
|
+
line: number;
|
|
31
|
+
column: number;
|
|
32
|
+
}) => void): any;
|
|
33
|
+
/**
|
|
34
|
+
* Unregisters the JS callback for playhead events.
|
|
35
|
+
* @returns void
|
|
36
|
+
*/
|
|
37
|
+
export declare function unregister_playhead_callback(): any;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parse = parse;
|
|
4
|
+
exports.debug_render = debug_render;
|
|
5
|
+
exports.render_audio = render_audio;
|
|
6
|
+
exports.register_playhead_callback = register_playhead_callback;
|
|
7
|
+
exports.unregister_playhead_callback = unregister_playhead_callback;
|
|
8
|
+
let wasmPkg = undefined;
|
|
9
|
+
try {
|
|
10
|
+
// prefer runtime pkg generated by wasm-pack when available
|
|
11
|
+
// require at runtime so the package can be used even if wasm hasn't been built
|
|
12
|
+
// (this keeps tests and consumers robust).
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
wasmPkg = require("../../pkg/devalang_core");
|
|
15
|
+
}
|
|
16
|
+
catch (_e) {
|
|
17
|
+
wasmPkg = undefined;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Parses the user code.
|
|
21
|
+
* @param entry_path The entry path for the code.
|
|
22
|
+
* @param source The source code to parse.
|
|
23
|
+
* @returns ParseResult | any
|
|
24
|
+
*/
|
|
25
|
+
function parse(entry_path, source) {
|
|
26
|
+
if (wasmPkg && typeof wasmPkg.parse === "function") {
|
|
27
|
+
return wasmPkg.parse(entry_path, source);
|
|
28
|
+
}
|
|
29
|
+
throw new Error("WASM binding 'parse' not available. Build the wasm package or use the JS runtime.");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Renders the debug information for the user code.
|
|
33
|
+
* @param user_code The user-provided code to render debug information for.
|
|
34
|
+
* @returns DebugResult | any
|
|
35
|
+
*/
|
|
36
|
+
function debug_render(user_code) {
|
|
37
|
+
if (wasmPkg && typeof wasmPkg.debug_render === "function") {
|
|
38
|
+
return wasmPkg.debug_render(user_code);
|
|
39
|
+
}
|
|
40
|
+
throw new Error("WASM binding 'debug_render' not available. Build the wasm package or use the JS runtime.");
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Renders audio from the user code.
|
|
44
|
+
* @param user_code The user-provided code to render audio from.
|
|
45
|
+
* @returns Float32Array
|
|
46
|
+
*/
|
|
47
|
+
function render_audio(user_code) {
|
|
48
|
+
if (wasmPkg && typeof wasmPkg.render_audio === "function") {
|
|
49
|
+
return wasmPkg.render_audio(user_code);
|
|
50
|
+
}
|
|
51
|
+
// Fallback: indicate missing wasm with an empty buffer rather than breaking consumers.
|
|
52
|
+
return new Float32Array(0);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Register a JS callback to receive playhead events { time, line, column } during playback.
|
|
56
|
+
* The callback will be called with a single object argument.
|
|
57
|
+
* @param cb The callback function to register.
|
|
58
|
+
* @returns void
|
|
59
|
+
*/
|
|
60
|
+
function register_playhead_callback(cb) {
|
|
61
|
+
if (wasmPkg && typeof wasmPkg.register_playhead_callback === "function") {
|
|
62
|
+
return wasmPkg.register_playhead_callback(cb);
|
|
63
|
+
}
|
|
64
|
+
// no-op fallback
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Unregisters the JS callback for playhead events.
|
|
69
|
+
* @returns void
|
|
70
|
+
*/
|
|
71
|
+
function unregister_playhead_callback() {
|
|
72
|
+
if (wasmPkg && typeof wasmPkg.unregister_playhead_callback === "function") {
|
|
73
|
+
return wasmPkg.unregister_playhead_callback();
|
|
74
|
+
}
|
|
75
|
+
return;
|
|
76
|
+
}
|