firefly_audio/
node.rs

1use crate::modulators::Modulator;
2use crate::*;
3use alloc::boxed::Box;
4use alloc::vec::Vec;
5
6const MODULATE_EVERY: u32 = SAMPLE_RATE / 60;
7
8/// A modulator connected to a parameter of a node.
9struct 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    /// Add a child node.
31    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    /// Reset the current node processor to its initial state.
70    pub fn reset(&mut self) {
71        self.proc.reset();
72    }
73
74    /// Reset the current node and all its children.
75    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    // TODO: reset modulator
83
84    /// Set modulator for the given parameter.
85    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}