Skip to main content

rill_core/traits/
processable.rs

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