audio_blocks/
ops.rs

1use rtsan_standalone::nonblocking;
2
3use crate::{AudioBlock, AudioBlockMut, BlockLayout, Sample};
4
5pub trait AudioBlockOps<S: Sample> {
6    /// Copy will panic if blocks don't have the exact same size
7    fn copy_from_block(&mut self, block: &impl AudioBlock<S>);
8    /// Destination block will take over the size from source block.
9    /// Panics if destination block has not enough memory allocated to grow.
10    fn copy_from_block_resize(&mut self, block: &impl AudioBlock<S>);
11    /// Gives access to all samples in the block.
12    fn for_each(&mut self, f: impl FnMut(&mut S));
13    /// Gives access to all samples in the block.
14    /// This is faster than `for_each` by not checking bounds of the block.
15    /// It can be used if your algorithm does not change if wrong samples are accessed.
16    /// For example this is the case for gain, clear, etc.
17    fn for_each_including_non_visible(&mut self, f: impl FnMut(&mut S));
18    /// Gives access to all samples in the block while supplying the information
19    /// about which channel and frame number the sample is stored in.
20    fn enumerate(&mut self, f: impl FnMut(u16, usize, &mut S));
21    /// Gives access to all samples in the block while supplying the information
22    /// about which channel and frame number the sample is stored in.
23    ///
24    /// This is faster than `enumerate` by not checking bounds of the block.
25    /// It can be used if your algorithm does not change if wrong samples are accessed.
26    /// For example this is the case for applying a gain, clear, etc.
27    fn enumerate_including_non_visible(&mut self, f: impl FnMut(u16, usize, &mut S));
28    /// Sets all samples in the block to the specified value
29    fn fill_with(&mut self, sample: S);
30    /// Sets all samples in the block to zero
31    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        // below 8 channels it is faster to always go per channel
62        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        // below 8 channels it is faster to always go per channel
109        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}