1use bbx_core::spsc::{Consumer, Producer, SpscRingBuffer};
7use bbx_dsp::Frame;
8use bbx_midi::message::MidiMessage;
9
10pub struct AudioBridgeProducer {
12 producer: Producer<Frame>,
13}
14
15impl AudioBridgeProducer {
16 pub fn try_send(&mut self, frame: Frame) -> bool {
21 self.producer.try_push(frame).is_ok()
22 }
23
24 pub fn is_full(&self) -> bool {
26 self.producer.is_full()
27 }
28}
29
30pub struct AudioBridgeConsumer {
34 consumer: Consumer<Frame>,
35}
36
37impl AudioBridgeConsumer {
38 #[inline]
42 pub fn try_pop(&mut self) -> Option<Frame> {
43 self.consumer.try_pop()
44 }
45
46 #[inline]
48 pub fn is_empty(&self) -> bool {
49 self.consumer.is_empty()
50 }
51
52 #[inline]
54 pub fn len(&self) -> usize {
55 self.consumer.len()
56 }
57}
58
59pub fn audio_bridge(capacity: usize) -> (AudioBridgeProducer, AudioBridgeConsumer) {
64 let (producer, consumer) = SpscRingBuffer::new(capacity);
65 (AudioBridgeProducer { producer }, AudioBridgeConsumer { consumer })
66}
67
68pub struct MidiBridgeProducer {
70 producer: Producer<MidiMessage>,
71}
72
73impl MidiBridgeProducer {
74 pub fn try_send(&mut self, message: MidiMessage) -> bool {
78 self.producer.try_push(message).is_ok()
79 }
80
81 pub fn is_full(&self) -> bool {
83 self.producer.is_full()
84 }
85}
86
87pub struct MidiBridgeConsumer {
89 consumer: Consumer<MidiMessage>,
90}
91
92impl MidiBridgeConsumer {
93 pub fn drain(&mut self) -> Vec<MidiMessage> {
95 let mut messages = Vec::new();
96 while let Some(msg) = self.consumer.try_pop() {
97 messages.push(msg);
98 }
99 messages
100 }
101
102 pub fn is_empty(&self) -> bool {
104 self.consumer.is_empty()
105 }
106}
107
108pub fn midi_bridge(capacity: usize) -> (MidiBridgeProducer, MidiBridgeConsumer) {
113 let (producer, consumer) = SpscRingBuffer::new(capacity);
114 (MidiBridgeProducer { producer }, MidiBridgeConsumer { consumer })
115}
116
117#[cfg(test)]
118mod tests {
119 use super::*;
120
121 #[test]
122 fn test_audio_bridge_send_receive() {
123 let (mut producer, mut consumer) = audio_bridge(4);
124
125 let samples = [0.5f32, -0.5, 0.25, -0.25];
126 let frame = Frame::new(&samples, 44100, 2);
127 assert!(producer.try_send(frame));
128
129 let frame = consumer.try_pop().expect("should have frame");
130 assert_eq!(frame.samples.len(), 4);
131 assert_eq!(frame.sample_rate, 44100);
132 assert!(consumer.try_pop().is_none());
133 }
134
135 #[test]
136 fn test_audio_bridge_overflow() {
137 let (mut producer, _consumer) = audio_bridge(2);
138
139 let samples = [0.0f32];
140 let frame = Frame::new(&samples, 44100, 1);
141 assert!(producer.try_send(frame.clone()));
142 assert!(producer.try_send(frame.clone()));
143 assert!(!producer.try_send(frame));
144 }
145
146 #[test]
147 fn test_try_pop_empty() {
148 let (_producer, mut consumer) = audio_bridge(4);
149 assert!(consumer.try_pop().is_none());
150 assert!(consumer.is_empty());
151 assert_eq!(consumer.len(), 0);
152 }
153
154 #[test]
155 fn test_try_pop_multiple() {
156 let (mut producer, mut consumer) = audio_bridge(4);
157
158 let samples1 = [1.0f32, 2.0];
159 let samples2 = [3.0f32, 4.0];
160 producer.try_send(Frame::new(&samples1, 44100, 1));
161 producer.try_send(Frame::new(&samples2, 44100, 1));
162
163 assert_eq!(consumer.len(), 2);
164
165 let f1 = consumer.try_pop().unwrap();
166 let f2 = consumer.try_pop().unwrap();
167 assert!(consumer.try_pop().is_none());
168
169 assert_eq!(f1.samples.as_slice(), &[1.0, 2.0]);
170 assert_eq!(f2.samples.as_slice(), &[3.0, 4.0]);
171 }
172
173 #[test]
174 fn test_midi_bridge_send_receive() {
175 let (mut producer, mut consumer) = midi_bridge(8);
176
177 let msg = MidiMessage::new([0x90, 60, 100]);
178 assert!(producer.try_send(msg));
179
180 let messages = consumer.drain();
181 assert_eq!(messages.len(), 1);
182 }
183}