1use rtsan_standalone::nonblocking;
2
3use crate::{AudioBlock, AudioBlockMut, BlockLayout, Sample};
4
5pub trait AudioBlockOps<S: Sample> {
6 fn copy_from_block(&mut self, block: &impl AudioBlock<S>);
8 fn copy_from_block_resize(&mut self, block: &impl AudioBlock<S>);
11 fn for_each(&mut self, f: impl FnMut(&mut S));
13 fn for_each_including_non_visible(&mut self, f: impl FnMut(&mut S));
18 fn enumerate(&mut self, f: impl FnMut(u16, usize, &mut S));
21 fn enumerate_including_non_visible(&mut self, f: impl FnMut(u16, usize, &mut S));
28 fn fill_with(&mut self, sample: S);
30 fn clear(&mut self);
32}
33
34impl<S: Sample, B: AudioBlockMut<S>> AudioBlockOps<S> for B {
35 #[nonblocking]
36 fn copy_from_block(&mut self, block: &impl AudioBlock<S>) {
37 assert_eq!(block.num_channels(), self.num_channels());
38 assert_eq!(block.num_frames(), self.num_frames());
39 for ch in 0..self.num_channels() {
40 for (sample_mut, sample) in self.channel_iter_mut(ch).zip(block.channel_iter(ch)) {
41 *sample_mut = *sample;
42 }
43 }
44 }
45
46 #[nonblocking]
47 fn copy_from_block_resize(&mut self, block: &impl AudioBlock<S>) {
48 assert!(block.num_channels() <= self.num_channels_allocated());
49 assert!(block.num_frames() <= self.num_frames_allocated());
50 self.set_active_size(block.num_channels(), block.num_frames());
51
52 for ch in 0..self.num_channels() {
53 for (sample_mut, sample) in self.channel_iter_mut(ch).zip(block.channel_iter(ch)) {
54 *sample_mut = *sample;
55 }
56 }
57 }
58
59 #[nonblocking]
60 fn for_each(&mut self, mut f: impl FnMut(&mut S)) {
61 if self.num_channels() < 8 {
63 for channel in self.channels_iter_mut() {
64 channel.for_each(&mut f);
65 }
66 } else {
67 match self.layout() {
68 BlockLayout::Sequential | BlockLayout::Planar => {
69 for channel in self.channels_iter_mut() {
70 channel.for_each(&mut f);
71 }
72 }
73 BlockLayout::Interleaved => {
74 for frame in 0..self.num_frames() {
75 self.frame_iter_mut(frame).for_each(&mut f);
76 }
77 }
78 }
79 }
80 }
81
82 #[nonblocking]
83 fn for_each_including_non_visible(&mut self, mut f: impl FnMut(&mut S)) {
84 match self.layout() {
85 BlockLayout::Interleaved => self
86 .as_interleaved_view_mut()
87 .expect("Layout is interleaved")
88 .raw_data_mut()
89 .iter_mut()
90 .for_each(&mut f),
91 BlockLayout::Planar => self
92 .as_planar_view_mut()
93 .expect("Layout is planar")
94 .raw_data_mut()
95 .iter_mut()
96 .for_each(|c| c.as_mut().iter_mut().for_each(&mut f)),
97 BlockLayout::Sequential => self
98 .as_sequential_view_mut()
99 .expect("Layout is sequential")
100 .raw_data_mut()
101 .iter_mut()
102 .for_each(&mut f),
103 }
104 }
105
106 #[nonblocking]
107 fn enumerate(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
108 if self.num_channels() < 8 {
110 for (ch, channel) in self.channels_iter_mut().enumerate() {
111 for (fr, sample) in channel.enumerate() {
112 f(ch as u16, fr, sample)
113 }
114 }
115 } else {
116 match self.layout() {
117 BlockLayout::Interleaved => {
118 for (fr, frame) in self.frames_iter_mut().enumerate() {
119 for (ch, sample) in frame.enumerate() {
120 f(ch as u16, fr, sample)
121 }
122 }
123 }
124 BlockLayout::Planar | BlockLayout::Sequential => {
125 for (ch, channel) in self.channels_iter_mut().enumerate() {
126 for (fr, sample) in channel.enumerate() {
127 f(ch as u16, fr, sample)
128 }
129 }
130 }
131 }
132 }
133 }
134
135 #[nonblocking]
136 fn enumerate_including_non_visible(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
137 match self.layout() {
138 BlockLayout::Interleaved => {
139 let num_frames = self.num_frames_allocated();
140 self.as_interleaved_view_mut()
141 .expect("Layout is interleaved")
142 .raw_data_mut()
143 .iter_mut()
144 .enumerate()
145 .for_each(|(i, sample)| {
146 let channel = i % num_frames;
147 let frame = i / num_frames;
148 f(channel as u16, frame, sample)
149 });
150 }
151 BlockLayout::Planar => self
152 .as_planar_view_mut()
153 .expect("Layout is planar")
154 .raw_data_mut()
155 .iter_mut()
156 .enumerate()
157 .for_each(|(ch, v)| {
158 v.as_mut()
159 .iter_mut()
160 .enumerate()
161 .for_each(|(frame, sample)| f(ch as u16, frame, sample))
162 }),
163 BlockLayout::Sequential => {
164 let num_frames = self.num_frames_allocated();
165 self.as_sequential_view_mut()
166 .expect("Layout is sequential")
167 .raw_data_mut()
168 .iter_mut()
169 .enumerate()
170 .for_each(|(i, sample)| {
171 let channel = i / num_frames;
172 let frame = i % num_frames;
173 f(channel as u16, frame, sample)
174 });
175 }
176 }
177 }
178
179 #[nonblocking]
180 fn fill_with(&mut self, sample: S) {
181 self.for_each_including_non_visible(|v| *v = sample);
182 }
183
184 #[nonblocking]
185 fn clear(&mut self) {
186 self.fill_with(S::zero());
187 }
188}
189
190#[cfg(test)]
191mod tests {
192 use rtsan_standalone::no_sanitize_realtime;
193
194 use crate::{
195 interleaved::AudioBlockInterleavedViewMut,
196 planar::AudioBlockPlanarViewMut,
197 sequential::{AudioBlockSequentialView, AudioBlockSequentialViewMut},
198 };
199
200 use super::*;
201
202 #[test]
203 fn test_copy_from() {
204 let mut data = [0.0; 15];
205 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 3, 5);
206 let view =
207 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
208 block.copy_from_block_resize(&view);
209
210 assert_eq!(block.num_channels(), 2);
211 assert_eq!(block.num_frames(), 4);
212 assert_eq!(block.num_channels_allocated(), 3);
213 assert_eq!(block.num_frames_allocated(), 5);
214
215 assert_eq!(
216 block.channel_iter(0).copied().collect::<Vec<_>>(),
217 vec![0.0, 1.0, 2.0, 3.0]
218 );
219 assert_eq!(
220 block.channel_iter(1).copied().collect::<Vec<_>>(),
221 vec![4.0, 5.0, 6.0, 7.0]
222 );
223 }
224
225 #[test]
226 fn test_copy_from_exact() {
227 let mut data = [0.0; 8];
228 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2, 4);
229 let view =
230 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
231 block.copy_from_block(&view);
232
233 assert_eq!(block.num_channels(), 2);
234 assert_eq!(block.num_frames(), 4);
235 assert_eq!(block.num_channels_allocated(), 2);
236 assert_eq!(block.num_frames_allocated(), 4);
237
238 assert_eq!(
239 block.channel_iter(0).copied().collect::<Vec<_>>(),
240 vec![0.0, 1.0, 2.0, 3.0]
241 );
242 assert_eq!(
243 block.channel_iter(1).copied().collect::<Vec<_>>(),
244 vec![4.0, 5.0, 6.0, 7.0]
245 );
246 }
247
248 #[test]
249 #[should_panic]
250 #[no_sanitize_realtime]
251 fn test_copy_data_wrong_channels() {
252 let mut data = [0.0; 5];
253 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 1, 5);
254 let view =
255 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
256 block.copy_from_block_resize(&view);
257 }
258
259 #[test]
260 #[should_panic]
261 #[no_sanitize_realtime]
262 fn test_copy_data_wrong_frames() {
263 let mut data = [0.0; 9];
264 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 3, 3);
265 let view =
266 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
267 block.copy_from_block(&view);
268 }
269
270 #[test]
271 #[should_panic]
272 #[no_sanitize_realtime]
273 fn test_copy_data_exact_wrong_channels() {
274 let mut data = [0.0; 12];
275 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 3, 4);
276 let view =
277 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
278 block.copy_from_block(&view);
279 }
280
281 #[test]
282 #[should_panic]
283 #[no_sanitize_realtime]
284 fn test_copy_data_exact_wrong_frames() {
285 let mut data = [0.0; 10];
286 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2, 5);
287 let view =
288 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2, 4);
289 block.copy_from_block(&view);
290 }
291
292 #[test]
293 fn test_for_each() {
294 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
295 let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 2, 4);
296
297 let mut i = 0;
298 let mut c_exp = 0;
299 let mut f_exp = 0;
300 block.enumerate_including_non_visible(|c, f, v| {
301 assert_eq!(c, c_exp);
302 assert_eq!(f, f_exp);
303 assert_eq!(*v, i as f32);
304 if f_exp == 3 {
305 c_exp = (c_exp + 1) % 4;
306 }
307 f_exp = (f_exp + 1) % 4;
308 i += 1;
309 });
310
311 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
312 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2, 4);
313
314 let mut i = 0;
315 let mut f_exp = 0;
316 let mut c_exp = 0;
317 block.enumerate_including_non_visible(|c, f, v| {
318 assert_eq!(c, c_exp);
319 assert_eq!(f, f_exp);
320 assert_eq!(*v, i as f32);
321 if c_exp == 3 {
322 f_exp = (f_exp + 1) % 4;
323 }
324 c_exp = (c_exp + 1) % 4;
325 i += 1;
326 });
327
328 let mut data = [[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]];
329 let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
330
331 let mut i = 0;
332 let mut c_exp = 0;
333 let mut f_exp = 0;
334 block.enumerate_including_non_visible(|c, f, v| {
335 assert_eq!(c, c_exp);
336 assert_eq!(f, f_exp);
337 assert_eq!(*v, i as f32);
338 if f_exp == 3 {
339 c_exp = (c_exp + 1) % 4;
340 }
341 f_exp = (f_exp + 1) % 4;
342 i += 1;
343 });
344 }
345
346 #[test]
347 fn test_clear() {
348 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
349 let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 2, 4);
350
351 block.fill_with(1.0);
352
353 assert_eq!(
354 block.channel_iter(0).copied().collect::<Vec<_>>(),
355 vec![1.0, 1.0, 1.0, 1.0]
356 );
357 assert_eq!(
358 block.channel_iter(1).copied().collect::<Vec<_>>(),
359 vec![1.0, 1.0, 1.0, 1.0]
360 );
361
362 block.clear();
363
364 assert_eq!(
365 block.channel_iter(0).copied().collect::<Vec<_>>(),
366 vec![0.0, 0.0, 0.0, 0.0]
367 );
368 assert_eq!(
369 block.channel_iter(1).copied().collect::<Vec<_>>(),
370 vec![0.0, 0.0, 0.0, 0.0]
371 );
372 }
373}