@devaloop/devalang 0.0.1-beta.2 → 0.0.1-beta.3
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.toml +84 -81
- package/README.md +3 -2
- package/docs/CHANGELOG.md +41 -0
- package/docs/ROADMAP.md +3 -3
- package/examples/chain.deva +19 -0
- package/examples/plugin.deva +10 -10
- package/examples/routing.deva +23 -0
- package/out-tsc/bin/project-version.json +6 -0
- package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -8
- package/out-tsc/scripts/version/copy-to-binary.d.ts +1 -0
- package/out-tsc/scripts/version/copy-to-binary.js +79 -0
- package/package.json +23 -10
- package/project-version.json +3 -3
- package/rust/bindings/Cargo.toml +9 -0
- package/rust/bindings/src/lib.rs +86 -0
- package/rust/cli/addon/commands.rs +35 -0
- package/rust/cli/addon/download.rs +234 -0
- package/rust/cli/addon/install.rs +33 -0
- package/rust/cli/addon/list.rs +224 -0
- package/rust/cli/addon/metadata.rs +124 -0
- package/rust/cli/addon/mod.rs +8 -0
- package/rust/cli/addon/remove.rs +271 -0
- package/rust/cli/addon/update.rs +305 -0
- package/rust/cli/{install/addon.rs → addon/utils.rs} +109 -118
- package/rust/cli/build/commands.rs +153 -153
- package/rust/cli/build/process.rs +165 -165
- package/rust/cli/check/mod.rs +208 -208
- package/rust/cli/discover/commands.rs +275 -253
- package/rust/cli/discover/config.rs +109 -111
- package/rust/cli/discover/fs.rs +19 -19
- package/rust/cli/discover/install.rs +214 -103
- package/rust/cli/discover/metadata.rs +48 -48
- package/rust/cli/discover/mod.rs +5 -5
- package/rust/cli/me/commands.rs +52 -0
- package/rust/cli/me/mod.rs +1 -0
- package/rust/cli/mod.rs +12 -12
- package/rust/cli/parser.rs +30 -69
- package/rust/cli/play/commands.rs +375 -375
- package/rust/cli/play/process.rs +159 -159
- package/rust/core/audio/engine/driver.rs +19 -2
- package/rust/core/audio/engine/export.rs +169 -169
- package/rust/core/audio/engine/mod.rs +56 -56
- package/rust/core/audio/engine/notes/dsp.rs +88 -85
- package/rust/core/audio/engine/notes/mod.rs +53 -44
- package/rust/core/audio/engine/notes/params.rs +294 -294
- package/rust/core/audio/engine/sample/insert.rs +148 -47
- package/rust/core/audio/engine/sample/mod.rs +40 -40
- package/rust/core/audio/engine/sample/padding.rs +170 -170
- package/rust/core/audio/evaluator/condition.rs +61 -61
- package/rust/core/audio/evaluator/numeric.rs +152 -152
- package/rust/core/audio/evaluator/rhs.rs +16 -16
- package/rust/core/audio/evaluator/string_expr.rs +94 -94
- package/rust/core/audio/interpreter/driver.rs +574 -574
- package/rust/core/audio/interpreter/mod.rs +2 -2
- package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +9 -5
- package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +398 -384
- package/rust/core/audio/interpreter/statements/arrow_call/methods/effects.rs +323 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +1 -0
- package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +66 -11
- package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -3
- package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -192
- package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -24
- package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -116
- package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -97
- package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -100
- package/rust/core/audio/interpreter/statements/automate.rs +16 -16
- package/rust/core/audio/interpreter/statements/call.rs +31 -1
- package/rust/core/audio/interpreter/statements/condition.rs +72 -72
- package/rust/core/audio/interpreter/statements/function.rs +24 -24
- package/rust/core/audio/interpreter/statements/let_.rs +36 -36
- package/rust/core/audio/interpreter/statements/load.rs +17 -17
- package/rust/core/audio/interpreter/statements/loop_.rs +115 -115
- package/rust/core/audio/interpreter/statements/spawn.rs +51 -2
- package/rust/core/audio/interpreter/statements/trigger.rs +242 -239
- package/rust/core/audio/loader/trigger.rs +98 -98
- package/rust/core/audio/player.rs +70 -70
- package/rust/core/audio/special/mod.rs +9 -9
- package/rust/core/builder/mod.rs +129 -129
- package/rust/core/debugger/lexer.rs +27 -27
- package/rust/core/debugger/logs.rs +52 -52
- package/rust/core/debugger/preprocessor.rs +27 -27
- package/rust/core/debugger/store.rs +38 -38
- package/rust/core/lexer/driver.rs +59 -59
- package/rust/core/lexer/handler/arrow.rs +82 -82
- package/rust/core/lexer/handler/at.rs +21 -21
- package/rust/core/lexer/handler/brace.rs +41 -41
- package/rust/core/lexer/handler/colon.rs +21 -21
- package/rust/core/lexer/handler/comment.rs +30 -30
- package/rust/core/lexer/handler/dot.rs +21 -21
- package/rust/core/lexer/handler/driver.rs +337 -337
- package/rust/core/lexer/handler/identifier.rs +47 -47
- package/rust/core/lexer/handler/indent.rs +66 -66
- package/rust/core/lexer/handler/mod.rs +15 -15
- package/rust/core/lexer/handler/newline.rs +23 -23
- package/rust/core/lexer/handler/number.rs +31 -31
- package/rust/core/lexer/handler/operator.rs +46 -46
- package/rust/core/lexer/handler/parenthesis.rs +41 -41
- package/rust/core/lexer/handler/slash.rs +21 -21
- package/rust/core/lexer/handler/string.rs +63 -63
- package/rust/core/lexer/mod.rs +3 -3
- package/rust/core/mod.rs +9 -9
- package/rust/core/parser/driver/block.rs +111 -111
- package/rust/core/parser/driver/cursor.rs +82 -82
- package/rust/core/parser/driver/driver_impl.rs +21 -1
- package/rust/core/parser/driver/mod.rs +6 -6
- package/rust/core/parser/driver/parse_array.rs +120 -120
- package/rust/core/parser/driver/parse_map.rs +247 -223
- package/rust/core/parser/driver/parser.rs +160 -160
- package/rust/core/parser/handler/arrow_call.rs +65 -14
- package/rust/core/parser/handler/identifier/synth.rs +171 -135
- package/rust/core/parser/handler/mod.rs +9 -9
- package/rust/core/parser/handler/pattern.rs +24 -1
- package/rust/core/plugin/loader.rs +137 -137
- package/rust/core/plugin/mod.rs +2 -2
- package/rust/core/plugin/runner/non_wasm.rs +481 -297
- package/rust/core/plugin/runner/wasm32.rs +1 -0
- package/rust/core/preprocessor/loader/inject.rs +313 -278
- package/rust/core/preprocessor/loader/loader_helpers.rs +110 -110
- package/rust/core/preprocessor/loader/mod.rs +235 -235
- package/rust/core/preprocessor/module.rs +55 -55
- package/rust/core/preprocessor/processor/handlers.rs +107 -107
- package/rust/core/preprocessor/resolver/bank.rs +49 -49
- package/rust/core/preprocessor/resolver/call.rs +124 -124
- package/rust/core/preprocessor/resolver/condition.rs +95 -95
- package/rust/core/preprocessor/resolver/driver.rs +324 -324
- package/rust/core/preprocessor/resolver/function.rs +69 -69
- package/rust/core/preprocessor/resolver/group.rs +122 -122
- package/rust/core/preprocessor/resolver/let_.rs +32 -32
- package/rust/core/preprocessor/resolver/loop_.rs +318 -318
- package/rust/core/preprocessor/resolver/mod.rs +16 -16
- package/rust/core/preprocessor/resolver/pattern.rs +95 -83
- package/rust/core/preprocessor/resolver/spawn.rs +99 -99
- package/rust/core/preprocessor/resolver/synth.rs +54 -54
- package/rust/core/preprocessor/resolver/tempo.rs +48 -48
- package/rust/core/preprocessor/resolver/trigger.rs +116 -116
- package/rust/core/preprocessor/resolver/value.rs +176 -176
- package/rust/core/store/global.rs +57 -57
- package/rust/lib.rs +323 -323
- package/rust/macros/Cargo.toml +14 -0
- package/rust/macros/src/lib.rs +52 -0
- package/rust/main.rs +311 -142
- package/rust/types/Cargo.toml +1 -1
- package/rust/types/src/addons.rs +3 -1
- package/rust/types/src/config.rs +1 -3
- package/rust/utils/Cargo.toml +5 -2
- package/rust/utils/src/file.rs +397 -14
- package/rust/utils/src/path.rs +31 -2
- package/rust/utils/src/version.rs +38 -7
- package/rust/web/auth.rs +5 -0
- package/rust/web/forge.rs +5 -0
- package/rust/web/mod.rs +5 -3
- package/typescript/scripts/version/copy-to-binary.ts +82 -0
- 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/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/play/process.rs
CHANGED
|
@@ -1,159 +1,159 @@
|
|
|
1
|
-
use crate::{
|
|
2
|
-
config::driver::ProjectConfig,
|
|
3
|
-
core::{
|
|
4
|
-
builder::Builder,
|
|
5
|
-
debugger::{
|
|
6
|
-
lexer::write_lexer_log_file,
|
|
7
|
-
logs::{write_module_function_log_file, write_module_variable_log_file},
|
|
8
|
-
preprocessor::write_preprocessor_log_file,
|
|
9
|
-
store::{write_function_log_file, write_variables_log_file},
|
|
10
|
-
},
|
|
11
|
-
preprocessor::loader::ModuleLoader,
|
|
12
|
-
store::global::GlobalStore,
|
|
13
|
-
},
|
|
14
|
-
};
|
|
15
|
-
use devalang_utils::path::normalize_path;
|
|
16
|
-
use devalang_utils::{
|
|
17
|
-
logger::{LogLevel, Logger},
|
|
18
|
-
spinner::start_spinner,
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
pub fn process_play(
|
|
22
|
-
_config: &Option<ProjectConfig>,
|
|
23
|
-
entry_file: &str,
|
|
24
|
-
output: &str,
|
|
25
|
-
audio_format: crate::cli::parser::AudioFormat,
|
|
26
|
-
sample_rate: u32,
|
|
27
|
-
debug: bool,
|
|
28
|
-
) -> Result<
|
|
29
|
-
(
|
|
30
|
-
f32,
|
|
31
|
-
Vec<crate::core::parser::statement::Statement>,
|
|
32
|
-
devalang_types::VariableTable,
|
|
33
|
-
devalang_types::FunctionTable,
|
|
34
|
-
crate::core::store::global::GlobalStore,
|
|
35
|
-
),
|
|
36
|
-
String,
|
|
37
|
-
> {
|
|
38
|
-
let spinner = start_spinner("Building...");
|
|
39
|
-
|
|
40
|
-
let normalized_entry = normalize_path(entry_file);
|
|
41
|
-
let normalized_output_dir = normalize_path(output);
|
|
42
|
-
|
|
43
|
-
let duration = std::time::Instant::now();
|
|
44
|
-
let mut global_store = GlobalStore::new();
|
|
45
|
-
let loader = ModuleLoader::new(&normalized_entry, &normalized_output_dir);
|
|
46
|
-
let (modules_tokens, modules_statements) = loader.load_all_modules(&mut global_store);
|
|
47
|
-
|
|
48
|
-
// Try to detect initial BPM from statements (fallback to 120.0)
|
|
49
|
-
let mut detected_bpm: f32 = 120.0;
|
|
50
|
-
let mut entry_statements: Vec<crate::core::parser::statement::Statement> = Vec::new();
|
|
51
|
-
// Prefer the entry module if present
|
|
52
|
-
if let Some(entry_stmts) = modules_statements.get(&normalized_entry) {
|
|
53
|
-
entry_statements = entry_stmts.clone();
|
|
54
|
-
for stmt in entry_stmts {
|
|
55
|
-
if let crate::core::parser::statement::StatementKind::Tempo = &stmt.kind {
|
|
56
|
-
use devalang_types::Value;
|
|
57
|
-
if let Value::Number(n) = &stmt.value {
|
|
58
|
-
detected_bpm = *n;
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
// If still default, scan other modules for a tempo directive
|
|
65
|
-
if (detected_bpm - 120.0).abs() < f32::EPSILON {
|
|
66
|
-
'outer: for (_name, stmts) in modules_statements.iter() {
|
|
67
|
-
for stmt in stmts {
|
|
68
|
-
if let crate::core::parser::statement::StatementKind::Tempo = &stmt.kind {
|
|
69
|
-
use devalang_types::Value;
|
|
70
|
-
if let Value::Number(n) = &stmt.value {
|
|
71
|
-
detected_bpm = *n;
|
|
72
|
-
break 'outer;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// SECTION Write logs
|
|
80
|
-
if debug {
|
|
81
|
-
for (module_path, module) in global_store.modules.clone() {
|
|
82
|
-
write_module_variable_log_file(
|
|
83
|
-
&normalized_output_dir,
|
|
84
|
-
&module_path,
|
|
85
|
-
&module.variable_table,
|
|
86
|
-
);
|
|
87
|
-
write_module_function_log_file(
|
|
88
|
-
&normalized_output_dir,
|
|
89
|
-
&module_path,
|
|
90
|
-
&module.function_table,
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
write_lexer_log_file(
|
|
95
|
-
&normalized_output_dir,
|
|
96
|
-
"lexer_tokens.log",
|
|
97
|
-
modules_tokens.clone(),
|
|
98
|
-
);
|
|
99
|
-
write_preprocessor_log_file(
|
|
100
|
-
&normalized_output_dir,
|
|
101
|
-
"resolved_statements.log",
|
|
102
|
-
modules_statements.clone(),
|
|
103
|
-
);
|
|
104
|
-
write_variables_log_file(
|
|
105
|
-
&normalized_output_dir,
|
|
106
|
-
"global_variables.log",
|
|
107
|
-
global_store.variables.clone(),
|
|
108
|
-
);
|
|
109
|
-
write_function_log_file(
|
|
110
|
-
&normalized_output_dir,
|
|
111
|
-
"global_functions.log",
|
|
112
|
-
global_store.functions.clone(),
|
|
113
|
-
);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// SECTION Detect errors before building (like build.rs)
|
|
117
|
-
let all_errors = crate::core::error::collect_all_errors_with_modules(&modules_statements);
|
|
118
|
-
let (warnings, criticals) = crate::core::error::partition_errors(all_errors);
|
|
119
|
-
crate::core::error::log_errors_with_stack("Play", &warnings, &criticals);
|
|
120
|
-
if !criticals.is_empty() {
|
|
121
|
-
spinner.finish_and_clear();
|
|
122
|
-
return Err(format!(
|
|
123
|
-
"play failed with {} critical error(s): {}",
|
|
124
|
-
criticals.len(),
|
|
125
|
-
criticals[0].message
|
|
126
|
-
));
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// SECTION Building AST and Audio
|
|
130
|
-
let builder = Builder::new();
|
|
131
|
-
builder.build_ast(&modules_statements, output, false);
|
|
132
|
-
let audio_format_str = format!("{:?}", audio_format);
|
|
133
|
-
builder.build_audio(
|
|
134
|
-
&modules_statements,
|
|
135
|
-
output,
|
|
136
|
-
&mut global_store,
|
|
137
|
-
Some(audio_format_str),
|
|
138
|
-
Some(sample_rate),
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
// SECTION Logging
|
|
142
|
-
let logger = Logger::new();
|
|
143
|
-
let success_message = format!(
|
|
144
|
-
"Build completed successfully in {:.2?}. Output files written to: '{}'",
|
|
145
|
-
duration.elapsed(),
|
|
146
|
-
normalized_output_dir
|
|
147
|
-
);
|
|
148
|
-
|
|
149
|
-
spinner.finish_and_clear();
|
|
150
|
-
logger.log_message(LogLevel::Success, &success_message);
|
|
151
|
-
|
|
152
|
-
Ok((
|
|
153
|
-
detected_bpm,
|
|
154
|
-
entry_statements,
|
|
155
|
-
global_store.variables.clone(),
|
|
156
|
-
global_store.functions.clone(),
|
|
157
|
-
global_store,
|
|
158
|
-
))
|
|
159
|
-
}
|
|
1
|
+
use crate::{
|
|
2
|
+
config::driver::ProjectConfig,
|
|
3
|
+
core::{
|
|
4
|
+
builder::Builder,
|
|
5
|
+
debugger::{
|
|
6
|
+
lexer::write_lexer_log_file,
|
|
7
|
+
logs::{write_module_function_log_file, write_module_variable_log_file},
|
|
8
|
+
preprocessor::write_preprocessor_log_file,
|
|
9
|
+
store::{write_function_log_file, write_variables_log_file},
|
|
10
|
+
},
|
|
11
|
+
preprocessor::loader::ModuleLoader,
|
|
12
|
+
store::global::GlobalStore,
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
use devalang_utils::path::normalize_path;
|
|
16
|
+
use devalang_utils::{
|
|
17
|
+
logger::{LogLevel, Logger},
|
|
18
|
+
spinner::start_spinner,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
pub fn process_play(
|
|
22
|
+
_config: &Option<ProjectConfig>,
|
|
23
|
+
entry_file: &str,
|
|
24
|
+
output: &str,
|
|
25
|
+
audio_format: crate::cli::parser::AudioFormat,
|
|
26
|
+
sample_rate: u32,
|
|
27
|
+
debug: bool,
|
|
28
|
+
) -> Result<
|
|
29
|
+
(
|
|
30
|
+
f32,
|
|
31
|
+
Vec<crate::core::parser::statement::Statement>,
|
|
32
|
+
devalang_types::VariableTable,
|
|
33
|
+
devalang_types::FunctionTable,
|
|
34
|
+
crate::core::store::global::GlobalStore,
|
|
35
|
+
),
|
|
36
|
+
String,
|
|
37
|
+
> {
|
|
38
|
+
let spinner = start_spinner("Building...");
|
|
39
|
+
|
|
40
|
+
let normalized_entry = normalize_path(entry_file);
|
|
41
|
+
let normalized_output_dir = normalize_path(output);
|
|
42
|
+
|
|
43
|
+
let duration = std::time::Instant::now();
|
|
44
|
+
let mut global_store = GlobalStore::new();
|
|
45
|
+
let loader = ModuleLoader::new(&normalized_entry, &normalized_output_dir);
|
|
46
|
+
let (modules_tokens, modules_statements) = loader.load_all_modules(&mut global_store);
|
|
47
|
+
|
|
48
|
+
// Try to detect initial BPM from statements (fallback to 120.0)
|
|
49
|
+
let mut detected_bpm: f32 = 120.0;
|
|
50
|
+
let mut entry_statements: Vec<crate::core::parser::statement::Statement> = Vec::new();
|
|
51
|
+
// Prefer the entry module if present
|
|
52
|
+
if let Some(entry_stmts) = modules_statements.get(&normalized_entry) {
|
|
53
|
+
entry_statements = entry_stmts.clone();
|
|
54
|
+
for stmt in entry_stmts {
|
|
55
|
+
if let crate::core::parser::statement::StatementKind::Tempo = &stmt.kind {
|
|
56
|
+
use devalang_types::Value;
|
|
57
|
+
if let Value::Number(n) = &stmt.value {
|
|
58
|
+
detected_bpm = *n;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
// If still default, scan other modules for a tempo directive
|
|
65
|
+
if (detected_bpm - 120.0).abs() < f32::EPSILON {
|
|
66
|
+
'outer: for (_name, stmts) in modules_statements.iter() {
|
|
67
|
+
for stmt in stmts {
|
|
68
|
+
if let crate::core::parser::statement::StatementKind::Tempo = &stmt.kind {
|
|
69
|
+
use devalang_types::Value;
|
|
70
|
+
if let Value::Number(n) = &stmt.value {
|
|
71
|
+
detected_bpm = *n;
|
|
72
|
+
break 'outer;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// SECTION Write logs
|
|
80
|
+
if debug {
|
|
81
|
+
for (module_path, module) in global_store.modules.clone() {
|
|
82
|
+
write_module_variable_log_file(
|
|
83
|
+
&normalized_output_dir,
|
|
84
|
+
&module_path,
|
|
85
|
+
&module.variable_table,
|
|
86
|
+
);
|
|
87
|
+
write_module_function_log_file(
|
|
88
|
+
&normalized_output_dir,
|
|
89
|
+
&module_path,
|
|
90
|
+
&module.function_table,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
write_lexer_log_file(
|
|
95
|
+
&normalized_output_dir,
|
|
96
|
+
"lexer_tokens.log",
|
|
97
|
+
modules_tokens.clone(),
|
|
98
|
+
);
|
|
99
|
+
write_preprocessor_log_file(
|
|
100
|
+
&normalized_output_dir,
|
|
101
|
+
"resolved_statements.log",
|
|
102
|
+
modules_statements.clone(),
|
|
103
|
+
);
|
|
104
|
+
write_variables_log_file(
|
|
105
|
+
&normalized_output_dir,
|
|
106
|
+
"global_variables.log",
|
|
107
|
+
global_store.variables.clone(),
|
|
108
|
+
);
|
|
109
|
+
write_function_log_file(
|
|
110
|
+
&normalized_output_dir,
|
|
111
|
+
"global_functions.log",
|
|
112
|
+
global_store.functions.clone(),
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// SECTION Detect errors before building (like build.rs)
|
|
117
|
+
let all_errors = crate::core::error::collect_all_errors_with_modules(&modules_statements);
|
|
118
|
+
let (warnings, criticals) = crate::core::error::partition_errors(all_errors);
|
|
119
|
+
crate::core::error::log_errors_with_stack("Play", &warnings, &criticals);
|
|
120
|
+
if !criticals.is_empty() {
|
|
121
|
+
spinner.finish_and_clear();
|
|
122
|
+
return Err(format!(
|
|
123
|
+
"play failed with {} critical error(s): {}",
|
|
124
|
+
criticals.len(),
|
|
125
|
+
criticals[0].message
|
|
126
|
+
));
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// SECTION Building AST and Audio
|
|
130
|
+
let builder = Builder::new();
|
|
131
|
+
builder.build_ast(&modules_statements, output, false);
|
|
132
|
+
let audio_format_str = format!("{:?}", audio_format);
|
|
133
|
+
builder.build_audio(
|
|
134
|
+
&modules_statements,
|
|
135
|
+
output,
|
|
136
|
+
&mut global_store,
|
|
137
|
+
Some(audio_format_str),
|
|
138
|
+
Some(sample_rate),
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
// SECTION Logging
|
|
142
|
+
let logger = Logger::new();
|
|
143
|
+
let success_message = format!(
|
|
144
|
+
"Build completed successfully in {:.2?}. Output files written to: '{}'",
|
|
145
|
+
duration.elapsed(),
|
|
146
|
+
normalized_output_dir
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
spinner.finish_and_clear();
|
|
150
|
+
logger.log_message(LogLevel::Success, &success_message);
|
|
151
|
+
|
|
152
|
+
Ok((
|
|
153
|
+
detected_bpm,
|
|
154
|
+
entry_statements,
|
|
155
|
+
global_store.variables.clone(),
|
|
156
|
+
global_store.functions.clone(),
|
|
157
|
+
global_store,
|
|
158
|
+
))
|
|
159
|
+
}
|
|
@@ -35,6 +35,8 @@ pub struct AudioEngine {
|
|
|
35
35
|
pub buffer: Vec<i16>,
|
|
36
36
|
/// Collected MIDI note events for export (non-audio representation).
|
|
37
37
|
pub midi_events: Vec<MidiNoteEvent>,
|
|
38
|
+
/// Map target synth -> last inserted note sample ranges (start_sample, total_samples)
|
|
39
|
+
pub last_notes: std::collections::HashMap<String, Vec<(usize, usize)>>,
|
|
38
40
|
/// Logical module name used for error traces/diagnostics.
|
|
39
41
|
pub module_name: String,
|
|
40
42
|
/// Simple diagnostic counter for inserted notes.
|
|
@@ -55,6 +57,7 @@ impl AudioEngine {
|
|
|
55
57
|
note_count: 0,
|
|
56
58
|
sample_rate: SAMPLE_RATE,
|
|
57
59
|
channels: CHANNELS,
|
|
60
|
+
last_notes: std::collections::HashMap::new(),
|
|
58
61
|
}
|
|
59
62
|
}
|
|
60
63
|
|
|
@@ -134,6 +137,7 @@ impl AudioEngine {
|
|
|
134
137
|
|
|
135
138
|
pub fn insert_note(
|
|
136
139
|
&mut self,
|
|
140
|
+
owner: Option<String>,
|
|
137
141
|
waveform: String,
|
|
138
142
|
freq: f32,
|
|
139
143
|
amp: f32,
|
|
@@ -142,10 +146,11 @@ impl AudioEngine {
|
|
|
142
146
|
synth_params: HashMap<String, Value>,
|
|
143
147
|
note_params: HashMap<String, Value>,
|
|
144
148
|
automation: Option<HashMap<String, Value>>,
|
|
145
|
-
) {
|
|
149
|
+
) -> Vec<(usize, usize)> {
|
|
146
150
|
// Delegated implementation lives in notes.rs
|
|
147
151
|
crate::core::audio::engine::notes::insert_note_impl(
|
|
148
152
|
self,
|
|
153
|
+
owner,
|
|
149
154
|
waveform,
|
|
150
155
|
freq,
|
|
151
156
|
amp,
|
|
@@ -154,7 +159,19 @@ impl AudioEngine {
|
|
|
154
159
|
synth_params,
|
|
155
160
|
note_params,
|
|
156
161
|
automation,
|
|
157
|
-
)
|
|
162
|
+
)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
pub fn record_last_note_range(
|
|
166
|
+
&mut self,
|
|
167
|
+
owner: &str,
|
|
168
|
+
start_sample: usize,
|
|
169
|
+
total_samples: usize,
|
|
170
|
+
) {
|
|
171
|
+
self.last_notes
|
|
172
|
+
.entry(owner.to_string())
|
|
173
|
+
.or_default()
|
|
174
|
+
.push((start_sample, total_samples));
|
|
158
175
|
}
|
|
159
176
|
|
|
160
177
|
// helper extraction functions left in this struct for now
|