bbx_dsp/blocks/effectors/
channel_splitter.rs1use std::marker::PhantomData;
4
5use crate::{
6 block::Block, channel::ChannelConfig, context::DspContext, graph::MAX_BLOCK_OUTPUTS, parameter::ModulationOutput,
7 sample::Sample,
8};
9
10pub struct ChannelSplitterBlock<S: Sample> {
19 channel_count: usize,
20 _phantom: PhantomData<S>,
21}
22
23impl<S: Sample> ChannelSplitterBlock<S> {
24 pub fn new(channels: usize) -> Self {
29 assert!(channels > 0 && channels <= MAX_BLOCK_OUTPUTS);
30 Self {
31 channel_count: channels,
32 _phantom: PhantomData,
33 }
34 }
35
36 pub fn channel_count(&self) -> usize {
38 self.channel_count
39 }
40}
41
42impl<S: Sample> Block<S> for ChannelSplitterBlock<S> {
43 fn process(&mut self, inputs: &[&[S]], outputs: &mut [&mut [S]], _modulation_values: &[S], _context: &DspContext) {
44 let num_channels = self.channel_count.min(inputs.len()).min(outputs.len());
45
46 for ch in 0..num_channels {
47 let input = inputs[ch];
48 let output = &mut outputs[ch];
49 let num_samples = input.len().min(output.len());
50
51 output[..num_samples].copy_from_slice(&input[..num_samples]);
52 }
53 }
54
55 #[inline]
56 fn input_count(&self) -> usize {
57 self.channel_count
58 }
59
60 #[inline]
61 fn output_count(&self) -> usize {
62 self.channel_count
63 }
64
65 #[inline]
66 fn modulation_outputs(&self) -> &[ModulationOutput] {
67 &[]
68 }
69
70 #[inline]
71 fn channel_config(&self) -> ChannelConfig {
72 ChannelConfig::Explicit
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79 use crate::channel::ChannelLayout;
80
81 fn test_context() -> DspContext {
82 DspContext {
83 sample_rate: 44100.0,
84 num_channels: 2,
85 buffer_size: 4,
86 current_sample: 0,
87 channel_layout: ChannelLayout::Stereo,
88 }
89 }
90
91 #[test]
92 fn test_channel_splitter_stereo() {
93 let mut splitter = ChannelSplitterBlock::<f32>::new(2);
94 let context = test_context();
95
96 let left_in = [1.0f32, 2.0, 3.0, 4.0];
97 let right_in = [5.0f32, 6.0, 7.0, 8.0];
98 let mut left_out = [0.0f32; 4];
99 let mut right_out = [0.0f32; 4];
100
101 let inputs: [&[f32]; 2] = [&left_in, &right_in];
102 let mut outputs: [&mut [f32]; 2] = [&mut left_out, &mut right_out];
103
104 splitter.process(&inputs, &mut outputs, &[], &context);
105
106 assert_eq!(left_out, left_in);
107 assert_eq!(right_out, right_in);
108 }
109
110 #[test]
111 fn test_channel_splitter_quad() {
112 let splitter = ChannelSplitterBlock::<f32>::new(4);
113 assert_eq!(splitter.input_count(), 4);
114 assert_eq!(splitter.output_count(), 4);
115 assert_eq!(splitter.channel_config(), ChannelConfig::Explicit);
116 }
117
118 #[test]
119 #[should_panic]
120 fn test_channel_splitter_zero_channels_panics() {
121 let _ = ChannelSplitterBlock::<f32>::new(0);
122 }
123
124 #[test]
125 #[should_panic]
126 fn test_channel_splitter_too_many_channels_panics() {
127 let _ = ChannelSplitterBlock::<f32>::new(17);
128 }
129}