1use core::marker::PhantomData;
2
3use super::*;
4
5pub struct Sine {}
7pub struct Mix {}
9pub struct AllForOne {}
11pub struct Gain {}
13pub struct Loop {}
15pub struct Concat {}
17pub struct Pan {}
19pub struct Mute {}
21pub struct Pause {}
23pub struct TrackPosition {}
25pub struct LowPass {}
27pub struct HighPass {}
29pub struct TakeLeft {}
31pub struct TakeRight {}
33pub struct Swap {}
35pub struct Clip {}
37pub struct Square {}
39pub struct Sawtooth {}
41pub struct Triangle {}
43pub struct Noise {}
45pub struct Empty {}
47pub struct Zero {}
49
50pub struct File {}
52
53trait Parent {}
55impl Parent for Mix {}
56impl Parent for AllForOne {}
57impl Parent for Gain {}
58impl Parent for Loop {}
59impl Parent for Concat {}
60impl Parent for Pan {}
61impl Parent for Mute {}
62impl Parent for Pause {}
63impl Parent for TrackPosition {}
64impl Parent for LowPass {}
65impl Parent for HighPass {}
66impl Parent for TakeLeft {}
67impl Parent for TakeRight {}
68impl Parent for Swap {}
69impl Parent for Clip {}
70
71pub struct Node<F> {
73 id: u32,
74 _flavor: PhantomData<F>,
76}
77
78pub const OUT: Node<Mix> = Node::new(0);
80
81impl<F> Node<F> {
82 #[must_use]
83 const fn new(id: u32) -> Self {
84 Self {
85 id,
86 _flavor: PhantomData,
87 }
88 }
89
90 pub fn reset(&self) {
92 unsafe { bindings::reset(self.id) }
93 }
94}
95
96#[expect(clippy::must_use_candidate, private_bounds)]
97impl<F: Parent> Node<F> {
98 pub fn add_sine(&self, f: Freq, phase: f32) -> Node<Sine> {
100 let id = unsafe { bindings::add_sine(self.id, f.0, phase) };
101 Node::new(id)
102 }
103
104 pub fn add_square(&self, f: Freq, phase: f32) -> Node<Square> {
106 let id = unsafe { bindings::add_square(self.id, f.0, phase) };
107 Node::new(id)
108 }
109
110 pub fn add_sawtooth(&self, f: Freq, phase: f32) -> Node<Sawtooth> {
112 let id = unsafe { bindings::add_sawtooth(self.id, f.0, phase) };
113 Node::new(id)
114 }
115
116 pub fn add_triangle(&self, f: Freq, phase: f32) -> Node<Triangle> {
118 let id = unsafe { bindings::add_triangle(self.id, f.0, phase) };
119 Node::new(id)
120 }
121
122 pub fn add_noise(&self, seed: i32) -> Node<Noise> {
124 let id = unsafe { bindings::add_noise(self.id, seed) };
125 Node::new(id)
126 }
127
128 pub fn add_empty(&self) -> Node<Empty> {
130 let id = unsafe { bindings::add_empty(self.id) };
131 Node::new(id)
132 }
133
134 pub fn add_zero(&self) -> Node<Zero> {
136 let id = unsafe { bindings::add_zero(self.id) };
137 Node::new(id)
138 }
139
140 pub fn add_file(&self, path: &str) -> Node<File> {
142 let ptr = path.as_ptr() as u32;
143 let len = path.len() as u32;
144 let id = unsafe { bindings::add_file(self.id, ptr, len) };
145 Node::new(id)
146 }
147
148 pub fn add_mix(&self) -> Node<Mix> {
150 let id = unsafe { bindings::add_mix(self.id) };
151 Node::new(id)
152 }
153
154 pub fn add_all_for_one(&self) -> Node<AllForOne> {
156 let id = unsafe { bindings::add_all_for_one(self.id) };
157 Node::new(id)
158 }
159
160 pub fn add_gain(&self, lvl: f32) -> Node<Gain> {
162 let id = unsafe { bindings::add_gain(self.id, lvl) };
163 Node::new(id)
164 }
165
166 pub fn add_loop(&self) -> Node<Loop> {
168 let id = unsafe { bindings::add_loop(self.id) };
169 Node::new(id)
170 }
171
172 pub fn add_concat(&self) -> Node<Concat> {
174 let id = unsafe { bindings::add_concat(self.id) };
175 Node::new(id)
176 }
177
178 pub fn add_pan(&self, lvl: f32) -> Node<Pan> {
180 let id = unsafe { bindings::add_pan(self.id, lvl) };
181 Node::new(id)
182 }
183
184 pub fn add_mute(&self) -> Node<Mute> {
186 let id = unsafe { bindings::add_mute(self.id) };
187 Node::new(id)
188 }
189
190 pub fn add_pause(&self) -> Node<Pause> {
192 let id = unsafe { bindings::add_pause(self.id) };
193 Node::new(id)
194 }
195
196 pub fn add_track_position(&self) -> Node<TrackPosition> {
198 let id = unsafe { bindings::add_track_position(self.id) };
199 Node::new(id)
200 }
201
202 pub fn add_low_pass(&self, freq: Freq, q: f32) -> Node<LowPass> {
204 let id = unsafe { bindings::add_low_pass(self.id, freq.0, q) };
205 Node::new(id)
206 }
207
208 pub fn add_high_pass(&self, freq: Freq, q: f32) -> Node<HighPass> {
210 let id = unsafe { bindings::add_high_pass(self.id, freq.0, q) };
211 Node::new(id)
212 }
213
214 pub fn add_take_left(&self) -> Node<TakeLeft> {
216 let id = unsafe { bindings::add_take_left(self.id) };
217 Node::new(id)
218 }
219
220 pub fn add_take_right(&self) -> Node<TakeRight> {
222 let id = unsafe { bindings::add_take_right(self.id) };
223 Node::new(id)
224 }
225
226 pub fn add_swap(&self) -> Node<Swap> {
228 let id = unsafe { bindings::add_swap(self.id) };
229 Node::new(id)
230 }
231
232 pub fn add_clip(&self, low: f32, high: f32) -> Node<Clip> {
234 let id = unsafe { bindings::add_clip(self.id, low, high) };
235 Node::new(id)
236 }
237
238 pub fn reset_all(&self) {
240 unsafe { bindings::reset_all(self.id) }
241 }
242
243 pub fn clear(&self) {
248 unsafe { bindings::clear(self.id) }
249 }
250}
251
252impl Node<Sine> {
253 pub fn modulate<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
255 m.modulate(self.id, 0, low.0, high.0);
256 }
257
258 pub fn set(&self, val: Freq) {
260 unsafe { bindings::set_param(self.id, 0, val.0) };
261 }
262}
263
264impl Node<Square> {
265 pub fn modulate<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
267 m.modulate(self.id, 0, low.0, high.0);
268 }
269
270 pub fn set(&self, val: Freq) {
272 unsafe { bindings::set_param(self.id, 0, val.0) };
273 }
274}
275
276impl Node<Sawtooth> {
277 pub fn modulate<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
279 m.modulate(self.id, 0, low.0, high.0);
280 }
281
282 pub fn set(&self, val: Freq) {
284 unsafe { bindings::set_param(self.id, 0, val.0) };
285 }
286}
287
288impl Node<Triangle> {
289 pub fn modulate<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
291 m.modulate(self.id, 0, low.0, high.0);
292 }
293
294 pub fn set(&self, val: Freq) {
296 unsafe { bindings::set_param(self.id, 0, val.0) };
297 }
298}
299
300impl Node<File> {
301 #[expect(clippy::cast_precision_loss)]
303 pub fn seek(&self, t: Time) {
304 unsafe { bindings::set_param(self.id, 0, t.0 as f32) };
305 }
306}
307
308impl Node<Gain> {
309 pub fn modulate<M: Modulator>(&self, low: f32, high: f32, m: M) {
311 m.modulate(self.id, 0, low, high);
312 }
313
314 pub fn set(&self, val: f32) {
316 unsafe { bindings::set_param(self.id, 0, val) };
317 }
318}
319
320impl Node<Pan> {
321 pub fn modulate<M: Modulator>(&self, low: f32, high: f32, m: M) {
323 m.modulate(self.id, 0, low, high);
324 }
325
326 pub fn set(&self, val: f32) {
328 unsafe { bindings::set_param(self.id, 0, val) };
329 }
330}
331
332impl Node<Mute> {
333 pub fn modulate<M: Modulator>(&self, low: f32, high: f32, m: M) {
337 m.modulate(self.id, 0, low, high);
338 }
339
340 pub fn mute(&self) {
341 unsafe { bindings::set_param(self.id, 0, 0.) };
342 }
343
344 pub fn unmute(&self) {
345 unsafe { bindings::set_param(self.id, 0, 1.) };
346 }
347}
348
349impl Node<Pause> {
350 pub fn modulate<M: Modulator>(&self, low: f32, high: f32, m: M) {
354 m.modulate(self.id, 0, low, high);
355 }
356
357 pub fn pause(&self) {
358 unsafe { bindings::set_param(self.id, 0, 0.) };
359 }
360
361 pub fn play(&self) {
362 unsafe { bindings::set_param(self.id, 0, 1.) };
363 }
364}
365
366impl Node<LowPass> {
367 pub fn modulate_freq<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
369 m.modulate(self.id, 0, low.0, high.0);
370 }
371
372 pub fn set_freq(&self, val: Freq) {
374 unsafe { bindings::set_param(self.id, 0, val.0) };
375 }
376}
377
378impl Node<HighPass> {
379 pub fn modulate_freq<M: Modulator>(&self, low: Freq, high: Freq, m: M) {
381 m.modulate(self.id, 0, low.0, high.0);
382 }
383
384 pub fn set_freq(&self, val: Freq) {
386 unsafe { bindings::set_param(self.id, 0, val.0) };
387 }
388}
389
390impl Node<Clip> {
391 pub fn modulate_both<M: Modulator>(&self, low: f32, high: f32, m: M) {
395 m.modulate(self.id, 0, low, high);
396 }
397
398 pub fn set_both(&self, val: f32) {
400 unsafe { bindings::set_param(self.id, 0, val) };
401 }
402
403 pub fn modulate_low<M: Modulator>(&self, low: f32, high: f32, m: M) {
405 m.modulate(self.id, 1, low, high);
406 }
407
408 pub fn set_low(&self, val: f32) {
410 unsafe { bindings::set_param(self.id, 1, val) };
411 }
412
413 pub fn modulate_high<M: Modulator>(&self, low: f32, high: f32, m: M) {
415 m.modulate(self.id, 2, low, high);
416 }
417
418 pub fn set_high(&self, val: f32) {
420 unsafe { bindings::set_param(self.id, 2, val) };
421 }
422}
423
424mod bindings {
425 #[link(wasm_import_module = "audio")]
426 unsafe extern "C" {
427 pub(super) unsafe fn add_sine(parent_id: u32, freq: f32, phase: f32) -> u32;
429 pub(super) unsafe fn add_square(parent_id: u32, freq: f32, phase: f32) -> u32;
430 pub(super) unsafe fn add_sawtooth(parent_id: u32, freq: f32, phase: f32) -> u32;
431 pub(super) unsafe fn add_triangle(parent_id: u32, freq: f32, phase: f32) -> u32;
432 pub(super) unsafe fn add_noise(parent_id: u32, seed: i32) -> u32;
433 pub(super) unsafe fn add_empty(parent_id: u32) -> u32;
434 pub(super) unsafe fn add_zero(parent_id: u32) -> u32;
435 pub(super) unsafe fn add_file(parent: u32, ptr: u32, len: u32) -> u32;
436
437 pub(super) unsafe fn add_mix(parent_id: u32) -> u32;
439 pub(super) unsafe fn add_all_for_one(parent_id: u32) -> u32;
440 pub(super) unsafe fn add_gain(parent_id: u32, lvl: f32) -> u32;
441 pub(super) unsafe fn add_loop(parent_id: u32) -> u32;
442 pub(super) unsafe fn add_concat(parent_id: u32) -> u32;
443 pub(super) unsafe fn add_pan(parent_id: u32, lvl: f32) -> u32;
444 pub(super) unsafe fn add_mute(parent_id: u32) -> u32;
445 pub(super) unsafe fn add_pause(parent_id: u32) -> u32;
446 pub(super) unsafe fn add_track_position(parent_id: u32) -> u32;
447 pub(super) unsafe fn add_low_pass(parent_id: u32, freq: f32, q: f32) -> u32;
448 pub(super) unsafe fn add_high_pass(parent_id: u32, freq: f32, q: f32) -> u32;
449 pub(super) unsafe fn add_take_left(parent_id: u32) -> u32;
450 pub(super) unsafe fn add_take_right(parent_id: u32) -> u32;
451 pub(super) unsafe fn add_swap(parent_id: u32) -> u32;
452 pub(super) unsafe fn add_clip(parent_id: u32, low: f32, high: f32) -> u32;
453
454 pub(super) unsafe fn reset(node_id: u32);
455 pub(super) unsafe fn reset_all(node_id: u32);
456 pub(super) unsafe fn clear(node_id: u32);
457 pub(super) unsafe fn set_param(node_id: u32, param: u32, val: f32);
458 }
459}