devalang_wasm/engine/functions/
effects.rs1use super::{FunctionContext, FunctionExecutor};
3use crate::language::syntax::ast::nodes::Value;
4use anyhow::{Result, anyhow};
5
6pub struct VelocityFunction;
8
9impl FunctionExecutor for VelocityFunction {
10 fn name(&self) -> &str {
11 "velocity"
12 }
13
14 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
15 if args.is_empty() {
16 return Err(anyhow!(
17 "velocity() requires 1 argument (velocity value 0-127)"
18 ));
19 }
20
21 let velocity = match &args[0] {
22 Value::Number(v) => *v,
23 _ => return Err(anyhow!("velocity() argument must be a number")),
24 };
25
26 context.set("velocity", Value::Number(velocity));
27 Ok(())
28 }
29}
30
31pub struct DurationFunction;
33
34impl FunctionExecutor for DurationFunction {
35 fn name(&self) -> &str {
36 "duration"
37 }
38
39 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
40 if args.is_empty() {
41 return Err(anyhow!("duration() requires 1 argument (duration in ms)"));
42 }
43
44 let duration_ms = match &args[0] {
45 Value::Number(d) => *d,
46 _ => return Err(anyhow!("duration() argument must be a number")),
47 };
48
49 context.set("duration", Value::Number(duration_ms));
50 context.duration = duration_ms / 1000.0; Ok(())
52 }
53}
54
55pub struct PanFunction;
57
58impl FunctionExecutor for PanFunction {
59 fn name(&self) -> &str {
60 "pan"
61 }
62
63 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
64 if args.is_empty() {
65 return Err(anyhow!("pan() requires 1 argument (pan value -1.0 to 1.0)"));
66 }
67
68 let pan = match &args[0] {
69 Value::Number(p) => *p,
70 _ => return Err(anyhow!("pan() argument must be a number")),
71 };
72
73 context.set("pan", Value::Number(pan));
74 Ok(())
75 }
76}
77
78pub struct DetuneFunction;
80
81impl FunctionExecutor for DetuneFunction {
82 fn name(&self) -> &str {
83 "detune"
84 }
85
86 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
87 if args.is_empty() {
88 return Err(anyhow!("detune() requires 1 argument (cents)"));
89 }
90
91 let detune = match &args[0] {
92 Value::Number(d) => *d,
93 _ => return Err(anyhow!("detune() argument must be a number")),
94 };
95
96 context.set("detune", Value::Number(detune));
97 Ok(())
98 }
99}
100
101pub struct SpreadFunction;
103
104impl FunctionExecutor for SpreadFunction {
105 fn name(&self) -> &str {
106 "spread"
107 }
108
109 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
110 if args.is_empty() {
111 return Err(anyhow!(
112 "spread() requires 1 argument (spread value 0.0 to 1.0)"
113 ));
114 }
115
116 let spread = match &args[0] {
117 Value::Number(s) => *s,
118 _ => return Err(anyhow!("spread() argument must be a number")),
119 };
120
121 context.set("spread", Value::Number(spread));
122 Ok(())
123 }
124}
125
126pub struct GainFunction;
128
129impl FunctionExecutor for GainFunction {
130 fn name(&self) -> &str {
131 "gain"
132 }
133
134 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
135 if args.is_empty() {
136 return Err(anyhow!("gain() requires 1 argument (gain multiplier)"));
137 }
138
139 let gain = match &args[0] {
140 Value::Number(g) => *g,
141 _ => return Err(anyhow!("gain() argument must be a number")),
142 };
143
144 context.set("gain", Value::Number(gain));
145 Ok(())
146 }
147}
148
149pub struct AttackFunction;
151
152impl FunctionExecutor for AttackFunction {
153 fn name(&self) -> &str {
154 "attack"
155 }
156
157 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
158 if args.is_empty() {
159 return Err(anyhow!("attack() requires 1 argument (attack time in ms)"));
160 }
161
162 let attack = match &args[0] {
163 Value::Number(a) => *a,
164 _ => return Err(anyhow!("attack() argument must be a number")),
165 };
166
167 context.set("attack", Value::Number(attack));
168 Ok(())
169 }
170}
171
172pub struct ReleaseFunction;
174
175impl FunctionExecutor for ReleaseFunction {
176 fn name(&self) -> &str {
177 "release"
178 }
179
180 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
181 if args.is_empty() {
182 return Err(anyhow!(
183 "release() requires 1 argument (release time in ms)"
184 ));
185 }
186
187 let release = match &args[0] {
188 Value::Number(r) => *r,
189 _ => return Err(anyhow!("release() argument must be a number")),
190 };
191
192 context.set("release", Value::Number(release));
193 Ok(())
194 }
195}
196
197pub struct DelayFunction;
200
201impl FunctionExecutor for DelayFunction {
202 fn name(&self) -> &str {
203 "delay"
204 }
205
206 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
207 if args.is_empty() {
208 return Err(anyhow!(
209 "delay() requires at least 1 argument (delay time in ms)"
210 ));
211 }
212
213 let time = match &args[0] {
215 Value::Number(t) => *t,
216 _ => {
217 return Err(anyhow!(
218 "delay() first argument must be a number (time in ms)"
219 ));
220 }
221 };
222
223 let feedback = if args.len() > 1 {
225 match &args[1] {
226 Value::Number(f) => *f,
227 _ => {
228 return Err(anyhow!(
229 "delay() second argument must be a number (feedback)"
230 ));
231 }
232 }
233 } else {
234 0.3
235 };
236
237 let mix = if args.len() > 2 {
239 match &args[2] {
240 Value::Number(m) => *m,
241 _ => return Err(anyhow!("delay() third argument must be a number (mix)")),
242 }
243 } else {
244 0.5
245 };
246
247 context.set("delay_time", Value::Number(time));
248 context.set("delay_feedback", Value::Number(feedback));
249 context.set("delay_mix", Value::Number(mix));
250
251 Ok(())
252 }
253}
254
255pub struct ReverbFunction;
258
259impl FunctionExecutor for ReverbFunction {
260 fn name(&self) -> &str {
261 "reverb"
262 }
263
264 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
265 if args.is_empty() {
266 return Err(anyhow!(
267 "reverb() requires 1 argument (reverb amount 0.0-1.0)"
268 ));
269 }
270
271 let amount = match &args[0] {
272 Value::Number(a) => *a,
273 _ => return Err(anyhow!("reverb() argument must be a number")),
274 };
275
276 context.set("reverb_amount", Value::Number(amount));
277 context.set("reverb_size", Value::Number(amount)); Ok(())
280 }
281}
282
283pub struct DriveFunction;
286
287impl FunctionExecutor for DriveFunction {
288 fn name(&self) -> &str {
289 "drive"
290 }
291
292 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
293 if args.is_empty() {
294 return Err(anyhow!(
295 "drive() requires at least 1 argument (drive amount 0.0-1.0)"
296 ));
297 }
298
299 let amount = match &args[0] {
301 Value::Number(a) => *a,
302 _ => return Err(anyhow!("drive() first argument must be a number (amount)")),
303 };
304
305 let color = if args.len() > 1 {
307 match &args[1] {
308 Value::Number(c) => *c,
309 _ => return Err(anyhow!("drive() second argument must be a number (color)")),
310 }
311 } else {
312 0.5
313 };
314
315 context.set("drive_amount", Value::Number(amount));
316 context.set("drive_amp", Value::Number(amount)); context.set("drive_color", Value::Number(color));
318
319 Ok(())
320 }
321}
322
323pub struct ChorusFunction;
325
326impl FunctionExecutor for ChorusFunction {
327 fn name(&self) -> &str {
328 "chorus"
329 }
330
331 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
332 let mut depth = 0.5; let mut rate = 1.5; let mut mix = 0.5; if let Some(Value::Map(params)) = args.first() {
339 if let Some(Value::Number(d)) = params.get("depth") {
340 depth = *d;
341 }
342 if let Some(Value::Number(r)) = params.get("rate") {
343 rate = *r;
344 }
345 if let Some(Value::Number(m)) = params.get("mix") {
346 mix = *m;
347 }
348 }
349
350 context.set("chorus_depth", Value::Number(depth));
351 context.set("chorus_rate", Value::Number(rate));
352 context.set("chorus_mix", Value::Number(mix));
353
354 Ok(())
355 }
356}
357
358pub struct FlangerFunction;
360
361impl FunctionExecutor for FlangerFunction {
362 fn name(&self) -> &str {
363 "flanger"
364 }
365
366 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
367 let mut depth = 0.7; let mut rate = 0.5; let mut feedback = 0.5; let mut mix = 0.5; if let Some(Value::Map(params)) = args.first() {
375 if let Some(Value::Number(d)) = params.get("depth") {
376 depth = *d;
377 }
378 if let Some(Value::Number(r)) = params.get("rate") {
379 rate = *r;
380 }
381 if let Some(Value::Number(f)) = params.get("feedback") {
382 feedback = *f;
383 }
384 if let Some(Value::Number(m)) = params.get("mix") {
385 mix = *m;
386 }
387 }
388
389 context.set("flanger_depth", Value::Number(depth));
390 context.set("flanger_rate", Value::Number(rate));
391 context.set("flanger_feedback", Value::Number(feedback));
392 context.set("flanger_mix", Value::Number(mix));
393
394 Ok(())
395 }
396}
397
398pub struct PhaserFunction;
400
401impl FunctionExecutor for PhaserFunction {
402 fn name(&self) -> &str {
403 "phaser"
404 }
405
406 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
407 let mut stages = 4.0; let mut rate = 0.5; let mut depth = 0.7; let mut feedback = 0.5; let mut mix = 0.5; if let Some(Value::Map(params)) = args.first() {
416 if let Some(Value::Number(s)) = params.get("stages") {
417 stages = *s;
418 }
419 if let Some(Value::Number(r)) = params.get("rate") {
420 rate = *r;
421 }
422 if let Some(Value::Number(d)) = params.get("depth") {
423 depth = *d;
424 }
425 if let Some(Value::Number(f)) = params.get("feedback") {
426 feedback = *f;
427 }
428 if let Some(Value::Number(m)) = params.get("mix") {
429 mix = *m;
430 }
431 }
432
433 context.set("phaser_stages", Value::Number(stages));
434 context.set("phaser_rate", Value::Number(rate));
435 context.set("phaser_depth", Value::Number(depth));
436 context.set("phaser_feedback", Value::Number(feedback));
437 context.set("phaser_mix", Value::Number(mix));
438
439 Ok(())
440 }
441}
442
443pub struct CompressorFunction;
445
446impl FunctionExecutor for CompressorFunction {
447 fn name(&self) -> &str {
448 "compressor"
449 }
450
451 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
452 let mut threshold = -20.0; let mut ratio = 4.0; let mut attack = 5.0; let mut release = 50.0; let mut makeup = 0.0; if let Some(Value::Map(params)) = args.first() {
461 if let Some(Value::Number(t)) = params.get("threshold") {
462 threshold = *t;
463 }
464 if let Some(Value::Number(r)) = params.get("ratio") {
465 ratio = *r;
466 }
467 if let Some(Value::Number(a)) = params.get("attack") {
468 attack = *a;
469 }
470 if let Some(Value::Number(r)) = params.get("release") {
471 release = *r;
472 }
473 if let Some(Value::Number(m)) = params.get("makeup") {
474 makeup = *m;
475 }
476 }
477
478 context.set("compressor_threshold", Value::Number(threshold));
479 context.set("compressor_ratio", Value::Number(ratio));
480 context.set("compressor_attack", Value::Number(attack));
481 context.set("compressor_release", Value::Number(release));
482 context.set("compressor_makeup", Value::Number(makeup));
483
484 Ok(())
485 }
486}
487
488pub struct DistortionFunction;
490
491impl FunctionExecutor for DistortionFunction {
492 fn name(&self) -> &str {
493 "distortion"
494 }
495
496 fn execute(&self, context: &mut FunctionContext, args: &[Value]) -> Result<()> {
497 let mut amount = 0.5; let mut tone = 0.5; let mut mix = 1.0; if let Some(Value::Map(params)) = args.first() {
504 if let Some(Value::Number(a)) = params.get("amount") {
505 amount = *a;
506 }
507 if let Some(Value::Number(t)) = params.get("tone") {
508 tone = *t;
509 }
510 if let Some(Value::Number(m)) = params.get("mix") {
511 mix = *m;
512 }
513 }
514
515 context.set("distortion_amount", Value::Number(amount));
516 context.set("distortion_tone", Value::Number(tone));
517 context.set("distortion_mix", Value::Number(mix));
518
519 Ok(())
520 }
521}