Skip to main content

rill_core/traits/
processable.rs

1//! Processable trait and NodeVariant.
2
3use crate::math::Transcendental;
4use crate::time::RenderContext;
5use crate::traits::port::Port;
6use crate::traits::Node;
7use crate::traits::ProcessResult;
8
9// ============================================================================
10// Processable Trait
11// ============================================================================
12
13/// A node or component that can process a block of signal data.
14///
15/// This is the main execution trait for the signal graph. Each node type
16/// (Source, Processor, Router, Sink) implements this via blanket impls
17/// that delegate to their respective `generate`/`process`/`route`/`consume`.
18pub trait Processable<T: Transcendental, const BUF_SIZE: usize> {
19    /// Process one block of signal samples.
20    ///
21    /// # Arguments
22    ///
23    /// * `ctx` — [`RenderContext`] with sample clock, transport state, and
24    ///   hardware clock correction.
25    ///
26    /// # Errors
27    /// Returns a [`ProcessError`](crate::traits::ProcessError) if processing fails.
28    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()>;
29}
30
31// ============================================================================
32// Blanket Implementations
33// ============================================================================
34
35impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
36    for Box<dyn crate::traits::Source<T, BUF_SIZE>>
37where
38    T: Transcendental,
39{
40    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()> {
41        // Compile-time guard: BUF_SIZE must be SIMD-aligned (multiple of 4).
42        // Fires at monomorphization time when a concrete BUF_SIZE is used.
43        const {
44            assert!(
45                BUF_SIZE.is_multiple_of(4),
46                "BUF_SIZE must be a multiple of 4 for SIMD"
47            )
48        }
49        self.as_mut().generate(ctx, &[], &[])
50    }
51}
52
53impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
54    for Box<dyn crate::traits::Processor<T, BUF_SIZE>>
55where
56    T: Transcendental,
57{
58    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()> {
59        self.as_mut().process(ctx, &[], &[], &[], &[])
60    }
61}
62
63impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
64    for Box<dyn crate::traits::Sink<T, BUF_SIZE>>
65where
66    T: Transcendental,
67{
68    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()> {
69        self.as_mut().consume(ctx, &[], &[], &[], &[])
70    }
71}
72
73impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
74    for Box<dyn crate::traits::Router<T, BUF_SIZE>>
75where
76    T: Transcendental,
77{
78    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()> {
79        (**self).route(ctx, &[])
80    }
81}
82
83// ============================================================================
84// NodeVariant
85// ============================================================================
86
87/// A type-erased node that wraps any of the four node roles.
88///
89/// Dispatches `process_block` and `Node` methods to the inner node.
90pub enum NodeVariant<T: Transcendental, const BUF_SIZE: usize> {
91    /// Signal source node (generates signal).
92    Source(Box<dyn crate::traits::Source<T, BUF_SIZE>>),
93    /// Signal processor node (processes signal in-place).
94    Processor(Box<dyn crate::traits::Processor<T, BUF_SIZE>>),
95    /// Signal router node (routes signals between ports).
96    Router(Box<dyn crate::traits::Router<T, BUF_SIZE>>),
97    /// Signal sink node (consumes signal).
98    Sink(Box<dyn crate::traits::Sink<T, BUF_SIZE>>),
99}
100
101impl<T: Transcendental, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
102    for NodeVariant<T, BUF_SIZE>
103{
104    fn process_block(&mut self, ctx: &RenderContext) -> ProcessResult<()> {
105        match self {
106            NodeVariant::Source(src) => src.process_block(ctx),
107            NodeVariant::Processor(proc) => proc.process_block(ctx),
108            NodeVariant::Router(rt) => rt.process_block(ctx),
109            NodeVariant::Sink(sink) => sink.process_block(ctx),
110        }
111    }
112}
113
114// ============================================================================
115// Node for NodeVariant
116// ============================================================================
117// Node for NodeVariant
118// ============================================================================
119
120impl<T: Transcendental, const BUF_SIZE: usize> Node<T, BUF_SIZE> for NodeVariant<T, BUF_SIZE> {
121    fn node_type_id(&self) -> crate::traits::NodeTypeId
122    where
123        Self: 'static + Sized,
124    {
125        unreachable!()
126    }
127    fn id(&self) -> crate::traits::NodeId {
128        match self {
129            NodeVariant::Source(src) => src.id(),
130            NodeVariant::Processor(proc) => proc.id(),
131            NodeVariant::Router(rt) => rt.id(),
132            NodeVariant::Sink(sink) => sink.id(),
133        }
134    }
135    fn set_id(&mut self, id: crate::traits::NodeId) {
136        match self {
137            NodeVariant::Source(src) => src.set_id(id),
138            NodeVariant::Processor(proc) => proc.set_id(id),
139            NodeVariant::Router(rt) => rt.set_id(id),
140            NodeVariant::Sink(sink) => sink.set_id(id),
141        }
142    }
143    fn metadata(&self) -> crate::traits::NodeMetadata {
144        match self {
145            NodeVariant::Source(src) => src.metadata(),
146            NodeVariant::Processor(proc) => proc.metadata(),
147            NodeVariant::Router(rt) => rt.metadata(),
148            NodeVariant::Sink(sink) => sink.metadata(),
149        }
150    }
151    fn init(&mut self, sample_rate: f32) {
152        match self {
153            NodeVariant::Source(src) => src.init(sample_rate),
154            NodeVariant::Processor(proc) => proc.init(sample_rate),
155            NodeVariant::Router(rt) => rt.init(sample_rate),
156            NodeVariant::Sink(sink) => sink.init(sample_rate),
157        }
158    }
159    fn resolve_resources(&mut self, buffers: &crate::buffer::BufferRegistry<T>) {
160        match self {
161            NodeVariant::Source(src) => src.resolve_resources(buffers),
162            NodeVariant::Processor(proc) => proc.resolve_resources(buffers),
163            NodeVariant::Router(rt) => rt.resolve_resources(buffers),
164            NodeVariant::Sink(sink) => sink.resolve_resources(buffers),
165        }
166    }
167    fn as_io_node_mut(&mut self) -> Option<&mut dyn crate::traits::node::IoNode<T, BUF_SIZE>> {
168        match self {
169            NodeVariant::Source(src) => src.as_io_node_mut(),
170            NodeVariant::Processor(proc) => proc.as_io_node_mut(),
171            NodeVariant::Router(rt) => rt.as_io_node_mut(),
172            NodeVariant::Sink(sink) => sink.as_io_node_mut(),
173        }
174    }
175    fn as_active_node_mut(
176        &mut self,
177    ) -> Option<&mut dyn crate::traits::node::ActiveNode<T, BUF_SIZE>> {
178        match self {
179            NodeVariant::Source(src) => src.as_active_node_mut(),
180            NodeVariant::Processor(proc) => proc.as_active_node_mut(),
181            NodeVariant::Router(rt) => rt.as_active_node_mut(),
182            NodeVariant::Sink(sink) => sink.as_active_node_mut(),
183        }
184    }
185    fn reset(&mut self) {
186        match self {
187            NodeVariant::Source(src) => src.reset(),
188            NodeVariant::Processor(proc) => proc.reset(),
189            NodeVariant::Router(rt) => rt.reset(),
190            NodeVariant::Sink(sink) => sink.reset(),
191        }
192    }
193    fn get_parameter(&self, id: &crate::traits::ParameterId) -> Option<crate::traits::ParamValue> {
194        match self {
195            NodeVariant::Source(src) => src.get_parameter(id),
196            NodeVariant::Processor(proc) => proc.get_parameter(id),
197            NodeVariant::Router(rt) => rt.get_parameter(id),
198            NodeVariant::Sink(sink) => sink.get_parameter(id),
199        }
200    }
201    fn set_parameter(
202        &mut self,
203        id: &crate::traits::ParameterId,
204        value: crate::traits::ParamValue,
205    ) -> ProcessResult<()> {
206        match self {
207            NodeVariant::Source(src) => src.set_parameter(id, value),
208            NodeVariant::Processor(proc) => proc.set_parameter(id, value),
209            NodeVariant::Router(rt) => rt.set_parameter(id, value),
210            NodeVariant::Sink(sink) => sink.set_parameter(id, value),
211        }
212    }
213    fn input_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
214        match self {
215            NodeVariant::Source(src) => src.input_port(index),
216            NodeVariant::Processor(proc) => proc.input_port(index),
217            NodeVariant::Router(rt) => rt.input_port(index),
218            NodeVariant::Sink(sink) => sink.input_port(index),
219        }
220    }
221    fn input_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
222        match self {
223            NodeVariant::Source(src) => src.input_port_mut(index),
224            NodeVariant::Processor(proc) => proc.input_port_mut(index),
225            NodeVariant::Router(rt) => rt.input_port_mut(index),
226            NodeVariant::Sink(sink) => sink.input_port_mut(index),
227        }
228    }
229    fn output_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
230        match self {
231            NodeVariant::Source(src) => src.output_port(index),
232            NodeVariant::Processor(proc) => proc.output_port(index),
233            NodeVariant::Router(rt) => rt.output_port(index),
234            NodeVariant::Sink(sink) => sink.output_port(index),
235        }
236    }
237    fn output_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
238        match self {
239            NodeVariant::Source(src) => src.output_port_mut(index),
240            NodeVariant::Processor(proc) => proc.output_port_mut(index),
241            NodeVariant::Router(rt) => rt.output_port_mut(index),
242            NodeVariant::Sink(sink) => sink.output_port_mut(index),
243        }
244    }
245    fn control_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
246        match self {
247            NodeVariant::Source(src) => src.control_port(index),
248            NodeVariant::Processor(proc) => proc.control_port(index),
249            NodeVariant::Router(rt) => rt.control_port(index),
250            NodeVariant::Sink(sink) => sink.control_port(index),
251        }
252    }
253    fn control_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
254        match self {
255            NodeVariant::Source(src) => src.control_port_mut(index),
256            NodeVariant::Processor(proc) => proc.control_port_mut(index),
257            NodeVariant::Router(rt) => rt.control_port_mut(index),
258            NodeVariant::Sink(sink) => sink.control_port_mut(index),
259        }
260    }
261    fn num_signal_inputs(&self) -> usize {
262        match self {
263            NodeVariant::Source(src) => {
264                let n: &dyn Node<T, BUF_SIZE> = &**src;
265                n.num_signal_inputs()
266            }
267            NodeVariant::Processor(proc) => {
268                let n: &dyn Node<T, BUF_SIZE> = &**proc;
269                n.num_signal_inputs()
270            }
271            NodeVariant::Router(rt) => {
272                let n: &dyn Node<T, BUF_SIZE> = &**rt;
273                n.num_signal_inputs()
274            }
275            NodeVariant::Sink(sink) => {
276                let n: &dyn Node<T, BUF_SIZE> = &**sink;
277                n.num_signal_inputs()
278            }
279        }
280    }
281    fn num_signal_outputs(&self) -> usize {
282        match self {
283            NodeVariant::Source(src) => {
284                let n: &dyn Node<T, BUF_SIZE> = &**src;
285                n.num_signal_outputs()
286            }
287            NodeVariant::Processor(proc) => {
288                let n: &dyn Node<T, BUF_SIZE> = &**proc;
289                n.num_signal_outputs()
290            }
291            NodeVariant::Router(rt) => {
292                let n: &dyn Node<T, BUF_SIZE> = &**rt;
293                n.num_signal_outputs()
294            }
295            NodeVariant::Sink(sink) => {
296                let n: &dyn Node<T, BUF_SIZE> = &**sink;
297                n.num_signal_outputs()
298            }
299        }
300    }
301    fn num_control_inputs(&self) -> usize {
302        match self {
303            NodeVariant::Source(src) => {
304                let n: &dyn Node<T, BUF_SIZE> = &**src;
305                n.num_control_inputs()
306            }
307            NodeVariant::Processor(proc) => {
308                let n: &dyn Node<T, BUF_SIZE> = &**proc;
309                n.num_control_inputs()
310            }
311            NodeVariant::Router(rt) => {
312                let n: &dyn Node<T, BUF_SIZE> = &**rt;
313                n.num_control_inputs()
314            }
315            NodeVariant::Sink(sink) => {
316                let n: &dyn Node<T, BUF_SIZE> = &**sink;
317                n.num_control_inputs()
318            }
319        }
320    }
321    fn num_control_outputs(&self) -> usize {
322        match self {
323            NodeVariant::Source(src) => {
324                let n: &dyn Node<T, BUF_SIZE> = &**src;
325                n.num_control_outputs()
326            }
327            NodeVariant::Processor(proc) => {
328                let n: &dyn Node<T, BUF_SIZE> = &**proc;
329                n.num_control_outputs()
330            }
331            NodeVariant::Router(rt) => {
332                let n: &dyn Node<T, BUF_SIZE> = &**rt;
333                n.num_control_outputs()
334            }
335            NodeVariant::Sink(sink) => {
336                let n: &dyn Node<T, BUF_SIZE> = &**sink;
337                n.num_control_outputs()
338            }
339        }
340    }
341    fn num_clock_inputs(&self) -> usize {
342        match self {
343            NodeVariant::Source(src) => {
344                let n: &dyn Node<T, BUF_SIZE> = &**src;
345                n.num_clock_inputs()
346            }
347            NodeVariant::Processor(proc) => {
348                let n: &dyn Node<T, BUF_SIZE> = &**proc;
349                n.num_clock_inputs()
350            }
351            NodeVariant::Router(rt) => {
352                let n: &dyn Node<T, BUF_SIZE> = &**rt;
353                n.num_clock_inputs()
354            }
355            NodeVariant::Sink(sink) => {
356                let n: &dyn Node<T, BUF_SIZE> = &**sink;
357                n.num_clock_inputs()
358            }
359        }
360    }
361    fn num_clock_outputs(&self) -> usize {
362        match self {
363            NodeVariant::Source(src) => {
364                let n: &dyn Node<T, BUF_SIZE> = &**src;
365                n.num_clock_outputs()
366            }
367            NodeVariant::Processor(proc) => {
368                let n: &dyn Node<T, BUF_SIZE> = &**proc;
369                n.num_clock_outputs()
370            }
371            NodeVariant::Router(rt) => {
372                let n: &dyn Node<T, BUF_SIZE> = &**rt;
373                n.num_clock_outputs()
374            }
375            NodeVariant::Sink(sink) => {
376                let n: &dyn Node<T, BUF_SIZE> = &**sink;
377                n.num_clock_outputs()
378            }
379        }
380    }
381    fn num_feedback_ports(&self) -> usize {
382        match self {
383            NodeVariant::Source(src) => {
384                let n: &dyn Node<T, BUF_SIZE> = &**src;
385                n.num_feedback_ports()
386            }
387            NodeVariant::Processor(proc) => {
388                let n: &dyn Node<T, BUF_SIZE> = &**proc;
389                n.num_feedback_ports()
390            }
391            NodeVariant::Router(rt) => {
392                let n: &dyn Node<T, BUF_SIZE> = &**rt;
393                n.num_feedback_ports()
394            }
395            NodeVariant::Sink(sink) => {
396                let n: &dyn Node<T, BUF_SIZE> = &**sink;
397                n.num_feedback_ports()
398            }
399        }
400    }
401    fn state(&self) -> &crate::traits::NodeState<T, BUF_SIZE> {
402        match self {
403            NodeVariant::Source(src) => src.state(),
404            NodeVariant::Processor(proc) => proc.state(),
405            NodeVariant::Router(rt) => rt.state(),
406            NodeVariant::Sink(sink) => sink.state(),
407        }
408    }
409    fn state_mut(&mut self) -> &mut crate::traits::NodeState<T, BUF_SIZE> {
410        match self {
411            NodeVariant::Source(src) => src.state_mut(),
412            NodeVariant::Processor(proc) => proc.state_mut(),
413            NodeVariant::Router(rt) => rt.state_mut(),
414            NodeVariant::Sink(sink) => sink.state_mut(),
415        }
416    }
417}