1use std::sync::{
2 Arc,
3 atomic::{AtomicBool, Ordering},
4};
5
6use bbx_core::StackVec;
7use bbx_dsp::{
8 buffer::{AudioBuffer, Buffer},
9 graph::{Graph, MAX_BLOCK_OUTPUTS},
10 sample::Sample,
11};
12
13pub struct Signal<S: Sample> {
18 graph: Graph<S>,
19 output_buffers: Vec<AudioBuffer<S>>,
20 sample_rate: u32,
21 num_channels: usize,
22 buffer_size: usize,
23 channel_index: usize,
24 sample_index: usize,
25 stop_flag: Arc<AtomicBool>,
26}
27
28impl<S: Sample> Signal<S> {
29 pub fn new(graph: Graph<S>, stop_flag: Arc<AtomicBool>) -> Self {
31 let channels = graph.context().num_channels;
32 let buffer_size = graph.context().buffer_size;
33 let sample_rate = graph.context().sample_rate as u32;
34
35 let mut output_buffers = Vec::with_capacity(channels);
36 for _ in 0..channels {
37 output_buffers.push(AudioBuffer::new(buffer_size));
38 }
39
40 Self {
41 graph,
42 output_buffers,
43 channel_index: 0,
44 sample_index: 0,
45 num_channels: channels,
46 buffer_size,
47 sample_rate,
48 stop_flag,
49 }
50 }
51
52 pub fn sample_rate(&self) -> u32 {
54 self.sample_rate
55 }
56
57 pub fn num_channels(&self) -> usize {
59 self.num_channels
60 }
61
62 fn process(&mut self) -> S {
63 if self.channel_index == 0 && self.sample_index == 0 {
64 debug_assert!(
65 self.num_channels <= MAX_BLOCK_OUTPUTS,
66 "Channel count {} exceeds MAX_BLOCK_OUTPUTS {}",
67 self.num_channels,
68 MAX_BLOCK_OUTPUTS
69 );
70 let mut output_refs: StackVec<&mut [S], MAX_BLOCK_OUTPUTS> = StackVec::new();
71 for buf in self.output_buffers.iter_mut() {
72 let _ = output_refs.push(buf.as_mut_slice());
73 }
74 self.graph.process_buffers(output_refs.as_mut_slice());
75 }
76
77 debug_assert!(
81 self.channel_index < self.num_channels,
82 "channel_index {} exceeds num_channels {}",
83 self.channel_index,
84 self.num_channels
85 );
86 debug_assert!(
87 self.sample_index < self.buffer_size,
88 "sample_index {} exceeds buffer_size {}",
89 self.sample_index,
90 self.buffer_size
91 );
92 let sample = self.output_buffers[self.channel_index][self.sample_index];
93
94 self.channel_index += 1;
95 if self.channel_index >= self.num_channels {
96 self.channel_index = 0;
97 self.sample_index += 1;
98 self.sample_index %= self.buffer_size;
99 }
100
101 sample
102 }
103}
104
105impl<S: Sample> Iterator for Signal<S> {
106 type Item = S;
107
108 fn next(&mut self) -> Option<Self::Item> {
109 if self.stop_flag.load(Ordering::SeqCst) {
110 return None;
111 }
112 Some(self.process())
113 }
114}