1use crate::modulators::Modulator;
2use crate::*;
3use alloc::boxed::Box;
4use alloc::vec::Vec;
5
6const MODULATE_EVERY: u32 = SAMPLE_RATE / 60;
7
8struct WiredModulator {
10 param: u8,
11 modulator: Box<dyn Modulator>,
12 time: u32,
13}
14
15pub struct Node {
16 children: Vec<Self>,
17 proc: Box<dyn Processor>,
18 modulator: Option<WiredModulator>,
19}
20
21impl Node {
22 pub(crate) fn new_root() -> Self {
23 Self {
24 children: Vec::new(),
25 proc: Box::new(Mix::new()),
26 modulator: None,
27 }
28 }
29
30 pub(crate) fn add(&mut self, proc: Box<dyn Processor>) -> Result<u8, NodeError> {
32 if self.children.len() >= 4 {
33 return Err(NodeError::TooManyChildren);
34 }
35 #[expect(clippy::cast_possible_truncation)]
36 let child_id = self.children.len() as u8;
37 let child = Self {
38 children: Vec::new(),
39 modulator: None,
40 proc,
41 };
42 self.children.push(child);
43 Ok(child_id)
44 }
45
46 pub(crate) fn get_node(&mut self, path: &[u8]) -> &mut Self {
47 let Some(first) = path.first() else {
48 return self;
49 };
50 let node = &mut self.children[*first as usize];
51 node.get_node(&path[1..])
52 }
53
54 pub(crate) fn next_frame(&mut self) -> Option<Frame> {
55 if let Some(modulator) = self.modulator.as_mut() {
56 if modulator.time % MODULATE_EVERY == 0 {
57 let val = modulator.modulator.get(modulator.time);
58 self.proc.set(modulator.param, val);
59 }
60 modulator.time += 8;
61 }
62 self.proc.process_children(&mut self.children)
63 }
64
65 pub(crate) fn clear(&mut self) {
66 self.children.clear();
67 }
68
69 pub fn reset(&mut self) {
71 self.proc.reset();
72 }
73
74 pub fn reset_all(&mut self) {
76 self.proc.reset();
77 for node in &mut self.children {
78 node.reset_all();
79 }
80 }
81
82 pub fn modulate(&mut self, param: u8, lfo: Box<dyn Modulator>) {
86 let modulator = WiredModulator {
87 param,
88 modulator: lfo,
89 time: 0,
90 };
91 self.modulator = Some(modulator);
92 }
93}