1use rtsan_standalone::nonblocking;
2
3use crate::{
4 AudioBlock, AudioBlockMut, BlockLayout, Sample,
5 mono::{AudioBlockMonoView, AudioBlockMonoViewMut},
6};
7
8pub trait AudioBlockOps<S: Sample> {
9 fn mix_to_mono(&self, dest: &mut AudioBlockMonoViewMut<S>)
12 where
13 S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>;
14}
15
16pub trait AudioBlockOpsMut<S: Sample> {
17 fn copy_from_block(&mut self, block: &impl AudioBlock<S>);
21 fn copy_from_block_exact(&mut self, block: &impl AudioBlock<S>);
24 fn copy_mono_to_all_channels(&mut self, mono: &AudioBlockMonoView<S>);
27 fn for_each(&mut self, f: impl FnMut(&mut S));
29 fn for_each_including_non_visible(&mut self, f: impl FnMut(&mut S));
34 fn enumerate(&mut self, f: impl FnMut(u16, usize, &mut S));
37 fn enumerate_including_non_visible(&mut self, f: impl FnMut(u16, usize, &mut S));
44 fn fill_with(&mut self, sample: S);
46 fn clear(&mut self)
48 where
49 S: Default;
50}
51
52impl<S: Sample, B: AudioBlock<S>> AudioBlockOps<S> for B {
53 #[nonblocking]
54 fn mix_to_mono(&self, dest: &mut AudioBlockMonoViewMut<S>)
55 where
56 S: std::ops::AddAssign + std::ops::Div<Output = S> + From<u16>,
57 {
58 assert_eq!(self.num_frames(), dest.num_frames());
59
60 let num_channels = S::from(self.num_channels());
61
62 for frame in 0..self.num_frames() {
63 let mut sum = *self.frame_iter(frame).next().unwrap();
64 for sample in self.frame_iter(frame).skip(1) {
65 sum += *sample;
66 }
67 *dest.sample_mut(frame) = sum / num_channels;
68 }
69 }
70}
71
72impl<S: Sample, B: AudioBlockMut<S>> AudioBlockOpsMut<S> for B {
73 #[nonblocking]
74 fn copy_from_block(&mut self, block: &impl AudioBlock<S>) {
75 let channels = self.num_channels().min(block.num_channels());
76 let frames = self.num_frames().min(block.num_frames());
77
78 self.set_visible(channels, frames);
79 for (this_channel, other_channel) in self.channels_iter_mut().zip(block.channels_iter()) {
80 for (sample_mut, sample) in this_channel.zip(other_channel) {
81 *sample_mut = *sample;
82 }
83 }
84 }
85
86 #[nonblocking]
87 fn copy_from_block_exact(&mut self, block: &impl AudioBlock<S>) {
88 assert_eq!(block.num_channels(), self.num_channels());
89 assert_eq!(block.num_frames(), self.num_frames());
90 for ch in 0..self.num_channels() {
91 for (sample_mut, sample) in self.channel_iter_mut(ch).zip(block.channel_iter(ch)) {
92 *sample_mut = *sample;
93 }
94 }
95 }
96
97 #[nonblocking]
98 fn copy_mono_to_all_channels(&mut self, mono: &AudioBlockMonoView<S>) {
99 assert_eq!(mono.num_frames(), self.num_frames());
100 for channel in self.channels_iter_mut() {
101 for (sample_mut, sample) in channel.zip(mono.samples()) {
102 *sample_mut = *sample;
103 }
104 }
105 }
106
107 #[nonblocking]
108 fn for_each(&mut self, mut f: impl FnMut(&mut S)) {
109 if self.num_channels() < 8 {
111 for channel in self.channels_iter_mut() {
112 channel.for_each(&mut f);
113 }
114 } else {
115 match self.layout() {
116 BlockLayout::Sequential | BlockLayout::Planar => {
117 for channel in self.channels_iter_mut() {
118 channel.for_each(&mut f);
119 }
120 }
121 BlockLayout::Interleaved => {
122 for frame in 0..self.num_frames() {
123 self.frame_iter_mut(frame).for_each(&mut f);
124 }
125 }
126 }
127 }
128 }
129
130 #[nonblocking]
131 fn for_each_including_non_visible(&mut self, mut f: impl FnMut(&mut S)) {
132 match self.layout() {
133 BlockLayout::Interleaved => self
134 .as_interleaved_view_mut()
135 .expect("Layout is interleaved")
136 .raw_data_mut()
137 .iter_mut()
138 .for_each(&mut f),
139 BlockLayout::Planar => self
140 .as_planar_view_mut()
141 .expect("Layout is planar")
142 .raw_data_mut()
143 .iter_mut()
144 .for_each(|c| c.as_mut().iter_mut().for_each(&mut f)),
145 BlockLayout::Sequential => self
146 .as_sequential_view_mut()
147 .expect("Layout is sequential")
148 .raw_data_mut()
149 .iter_mut()
150 .for_each(&mut f),
151 }
152 }
153
154 #[nonblocking]
155 fn enumerate(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
156 if self.num_channels() < 8 {
158 for (ch, channel) in self.channels_iter_mut().enumerate() {
159 for (fr, sample) in channel.enumerate() {
160 f(ch as u16, fr, sample)
161 }
162 }
163 } else {
164 match self.layout() {
165 BlockLayout::Interleaved => {
166 for (fr, frame) in self.frames_iter_mut().enumerate() {
167 for (ch, sample) in frame.enumerate() {
168 f(ch as u16, fr, sample)
169 }
170 }
171 }
172 BlockLayout::Planar | BlockLayout::Sequential => {
173 for (ch, channel) in self.channels_iter_mut().enumerate() {
174 for (fr, sample) in channel.enumerate() {
175 f(ch as u16, fr, sample)
176 }
177 }
178 }
179 }
180 }
181 }
182
183 #[nonblocking]
184 fn enumerate_including_non_visible(&mut self, mut f: impl FnMut(u16, usize, &mut S)) {
185 match self.layout() {
186 BlockLayout::Interleaved => {
187 let num_frames = self.num_frames_allocated();
188 self.as_interleaved_view_mut()
189 .expect("Layout is interleaved")
190 .raw_data_mut()
191 .iter_mut()
192 .enumerate()
193 .for_each(|(i, sample)| {
194 let channel = i % num_frames;
195 let frame = i / num_frames;
196 f(channel as u16, frame, sample)
197 });
198 }
199 BlockLayout::Planar => self
200 .as_planar_view_mut()
201 .expect("Layout is planar")
202 .raw_data_mut()
203 .iter_mut()
204 .enumerate()
205 .for_each(|(ch, v)| {
206 v.as_mut()
207 .iter_mut()
208 .enumerate()
209 .for_each(|(frame, sample)| f(ch as u16, frame, sample))
210 }),
211 BlockLayout::Sequential => {
212 let num_frames = self.num_frames_allocated();
213 self.as_sequential_view_mut()
214 .expect("Layout is sequential")
215 .raw_data_mut()
216 .iter_mut()
217 .enumerate()
218 .for_each(|(i, sample)| {
219 let channel = i / num_frames;
220 let frame = i % num_frames;
221 f(channel as u16, frame, sample)
222 });
223 }
224 }
225 }
226
227 #[nonblocking]
228 fn fill_with(&mut self, sample: S) {
229 self.for_each_including_non_visible(|v| *v = sample);
230 }
231
232 #[nonblocking]
233 fn clear(&mut self)
234 where
235 S: Default,
236 {
237 self.fill_with(S::default());
238 }
239}
240
241#[cfg(test)]
242mod tests {
243 use rtsan_standalone::no_sanitize_realtime;
244
245 use crate::{
246 interleaved::AudioBlockInterleavedViewMut,
247 planar::AudioBlockPlanarViewMut,
248 sequential::{AudioBlockSequentialView, AudioBlockSequentialViewMut},
249 };
250
251 use super::*;
252
253 #[test]
254 fn test_copy_from_block_resizes_to_smaller() {
255 let mut data = [0.0; 15];
257 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 3);
258 let view =
259 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
260 block.copy_from_block(&view);
261
262 assert_eq!(block.num_channels(), 2);
263 assert_eq!(block.num_frames(), 4);
264 assert_eq!(block.num_channels_allocated(), 3);
265 assert_eq!(block.num_frames_allocated(), 5);
266
267 assert_eq!(
268 block.channel_iter(0).copied().collect::<Vec<_>>(),
269 vec![0.0, 1.0, 2.0, 3.0]
270 );
271 assert_eq!(
272 block.channel_iter(1).copied().collect::<Vec<_>>(),
273 vec![4.0, 5.0, 6.0, 7.0]
274 );
275 }
276
277 #[test]
278 fn test_copy_from_block_clamps_to_dest_size() {
279 let mut data = [0.0; 4]; let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 2);
282 let view =
283 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
284 block.copy_from_block(&view);
285
286 assert_eq!(block.num_channels(), 2);
287 assert_eq!(block.num_frames(), 2);
288 assert_eq!(
290 block.channel_iter(0).copied().collect::<Vec<_>>(),
291 vec![0.0, 1.0]
292 );
293 assert_eq!(
294 block.channel_iter(1).copied().collect::<Vec<_>>(),
295 vec![4.0, 5.0]
296 );
297 }
298
299 #[test]
300 fn test_copy_from_block_clamps_channels() {
301 let mut data = [0.0; 4]; let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 1);
304 let view =
305 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
306 block.copy_from_block(&view);
307
308 assert_eq!(block.num_channels(), 1);
309 assert_eq!(block.num_frames(), 4);
310 assert_eq!(
311 block.channel_iter(0).copied().collect::<Vec<_>>(),
312 vec![0.0, 1.0, 2.0, 3.0]
313 );
314 }
315
316 #[test]
317 fn test_copy_from_block_exact() {
318 let mut data = [0.0; 8];
319 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2);
320 let view =
321 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
322 block.copy_from_block_exact(&view);
323
324 assert_eq!(block.num_channels(), 2);
325 assert_eq!(block.num_frames(), 4);
326
327 assert_eq!(
328 block.channel_iter(0).copied().collect::<Vec<_>>(),
329 vec![0.0, 1.0, 2.0, 3.0]
330 );
331 assert_eq!(
332 block.channel_iter(1).copied().collect::<Vec<_>>(),
333 vec![4.0, 5.0, 6.0, 7.0]
334 );
335 }
336
337 #[test]
338 #[should_panic]
339 #[no_sanitize_realtime]
340 fn test_copy_from_block_exact_wrong_channels() {
341 let mut data = [0.0; 12];
342 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 3);
343 let view =
344 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
345 block.copy_from_block_exact(&view);
346 }
347
348 #[test]
349 #[should_panic]
350 #[no_sanitize_realtime]
351 fn test_copy_from_block_exact_wrong_frames() {
352 let mut data = [0.0; 10];
353 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2);
354 let view =
355 AudioBlockSequentialView::from_slice(&[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0], 2);
356 block.copy_from_block_exact(&view);
357 }
358
359 #[test]
360 fn test_for_each() {
361 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
362 let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 2);
363
364 let mut i = 0;
365 let mut c_exp = 0;
366 let mut f_exp = 0;
367 block.enumerate_including_non_visible(|c, f, v| {
368 assert_eq!(c, c_exp);
369 assert_eq!(f, f_exp);
370 assert_eq!(*v, i as f32);
371 if f_exp == 3 {
372 c_exp = (c_exp + 1) % 4;
373 }
374 f_exp = (f_exp + 1) % 4;
375 i += 1;
376 });
377
378 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
379 let mut block = AudioBlockInterleavedViewMut::from_slice(&mut data, 2);
380
381 let mut i = 0;
382 let mut f_exp = 0;
383 let mut c_exp = 0;
384 block.enumerate_including_non_visible(|c, f, v| {
385 assert_eq!(c, c_exp);
386 assert_eq!(f, f_exp);
387 assert_eq!(*v, i as f32);
388 if c_exp == 3 {
389 f_exp = (f_exp + 1) % 4;
390 }
391 c_exp = (c_exp + 1) % 4;
392 i += 1;
393 });
394
395 let mut data = [[0.0, 1.0, 2.0, 3.0], [4.0, 5.0, 6.0, 7.0]];
396 let mut block = AudioBlockPlanarViewMut::from_slice(&mut data);
397
398 let mut i = 0;
399 let mut c_exp = 0;
400 let mut f_exp = 0;
401 block.enumerate_including_non_visible(|c, f, v| {
402 assert_eq!(c, c_exp);
403 assert_eq!(f, f_exp);
404 assert_eq!(*v, i as f32);
405 if f_exp == 3 {
406 c_exp = (c_exp + 1) % 4;
407 }
408 f_exp = (f_exp + 1) % 4;
409 i += 1;
410 });
411 }
412
413 #[test]
414 fn test_clear() {
415 let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0];
416 let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 2);
417
418 block.fill_with(1.0);
419
420 assert_eq!(
421 block.channel_iter(0).copied().collect::<Vec<_>>(),
422 vec![1.0, 1.0, 1.0, 1.0]
423 );
424 assert_eq!(
425 block.channel_iter(1).copied().collect::<Vec<_>>(),
426 vec![1.0, 1.0, 1.0, 1.0]
427 );
428
429 block.clear();
430
431 assert_eq!(
432 block.channel_iter(0).copied().collect::<Vec<_>>(),
433 vec![0.0, 0.0, 0.0, 0.0]
434 );
435 assert_eq!(
436 block.channel_iter(1).copied().collect::<Vec<_>>(),
437 vec![0.0, 0.0, 0.0, 0.0]
438 );
439 }
440
441 #[test]
442 fn test_mix_to_mono() {
443 use crate::mono::AudioBlockMonoViewMut;
444
445 let data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0];
446 let block = AudioBlockSequentialView::from_slice(&data, 2);
447
448 let mut mono_data = [0.0; 4];
449 let mut mono = AudioBlockMonoViewMut::from_slice(&mut mono_data);
450
451 block.mix_to_mono(&mut mono);
452
453 assert_eq!(mono.num_frames(), 4);
454 assert_eq!(
455 mono.samples().iter().copied().collect::<Vec<_>>(),
456 vec![3.0, 4.0, 5.0, 6.0] );
458 }
459
460 #[test]
461 fn test_copy_mono_to_all_channels() {
462 use crate::mono::AudioBlockMonoView;
463
464 let mono_data = [1.0, 2.0, 3.0, 4.0];
465 let mono = AudioBlockMonoView::from_slice(&mono_data);
466
467 let mut data = [0.0; 12];
468 let mut block = AudioBlockSequentialViewMut::from_slice(&mut data, 3);
469
470 block.copy_mono_to_all_channels(&mono);
471
472 assert_eq!(
473 block.channel_iter(0).copied().collect::<Vec<_>>(),
474 vec![1.0, 2.0, 3.0, 4.0]
475 );
476 assert_eq!(
477 block.channel_iter(1).copied().collect::<Vec<_>>(),
478 vec![1.0, 2.0, 3.0, 4.0]
479 );
480 assert_eq!(
481 block.channel_iter(2).copied().collect::<Vec<_>>(),
482 vec![1.0, 2.0, 3.0, 4.0]
483 );
484 }
485}