euphony_node/
lib.rs

1pub use euphony_macros::Node;
2
3#[doc(hidden)]
4#[cfg(feature = "reflect")]
5pub mod reflect;
6
7use euphony_graph as graph;
8
9pub type Error = String;
10
11pub type BoxProcessor = Box<dyn graph::Processor<Config>>;
12
13mod sink;
14pub use sink::{SampleType, Sink};
15
16#[inline]
17pub fn spawn<const I: usize, const B: usize, N: Node<I, B>>(node: N) -> BoxProcessor {
18    Box::new(StaticNode::new(node))
19}
20
21pub type Hash = [u8; 32];
22
23pub trait BufferMap: 'static + core::fmt::Debug + Send + Sync {
24    fn get(&self, id: u64, channel: u64) -> Buffer;
25}
26
27impl BufferMap for () {
28    fn get(&self, _id: u64, _channel: u64) -> Buffer {
29        Buffer {
30            samples: &[][..],
31            hash: &[0; 32],
32        }
33    }
34}
35
36pub type Sample = f64;
37pub const LEN: usize = 4000 / (core::mem::size_of::<Sample>() / 8);
38pub type Output = [Sample; LEN];
39
40type BufferKey = (u64, u64);
41
42#[derive(Debug)]
43pub struct Context {
44    pub buffers: Box<dyn BufferMap>,
45    pub partial: Option<usize>,
46}
47
48impl Default for Context {
49    fn default() -> Self {
50        Self {
51            buffers: Box::new(()),
52            partial: None,
53        }
54    }
55}
56
57#[derive(Clone, Copy, Debug, Default)]
58pub struct Config;
59
60impl graph::Config for Config {
61    type Context = Context;
62    type Output = Output;
63    type Value = Value;
64    type Parameter = Parameter;
65}
66
67type Parameter = u64;
68
69#[derive(Clone, Copy, Debug, PartialEq)]
70pub enum ParameterValue {
71    Constant(f64),
72    Node(u64),
73    Buffer(BufferKey),
74}
75
76pub enum Value {
77    Constant(f64),
78    Buffer(BufferKey),
79}
80
81pub struct Inputs<'a, const I: usize> {
82    inputs: graph::Inputs<'a, Config>,
83    keys: &'a [graph::Input<f64>; I],
84}
85
86impl<'a, const I: usize> Inputs<'a, I> {
87    #[inline]
88    pub fn get(&self, index: usize) -> Input {
89        debug_assert!(index < I);
90        match unsafe { *self.keys.get_unchecked(index) } {
91            graph::Input::Value(v) => Input::Constant(v),
92            graph::Input::Node(n) => Input::Buffer(&self.inputs[n]),
93        }
94    }
95}
96
97#[derive(Clone, Copy, Debug)]
98pub enum Input<'a> {
99    Constant(f64),
100    Buffer(&'a Output),
101}
102
103impl<'a> Input<'a> {
104    #[inline]
105    pub fn iter(&self) -> InputIter {
106        self.into_iter()
107    }
108}
109
110impl<'a> IntoIterator for Input<'a> {
111    type Item = Sample;
112    type IntoIter = InputIter<'a>;
113
114    fn into_iter(self) -> Self::IntoIter {
115        match self {
116            Self::Constant(v) => InputIter::Constant(v),
117            Self::Buffer(v) => InputIter::Buffer(v.iter()),
118        }
119    }
120}
121
122impl<'a> From<f64> for Input<'a> {
123    fn from(value: f64) -> Self {
124        Self::Constant(value)
125    }
126}
127
128impl<'a> From<&'a Output> for Input<'a> {
129    fn from(buffer: &'a Output) -> Self {
130        Self::Buffer(buffer)
131    }
132}
133
134pub enum InputIter<'a> {
135    Constant(f64),
136    Buffer(core::slice::Iter<'a, Sample>),
137}
138
139impl<'a> Iterator for InputIter<'a> {
140    type Item = Sample;
141
142    #[inline]
143    fn next(&mut self) -> Option<Self::Item> {
144        match self {
145            Self::Constant(v) => Some(*v),
146            Self::Buffer(v) => v.next().copied(),
147        }
148    }
149}
150
151pub struct Buffers<'a, const B: usize> {
152    buffers: &'a dyn BufferMap,
153    keys: &'a [BufferKey; B],
154}
155
156impl<'a, const B: usize> Buffers<'a, B> {
157    #[inline]
158    pub fn get(&self, index: usize) -> Buffer {
159        debug_assert!(index < B);
160        let (buffer, channel) = unsafe { *self.keys.get_unchecked(index) };
161
162        // return an empty buffer if not set
163        if buffer == u64::MAX {
164            return ().get(buffer, channel);
165        }
166
167        self.buffers.get(buffer, channel)
168    }
169}
170
171pub struct Buffer<'a> {
172    pub samples: &'a [Sample],
173    pub hash: &'a Hash,
174}
175
176impl<'a> From<&'a [Sample]> for Buffer<'a> {
177    fn from(samples: &'a [Sample]) -> Self {
178        Self {
179            samples,
180            hash: &[0; 32],
181        }
182    }
183}
184
185pub struct StaticNode<const I: usize, const B: usize, P: Node<I, B>> {
186    inputs: [graph::Input<f64>; I],
187    buffers: [BufferKey; B],
188    output: Output,
189    processor: P,
190}
191
192impl<const I: usize, const B: usize, P: Node<I, B>> StaticNode<I, B, P> {
193    #[inline]
194    pub fn new(processor: P) -> Self {
195        let defaults = P::DEFAULTS;
196
197        let mut inputs = [graph::Input::Value(0.0); I];
198
199        for (from, to) in defaults.iter().zip(inputs.iter_mut()) {
200            *to = graph::Input::Value(*from);
201        }
202
203        Self {
204            inputs,
205            buffers: [(u64::MAX, u64::MAX); B],
206            output: [0.0; LEN],
207            processor,
208        }
209    }
210}
211
212impl<const I: usize, const B: usize, P: Node<I, B>> graph::Processor<Config>
213    for StaticNode<I, B, P>
214{
215    #[inline(never)]
216    fn set(
217        &mut self,
218        param: Parameter,
219        value: graph::Input<Value>,
220    ) -> Result<graph::Input<Value>, u64> {
221        let value = match value {
222            graph::Input::Value(Value::Buffer(idx)) => {
223                let input = self.buffers.get_mut(param as usize).ok_or(param)?;
224                let prev = core::mem::replace(input, idx);
225                return Ok(graph::Input::Value(Value::Buffer(prev)));
226            }
227            graph::Input::Value(Value::Constant(v)) => {
228                self.processor.trigger(param, v);
229                graph::Input::Value(v)
230            }
231            graph::Input::Node(node) => {
232                // check to see if this is a trigger
233                if self.processor.trigger(param, 0.0) {
234                    return Err(param);
235                }
236                graph::Input::Node(node)
237            }
238        };
239
240        let input = self.inputs.get_mut(param as usize).ok_or(param)?;
241        let prev = core::mem::replace(input, value);
242
243        Ok(match prev {
244            graph::Input::Value(v) => graph::Input::Value(Value::Constant(v)),
245            graph::Input::Node(n) => graph::Input::Node(n),
246        })
247    }
248
249    #[inline(never)]
250    fn remove(&mut self, node: graph::NodeKey) {
251        for input in self.inputs.iter_mut() {
252            if let graph::Input::Node(key) = input {
253                if *key == node {
254                    *input = graph::Input::Value(0.0);
255                }
256            }
257        }
258    }
259
260    #[inline(never)]
261    fn output(&self) -> &Output {
262        &self.output
263    }
264
265    #[inline(never)]
266    fn output_mut(&mut self) -> &mut Output {
267        &mut self.output
268    }
269
270    #[inline(never)]
271    fn process(&mut self, inputs: graph::Inputs<Config>, context: &Context) {
272        let inputs = Inputs {
273            inputs,
274            keys: &self.inputs,
275        };
276
277        let buffers = Buffers {
278            buffers: context.buffers.as_ref(),
279            keys: &self.buffers,
280        };
281
282        if let Some(partial) = context.partial {
283            let output = unsafe {
284                debug_assert!(partial <= LEN);
285                self.output.get_unchecked_mut(..partial)
286            };
287            self.processor.process(inputs, buffers, output);
288        } else {
289            self.processor
290                .process_full(inputs, buffers, &mut self.output);
291        }
292    }
293}
294
295pub trait Node<const INPUTS: usize, const BUFFERS: usize>: 'static + Send {
296    const DEFAULTS: [f64; INPUTS] = [0.0; INPUTS];
297
298    #[inline]
299    fn trigger(&mut self, param: Parameter, value: f64) -> bool {
300        // no op
301        let _ = param;
302        let _ = value;
303        false
304    }
305
306    #[inline]
307    fn process_full(
308        &mut self,
309        inputs: Inputs<INPUTS>,
310        buffers: Buffers<BUFFERS>,
311        output: &mut Output,
312    ) {
313        self.process(inputs, buffers, output)
314    }
315
316    fn process(&mut self, inputs: Inputs<INPUTS>, buffers: Buffers<BUFFERS>, output: &mut [Sample]);
317}