use crate::audio::node_graph::{AudioNode, NodeCategory, NodePort, Parameter, SignalType}; use crate::audio::midi::MidiEvent; /// Splitter node - copies input to multiple outputs for parallel routing pub struct SplitterNode { name: String, inputs: Vec, outputs: Vec, parameters: Vec, } impl SplitterNode { pub fn new(name: impl Into) -> Self { let name = name.into(); let inputs = vec![ NodePort::new("Audio In", SignalType::Audio, 0), ]; let outputs = vec![ NodePort::new("Out 1", SignalType::Audio, 0), NodePort::new("Out 2", SignalType::Audio, 1), NodePort::new("Out 3", SignalType::Audio, 2), NodePort::new("Out 4", SignalType::Audio, 3), ]; let parameters = vec![]; Self { name, inputs, outputs, parameters, } } } impl AudioNode for SplitterNode { fn category(&self) -> NodeCategory { NodeCategory::Utility } fn inputs(&self) -> &[NodePort] { &self.inputs } fn outputs(&self) -> &[NodePort] { &self.outputs } fn parameters(&self) -> &[Parameter] { &self.parameters } fn set_parameter(&mut self, _id: u32, _value: f32) { // No parameters } fn get_parameter(&self, _id: u32) -> f32 { 0.0 } fn process( &mut self, inputs: &[&[f32]], outputs: &mut [&mut [f32]], _midi_inputs: &[&[MidiEvent]], _midi_outputs: &mut [&mut Vec], _sample_rate: u32, ) { if inputs.is_empty() || outputs.is_empty() { return; } let input = inputs[0]; // Copy input to all outputs for output in outputs.iter_mut() { let len = input.len().min(output.len()); output[..len].copy_from_slice(&input[..len]); } } fn reset(&mut self) { // No state to reset } fn node_type(&self) -> &str { "Splitter" } fn name(&self) -> &str { &self.name } fn clone_node(&self) -> Box { Box::new(Self { name: self.name.clone(), inputs: self.inputs.clone(), outputs: self.outputs.clone(), parameters: self.parameters.clone(), }) } }