Skip to main content

rill_core/traits/
processable.rs

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