1use crate::queues::signal::SetParameter;
10use crate::time::ClockTick;
11use crate::traits::param::{ParamMetadata, ParamValue, ParameterId};
12use crate::traits::ProcessResult;
13use std::any::TypeId;
14use std::fmt;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
22pub struct NodeId(pub u32);
23
24impl NodeId {
25 pub const fn new(id: u32) -> Self {
27 Self(id)
28 }
29
30 pub const fn inner(&self) -> u32 {
32 self.0
33 }
34}
35
36impl fmt::Display for NodeId {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 write!(f, "Node({})", self.0)
39 }
40}
41
42impl From<u32> for NodeId {
43 fn from(id: u32) -> Self {
44 Self(id)
45 }
46}
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
54pub enum NodeCategory {
55 Source,
57
58 Processor,
60
61 Sink,
63
64 Utility,
66
67 Analyzer,
69
70 Sequencer,
72}
73
74impl NodeCategory {
75 pub const fn name(&self) -> &'static str {
77 match self {
78 Self::Source => "source",
79 Self::Processor => "processor",
80 Self::Sink => "sink",
81 Self::Utility => "utility",
82 Self::Analyzer => "analyzer",
83 Self::Sequencer => "sequencer",
84 }
85 }
86}
87
88impl fmt::Display for NodeCategory {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 write!(f, "{}", self.name())
91 }
92}
93
94#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
100pub struct NodeTypeId(TypeId);
101
102impl NodeTypeId {
103 pub fn of<T: 'static + ?Sized>() -> Self {
105 Self(TypeId::of::<T>())
106 }
107
108 pub fn as_type_id(&self) -> TypeId {
110 self.0
111 }
112}
113
114#[derive(Debug, Clone)]
120pub struct NodeMetadata {
121 pub name: String,
123
124 pub type_name: Option<String>,
127
128 pub category: NodeCategory,
130
131 pub description: String,
133
134 pub author: String,
136
137 pub version: String,
139
140 pub signal_inputs: usize,
142
143 pub signal_outputs: usize,
145
146 pub control_inputs: usize,
148
149 pub control_outputs: usize,
151
152 pub clock_inputs: usize,
154
155 pub clock_outputs: usize,
157
158 pub feedback_ports: usize,
160
161 pub parameters: Vec<ParamMetadata>,
163}
164
165impl NodeMetadata {
166 pub fn new(name: &str, category: NodeCategory) -> Self {
168 Self {
169 type_name: None,
170 name: name.to_string(),
171 category,
172 description: String::new(),
173 author: String::new(),
174 version: String::new(),
175 signal_inputs: 0,
176 signal_outputs: 0,
177 control_inputs: 0,
178 control_outputs: 0,
179 clock_inputs: 0,
180 clock_outputs: 0,
181 feedback_ports: 0,
182 parameters: Vec::new(),
183 }
184 }
185}
186
187#[derive(Debug, Clone)]
194pub struct NodeState<T: crate::math::Transcendental, const BUF_SIZE: usize> {
195 pub sample_pos: u64,
197
198 pub blocks_processed: u64,
200
201 pub sample_rate: f32,
203
204 pub active: bool,
206
207 pub phase: T,
209}
210
211impl<T: crate::math::Transcendental, const BUF_SIZE: usize> NodeState<T, BUF_SIZE> {
212 pub fn new(sample_rate: f32) -> Self {
214 Self {
215 sample_pos: 0,
216 blocks_processed: 0,
217 sample_rate,
218 active: true,
219 phase: T::ZERO,
220 }
221 }
222
223 pub fn advance(&mut self) {
225 self.sample_pos += BUF_SIZE as u64;
226 self.blocks_processed += 1;
227 }
228
229 pub fn current_time_seconds(&self) -> f64 {
231 self.sample_pos as f64 / self.sample_rate as f64
232 }
233
234 pub fn reset(&mut self) {
236 self.sample_pos = 0;
237 self.blocks_processed = 0;
238 self.phase = T::ZERO;
239 }
240}
241
242pub trait SignalNode<T: crate::math::Transcendental, const BUF_SIZE: usize>: Send + Sync {
258 fn metadata(&self) -> NodeMetadata;
260
261 fn node_type_id(&self) -> NodeTypeId
263 where
264 Self: 'static + Sized,
265 {
266 NodeTypeId::of::<Self>()
267 }
268
269 fn init(&mut self, sample_rate: f32);
271
272 fn reset(&mut self);
274
275 fn get_parameter(&self, id: &ParameterId) -> Option<ParamValue>;
277
278 fn set_parameter(&mut self, id: &ParameterId, value: ParamValue) -> ProcessResult<()>;
280
281 fn apply_set_parameter(&mut self, cmd: &SetParameter) -> ProcessResult<()> {
286 use crate::traits::port::{PortDirection, PortType};
287 let value = T::from_f32(cmd.value);
288 let port = match cmd.port.port_type() {
289 PortType::Control => self.control_port_mut(cmd.port.index() as usize),
290 PortType::Signal => match cmd.port.direction() {
291 PortDirection::Input => self.input_port_mut(cmd.port.index() as usize),
292 PortDirection::Output => self.output_port_mut(cmd.port.index() as usize),
293 },
294 PortType::Param => self.input_port_mut(cmd.port.index() as usize),
295 PortType::Clock | PortType::Feedback => None,
296 };
297 match port {
298 Some(p) => {
299 p.set_value(value);
300 Ok(())
301 }
302 None => self.set_parameter(&cmd.parameter, ParamValue::Float(cmd.value)),
303 }
304 }
305
306 fn id(&self) -> NodeId;
308
309 fn set_id(&mut self, id: NodeId);
311
312 fn input_port(&self, index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>>;
314
315 fn input_port_mut(
317 &mut self,
318 index: usize,
319 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>>;
320
321 fn output_port(&self, index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>>;
323
324 fn output_port_mut(
326 &mut self,
327 index: usize,
328 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>>;
329
330 fn control_port(&self, index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>>;
332
333 fn control_port_mut(
335 &mut self,
336 index: usize,
337 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>>;
338
339 fn state(&self) -> &NodeState<T, BUF_SIZE>;
341
342 fn state_mut(&mut self) -> &mut NodeState<T, BUF_SIZE>;
344
345 fn num_signal_inputs(&self) -> usize {
351 0
352 }
353
354 fn num_signal_outputs(&self) -> usize {
356 0
357 }
358
359 fn num_control_inputs(&self) -> usize {
361 0
362 }
363
364 fn num_control_outputs(&self) -> usize {
366 0
367 }
368
369 fn num_clock_inputs(&self) -> usize {
371 0
372 }
373
374 fn num_clock_outputs(&self) -> usize {
376 0
377 }
378
379 fn num_feedback_ports(&self) -> usize {
381 0
382 }
383
384 fn num_inputs(&self) -> usize {
386 self.num_signal_inputs()
387 + self.num_control_inputs()
388 + self.num_clock_inputs()
389 + self.num_feedback_ports()
390 }
391
392 fn num_outputs(&self) -> usize {
394 self.num_signal_outputs() + self.num_control_outputs() + self.num_clock_outputs()
395 }
396}
397
398pub trait Source<T: crate::math::Transcendental, const BUF_SIZE: usize>: SignalNode<T, BUF_SIZE> {
407 fn generate(
417 &mut self,
418 clock: &ClockTick,
419 control_inputs: &[T],
420 clock_inputs: &[ClockTick],
421 ) -> ProcessResult<()>;
422
423 fn num_signal_outputs(&self) -> usize {
425 1
426 }
427
428 fn num_control_inputs(&self) -> usize {
430 0
431 }
432
433 fn num_clock_inputs(&self) -> usize {
435 0
436 }
437}
438
439pub trait Processor<T: crate::math::Transcendental, const BUF_SIZE: usize>:
448 SignalNode<T, BUF_SIZE>
449{
450 fn process(
462 &mut self,
463 clock: &ClockTick,
464 signal_inputs: &[&[T; BUF_SIZE]],
465 control_inputs: &[T],
466 clock_inputs: &[ClockTick],
467 feedback_inputs: &[&[T; BUF_SIZE]],
468 ) -> ProcessResult<()>;
469
470 fn latency(&self) -> usize {
472 0
473 }
474}
475
476pub trait Sink<T: crate::math::Transcendental, const BUF_SIZE: usize>: SignalNode<T, BUF_SIZE> {
485 fn consume(
494 &mut self,
495 clock: &ClockTick,
496 signal_inputs: &[&[T; BUF_SIZE]],
497 control_inputs: &[T],
498 clock_inputs: &[ClockTick],
499 feedback_inputs: &[&[T; BUF_SIZE]],
500 ) -> ProcessResult<()>;
501}
502
503#[cfg(test)]
508mod tests {
509 use super::*;
510 use crate::math::Transcendental;
511
512 struct TestNode;
513
514 impl<T: Transcendental, const BUF_SIZE: usize> SignalNode<T, BUF_SIZE> for TestNode {
515 fn metadata(&self) -> NodeMetadata {
516 NodeMetadata {
517 name: "Test".to_string(),
518 type_name: None,
519 category: NodeCategory::Utility,
520 description: "Test node".to_string(),
521 author: "Rill".to_string(),
522 version: "1.0".to_string(),
523 signal_inputs: 0,
524 signal_outputs: 0,
525 control_inputs: 0,
526 control_outputs: 0,
527 clock_inputs: 0,
528 clock_outputs: 0,
529 feedback_ports: 0,
530 parameters: vec![],
531 }
532 }
533
534 fn init(&mut self, _sample_rate: f32) {}
535 fn reset(&mut self) {}
536 fn get_parameter(&self, _id: &ParameterId) -> Option<ParamValue> {
537 None
538 }
539 fn set_parameter(&mut self, _id: &ParameterId, _value: ParamValue) -> ProcessResult<()> {
540 Ok(())
541 }
542
543 fn id(&self) -> NodeId {
544 NodeId(0)
545 }
546 fn set_id(&mut self, _id: NodeId) {}
547
548 fn input_port(&self, _index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>> {
549 None
550 }
551 fn input_port_mut(
552 &mut self,
553 _index: usize,
554 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>> {
555 None
556 }
557 fn output_port(&self, _index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>> {
558 None
559 }
560 fn output_port_mut(
561 &mut self,
562 _index: usize,
563 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>> {
564 None
565 }
566 fn control_port(&self, _index: usize) -> Option<&crate::traits::port::Port<T, BUF_SIZE>> {
567 None
568 }
569 fn control_port_mut(
570 &mut self,
571 _index: usize,
572 ) -> Option<&mut crate::traits::port::Port<T, BUF_SIZE>> {
573 None
574 }
575
576 fn state(&self) -> &NodeState<T, BUF_SIZE> {
577 unimplemented!()
578 }
579
580 fn state_mut(&mut self) -> &mut NodeState<T, BUF_SIZE> {
581 unimplemented!()
582 }
583 }
584
585 #[test]
586 fn test_node_id() {
587 let id = NodeId::new(42);
588 assert_eq!(id.inner(), 42);
589 assert_eq!(format!("{}", id), "Node(42)");
590 }
591
592 #[test]
593 fn test_node_category() {
594 assert_eq!(NodeCategory::Source.name(), "source");
595 assert_eq!(NodeCategory::Processor.name(), "processor");
596 assert_eq!(NodeCategory::Sink.name(), "sink");
597 assert_eq!(NodeCategory::Utility.name(), "utility");
598 }
599
600 #[test]
601 fn test_node_metadata_new() {
602 let metadata = NodeMetadata::new("Test", NodeCategory::Source);
603 assert_eq!(metadata.name, "Test");
604 assert_eq!(metadata.category, NodeCategory::Source);
605 }
606
607 #[test]
608 fn test_node_state() {
609 let mut state = NodeState::<f32, 64>::new(44100.0);
610 assert_eq!(state.sample_pos, 0);
611 assert_eq!(state.sample_rate, 44100.0);
612
613 state.advance();
614 assert_eq!(state.sample_pos, 64);
615 assert_eq!(state.blocks_processed, 1);
616
617 state.reset();
618 assert_eq!(state.sample_pos, 0);
619 assert_eq!(state.blocks_processed, 0);
620 }
621}