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 T: Transcendental,
44{
45    fn process_block(&mut self, ctx: &mut ProcessContext) -> ProcessResult<()> {
46        self.as_mut().generate(ctx.clock, &[], &[])
47    }
48}
49
50impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
51    for Box<dyn crate::traits::Processor<T, BUF_SIZE>>
52where T: Transcendental,
53{
54    fn process_block(&mut self, ctx: &mut ProcessContext) -> ProcessResult<()> {
55        self.as_mut().process(ctx.clock, &[], &[], &[], &[])
56    }
57}
58
59impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
60    for Box<dyn crate::traits::Sink<T, BUF_SIZE>>
61where T: Transcendental,
62{
63    fn process_block(&mut self, ctx: &mut ProcessContext) -> ProcessResult<()> {
64        self.as_mut().consume(ctx.clock, &[], &[], &[], &[])
65    }
66}
67
68impl<T, const BUF_SIZE: usize> Processable<T, BUF_SIZE>
69    for Box<dyn crate::traits::Router<T, BUF_SIZE>>
70where T: Transcendental,
71{
72    fn process_block(&mut self, ctx: &mut ProcessContext) -> ProcessResult<()> {
73        (**self).route(ctx.clock, &[])
74    }
75}
76
77// ============================================================================
78// NodeVariant
79// ============================================================================
80
81/// A type-erased node that wraps any of the four node roles.
82///
83/// Dispatches `process_block` and `SignalNode` methods to the inner node.
84pub enum NodeVariant<T: Transcendental, const BUF_SIZE: usize> {
85    /// Signal source node (generates audio).
86    Source(Box<dyn crate::traits::Source<T, BUF_SIZE>>),
87    /// Signal processor node (processes audio in-place).
88    Processor(Box<dyn crate::traits::Processor<T, BUF_SIZE>>),
89    /// Signal router node (routes signals between ports).
90    Router(Box<dyn crate::traits::Router<T, BUF_SIZE>>),
91    /// Signal sink node (consumes audio).
92    Sink(Box<dyn crate::traits::Sink<T, BUF_SIZE>>),
93}
94
95impl<T: Transcendental, const BUF_SIZE: usize> Processable<T, BUF_SIZE> for NodeVariant<T, BUF_SIZE> {
96    fn process_block(&mut self, ctx: &mut ProcessContext) -> ProcessResult<()> {
97        match self {
98            NodeVariant::Source(src) => src.process_block(ctx),
99            NodeVariant::Processor(proc) => proc.process_block(ctx),
100            NodeVariant::Router(rt) => rt.process_block(ctx),
101            NodeVariant::Sink(sink) => sink.process_block(ctx),
102        }
103    }
104}
105
106impl<T: Transcendental, const BUF_SIZE: usize> NodeVariant<T, BUF_SIZE> {
107    /// Set the telemetry sender for the wrapped node.
108    pub fn set_telemetry_tx(&mut self, tx: TelemetryTx) {
109        match self {
110            NodeVariant::Source(src) => SignalNode::set_telemetry_tx(src.as_mut(), tx),
111            NodeVariant::Processor(proc) => SignalNode::set_telemetry_tx(proc.as_mut(), tx),
112            NodeVariant::Router(rt) => SignalNode::set_telemetry_tx(rt.as_mut(), tx),
113            NodeVariant::Sink(sink) => SignalNode::set_telemetry_tx(sink.as_mut(), tx),
114        }
115    }
116}
117
118// ============================================================================
119// SignalNode for NodeVariant
120// ============================================================================
121
122impl<T: Transcendental, const BUF_SIZE: usize> SignalNode<T, BUF_SIZE> for NodeVariant<T, BUF_SIZE> {
123    fn node_type_id(&self) -> crate::traits::NodeTypeId
124    where Self: 'static + Sized { unreachable!() }
125    fn id(&self) -> crate::traits::NodeId {
126        match self {
127            NodeVariant::Source(src) => src.id(),
128            NodeVariant::Processor(proc) => proc.id(),
129            NodeVariant::Router(rt) => rt.id(),
130            NodeVariant::Sink(sink) => sink.id(),
131        }
132    }
133    fn set_id(&mut self, id: crate::traits::NodeId) {
134        match self {
135            NodeVariant::Source(src) => src.set_id(id),
136            NodeVariant::Processor(proc) => proc.set_id(id),
137            NodeVariant::Router(rt) => rt.set_id(id),
138            NodeVariant::Sink(sink) => sink.set_id(id),
139        }
140    }
141    fn metadata(&self) -> crate::traits::NodeMetadata {
142        match self {
143            NodeVariant::Source(src) => src.metadata(),
144            NodeVariant::Processor(proc) => proc.metadata(),
145            NodeVariant::Router(rt) => rt.metadata(),
146            NodeVariant::Sink(sink) => sink.metadata(),
147        }
148    }
149    fn init(&mut self, sample_rate: f32) {
150        match self {
151            NodeVariant::Source(src) => src.init(sample_rate),
152            NodeVariant::Processor(proc) => proc.init(sample_rate),
153            NodeVariant::Router(rt) => rt.init(sample_rate),
154            NodeVariant::Sink(sink) => sink.init(sample_rate),
155        }
156    }
157    fn reset(&mut self) {
158        match self {
159            NodeVariant::Source(src) => src.reset(),
160            NodeVariant::Processor(proc) => proc.reset(),
161            NodeVariant::Router(rt) => rt.reset(),
162            NodeVariant::Sink(sink) => sink.reset(),
163        }
164    }
165    fn get_parameter(&self, id: &crate::traits::ParameterId) -> Option<crate::traits::ParamValue> {
166        match self {
167            NodeVariant::Source(src) => src.get_parameter(id),
168            NodeVariant::Processor(proc) => proc.get_parameter(id),
169            NodeVariant::Router(rt) => rt.get_parameter(id),
170            NodeVariant::Sink(sink) => sink.get_parameter(id),
171        }
172    }
173    fn set_parameter(&mut self, id: &crate::traits::ParameterId, value: crate::traits::ParamValue) -> ProcessResult<()> {
174        match self {
175            NodeVariant::Source(src) => src.set_parameter(id, value),
176            NodeVariant::Processor(proc) => proc.set_parameter(id, value),
177            NodeVariant::Router(rt) => rt.set_parameter(id, value),
178            NodeVariant::Sink(sink) => sink.set_parameter(id, value),
179        }
180    }
181    fn input_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
182        match self {
183            NodeVariant::Source(src) => src.input_port(index),
184            NodeVariant::Processor(proc) => proc.input_port(index),
185            NodeVariant::Router(rt) => rt.input_port(index),
186            NodeVariant::Sink(sink) => sink.input_port(index),
187        }
188    }
189    fn input_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
190        match self {
191            NodeVariant::Source(src) => src.input_port_mut(index),
192            NodeVariant::Processor(proc) => proc.input_port_mut(index),
193            NodeVariant::Router(rt) => rt.input_port_mut(index),
194            NodeVariant::Sink(sink) => sink.input_port_mut(index),
195        }
196    }
197    fn output_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
198        match self {
199            NodeVariant::Source(src) => src.output_port(index),
200            NodeVariant::Processor(proc) => proc.output_port(index),
201            NodeVariant::Router(rt) => rt.output_port(index),
202            NodeVariant::Sink(sink) => sink.output_port(index),
203        }
204    }
205    fn output_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
206        match self {
207            NodeVariant::Source(src) => src.output_port_mut(index),
208            NodeVariant::Processor(proc) => proc.output_port_mut(index),
209            NodeVariant::Router(rt) => rt.output_port_mut(index),
210            NodeVariant::Sink(sink) => sink.output_port_mut(index),
211        }
212    }
213    fn control_port(&self, index: usize) -> Option<&Port<T, BUF_SIZE>> {
214        match self {
215            NodeVariant::Source(src) => src.control_port(index),
216            NodeVariant::Processor(proc) => proc.control_port(index),
217            NodeVariant::Router(rt) => rt.control_port(index),
218            NodeVariant::Sink(sink) => sink.control_port(index),
219        }
220    }
221    fn control_port_mut(&mut self, index: usize) -> Option<&mut Port<T, BUF_SIZE>> {
222        match self {
223            NodeVariant::Source(src) => src.control_port_mut(index),
224            NodeVariant::Processor(proc) => proc.control_port_mut(index),
225            NodeVariant::Router(rt) => rt.control_port_mut(index),
226            NodeVariant::Sink(sink) => sink.control_port_mut(index),
227        }
228    }
229    fn num_signal_inputs(&self) -> usize {
230        match self {
231            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_signal_inputs() }
232            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_signal_inputs() }
233            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_signal_inputs() }
234            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_signal_inputs() }
235        }
236    }
237    fn num_signal_outputs(&self) -> usize {
238        match self {
239            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_signal_outputs() }
240            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_signal_outputs() }
241            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_signal_outputs() }
242            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_signal_outputs() }
243        }
244    }
245    fn num_control_inputs(&self) -> usize {
246        match self {
247            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_control_inputs() }
248            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_control_inputs() }
249            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_control_inputs() }
250            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_control_inputs() }
251        }
252    }
253    fn num_control_outputs(&self) -> usize {
254        match self {
255            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_control_outputs() }
256            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_control_outputs() }
257            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_control_outputs() }
258            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_control_outputs() }
259        }
260    }
261    fn num_clock_inputs(&self) -> usize {
262        match self {
263            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_clock_inputs() }
264            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_clock_inputs() }
265            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_clock_inputs() }
266            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_clock_inputs() }
267        }
268    }
269    fn num_clock_outputs(&self) -> usize {
270        match self {
271            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_clock_outputs() }
272            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_clock_outputs() }
273            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_clock_outputs() }
274            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_clock_outputs() }
275        }
276    }
277    fn num_feedback_ports(&self) -> usize {
278        match self {
279            NodeVariant::Source(src) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**src; n.num_feedback_ports() }
280            NodeVariant::Processor(proc) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**proc; n.num_feedback_ports() }
281            NodeVariant::Router(rt) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**rt; n.num_feedback_ports() }
282            NodeVariant::Sink(sink) => { let n: &dyn SignalNode<T, BUF_SIZE> = &**sink; n.num_feedback_ports() }
283        }
284    }
285    fn state(&self) -> &crate::traits::NodeState<T, BUF_SIZE> {
286        match self {
287            NodeVariant::Source(src) => src.state(),
288            NodeVariant::Processor(proc) => proc.state(),
289            NodeVariant::Router(rt) => rt.state(),
290            NodeVariant::Sink(sink) => sink.state(),
291        }
292    }
293    fn state_mut(&mut self) -> &mut crate::traits::NodeState<T, BUF_SIZE> {
294        match self {
295            NodeVariant::Source(src) => src.state_mut(),
296            NodeVariant::Processor(proc) => proc.state_mut(),
297            NodeVariant::Router(rt) => rt.state_mut(),
298            NodeVariant::Sink(sink) => sink.state_mut(),
299        }
300    }
301}