Skip to main content

rill_core/traits/
processable.rs

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