audio_blocks/planar/
owned.rs

1use rtsan_standalone::{blocking, nonblocking};
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::{boxed::Box, vec, vec::Vec};
5#[cfg(all(feature = "std", not(feature = "alloc")))]
6use std::{boxed::Box, vec, vec::Vec};
7#[cfg(all(feature = "std", feature = "alloc"))]
8use std::{boxed::Box, vec, vec::Vec};
9
10use crate::{AudioBlock, AudioBlockMut, Sample};
11
12use super::{view::AudioBlockPlanarView, view_mut::AudioBlockPlanarViewMut};
13
14/// A planar / seperate-channel audio block that owns its data.
15///
16/// * **Layout:** `[[ch0, ch0, ch0], [ch1, ch1, ch1]]`
17/// * **Interpretation:** Each channel has its own separate buffer or array.
18/// * **Terminology:** Also described as “planar” or “channels first” though more specifically it’s channel-isolated buffers.
19/// * **Usage:** Very common in real-time DSP, as it simplifies memory access and can improve SIMD/vectorization efficiency.
20///
21/// # Example
22///
23/// ```
24/// use audio_blocks::*;
25///
26/// let block = AudioBlockPlanar::new(2, 3);
27/// let mut block = AudioBlockPlanar::from_block(&block);
28///
29/// block.channel_mut(0).fill(0.0);
30/// block.channel_mut(1).fill(1.0);
31///
32/// assert_eq!(block.channel(0), &[0.0, 0.0, 0.0]);
33/// assert_eq!(block.channel(1), &[1.0, 1.0, 1.0]);
34/// ```
35pub struct AudioBlockPlanar<S: Sample> {
36    data: Box<[Box<[S]>]>,
37    num_channels: u16,
38    num_frames: usize,
39    num_channels_allocated: u16,
40    num_frames_allocated: usize,
41}
42
43impl<S: Sample> AudioBlockPlanar<S> {
44    /// Creates a new audio block with the specified dimensions.
45    ///
46    /// Allocates memory for a new planar audio block with exactly the specified
47    /// number of channels and frames. The block is initialized with the default value
48    /// for the sample type.
49    ///
50    /// Do not use in real-time processes!
51    ///
52    /// # Arguments
53    ///
54    /// * `num_channels` - The number of audio channels
55    /// * `num_frames` - The number of frames per channel
56    ///
57    /// # Panics
58    ///
59    /// Panics if the multiplication of `num_channels` and `num_frames` would overflow a usize.
60    #[blocking]
61    pub fn new(num_channels: u16, num_frames: usize) -> Self {
62        Self {
63            data: vec![vec![S::zero(); num_frames].into_boxed_slice(); num_channels as usize]
64                .into_boxed_slice(),
65            num_channels,
66            num_frames,
67            num_channels_allocated: num_channels,
68            num_frames_allocated: num_frames,
69        }
70    }
71
72    /// Creates a new audio block by copying data from another [`AudioBlock`].
73    ///
74    /// Converts any [`AudioBlock`] implementation to a planar format by iterating
75    /// through each channel of the source block and copying its samples. The new block
76    /// will have the same dimensions as the source block.
77    ///
78    /// # Warning
79    ///
80    /// This function allocates memory and should not be used in real-time audio processing contexts.
81    ///
82    /// # Arguments
83    ///
84    /// * `block` - The source audio block to copy data from
85    #[blocking]
86    pub fn from_block(block: &impl AudioBlock<S>) -> Self {
87        let data: Vec<Box<[S]>> = block
88            .channels_iter()
89            .map(|c| c.copied().collect())
90            .collect();
91        Self {
92            data: data.into_boxed_slice(),
93            num_channels: block.num_channels(),
94            num_frames: block.num_frames(),
95            num_channels_allocated: block.num_channels(),
96            num_frames_allocated: block.num_frames(),
97        }
98    }
99
100    /// Returns a slice for a single channel.
101    ///
102    /// # Panics
103    ///
104    /// Panics if channel index is out of bounds.
105    #[nonblocking]
106    pub fn channel(&self, channel: u16) -> &[S] {
107        assert!(channel < self.num_channels);
108        &self.data[channel as usize].as_ref()[..self.num_frames]
109    }
110
111    /// Returns a mutable slice for a single channel.
112    ///
113    /// # Panics
114    ///
115    /// Panics if channel index is out of bounds.
116    #[nonblocking]
117    pub fn channel_mut(&mut self, channel: u16) -> &mut [S] {
118        assert!(channel < self.num_channels);
119        &mut self.data[channel as usize].as_mut()[..self.num_frames]
120    }
121
122    /// Returns an iterator over all channels in the block.
123    ///
124    /// Each channel is represented as a slice of samples.
125    #[nonblocking]
126    pub fn channels(&self) -> impl Iterator<Item = &[S]> {
127        self.data
128            .iter()
129            .take(self.num_channels as usize)
130            .map(|channel_data| &channel_data.as_ref()[..self.num_frames])
131    }
132
133    /// Returns a mutable iterator over all channels in the block.
134    ///
135    /// Each channel is represented as a mutable slice of samples.
136    #[nonblocking]
137    pub fn channels_mut(&mut self) -> impl Iterator<Item = &mut [S]> {
138        self.data
139            .iter_mut()
140            .take(self.num_channels as usize)
141            .map(|channel_data| &mut channel_data.as_mut()[..self.num_frames])
142    }
143
144    /// Provides direct access to the underlying memory.
145    ///
146    /// This function gives access to all allocated data, including any reserved capacity
147    /// beyond the active range.
148    #[nonblocking]
149    pub fn raw_data(&self) -> &[Box<[S]>] {
150        &self.data
151    }
152
153    /// Provides direct access to the underlying memory.
154    ///
155    /// This function gives access to all allocated data, including any reserved capacity
156    /// beyond the active range.
157    #[nonblocking]
158    pub fn raw_data_mut(&mut self) -> &mut [Box<[S]>] {
159        &mut self.data
160    }
161
162    #[nonblocking]
163    pub fn view(&self) -> AudioBlockPlanarView<'_, S, Box<[S]>> {
164        AudioBlockPlanarView::from_slice_limited(&self.data, self.num_channels, self.num_frames)
165    }
166
167    #[nonblocking]
168    pub fn view_mut(&mut self) -> AudioBlockPlanarViewMut<'_, S, Box<[S]>> {
169        AudioBlockPlanarViewMut::from_slice_limited(
170            &mut self.data,
171            self.num_channels,
172            self.num_frames,
173        )
174    }
175}
176
177impl<S: Sample> AudioBlock<S> for AudioBlockPlanar<S> {
178    type PlanarView = Box<[S]>;
179
180    #[nonblocking]
181    fn num_channels(&self) -> u16 {
182        self.num_channels
183    }
184
185    #[nonblocking]
186    fn num_frames(&self) -> usize {
187        self.num_frames
188    }
189
190    #[nonblocking]
191    fn num_channels_allocated(&self) -> u16 {
192        self.num_channels_allocated
193    }
194
195    #[nonblocking]
196    fn num_frames_allocated(&self) -> usize {
197        self.num_frames_allocated
198    }
199
200    #[nonblocking]
201    fn layout(&self) -> crate::BlockLayout {
202        crate::BlockLayout::Planar
203    }
204
205    #[nonblocking]
206    fn sample(&self, channel: u16, frame: usize) -> S {
207        assert!(channel < self.num_channels);
208        assert!(frame < self.num_frames);
209        unsafe {
210            *self
211                .data
212                .get_unchecked(channel as usize)
213                .get_unchecked(frame)
214        }
215    }
216
217    #[nonblocking]
218    fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
219        assert!(channel < self.num_channels);
220        unsafe {
221            self.data
222                .get_unchecked(channel as usize)
223                .iter()
224                .take(self.num_frames)
225        }
226    }
227
228    #[nonblocking]
229    fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
230        let num_frames = self.num_frames; // Capture num_frames for the closure
231        self.data
232            .iter()
233            // Limit to the active number of channels
234            .take(self.num_channels as usize)
235            // For each channel slice, create an iterator over its samples
236            .map(move |channel_data| channel_data.as_ref().iter().take(num_frames))
237    }
238
239    #[nonblocking]
240    fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
241        assert!(frame < self.num_frames);
242        self.data
243            .iter()
244            .take(self.num_channels as usize)
245            .map(move |channel_data| unsafe { channel_data.get_unchecked(frame) })
246    }
247
248    #[nonblocking]
249    fn frame_iters(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
250        let num_channels = self.num_channels as usize;
251        let num_frames = self.num_frames;
252        // Get an immutable slice of the channel boxes: `&[Box<[S]>]`
253        let data_slice: &[Box<[S]>] = &self.data;
254
255        // Assumes the struct guarantees that for all `chan` in `0..num_channels`,
256        // `self.data[chan].len() >= num_frames`.
257
258        (0..num_frames).map(move |frame_idx| {
259            // For each frame index, create an iterator over the relevant channel boxes.
260            // `data_slice` is captured immutably, which is allowed by nested closures.
261            data_slice[..num_channels]
262                .iter() // Yields `&'a Box<[S]>`
263                .map(move |channel_slice_box| {
264                    // Get the immutable slice `&[S]` from the box.
265                    let channel_slice: &[S] = channel_slice_box;
266                    // Access the sample immutably using safe indexing.
267                    // Assumes frame_idx is valid based on outer loop and struct invariants.
268                    &channel_slice[frame_idx]
269                    // For max performance (if bounds are absolutely guaranteed):
270                    // unsafe { channel_slice.get_unchecked(frame_idx) }
271                })
272        })
273    }
274
275    #[nonblocking]
276    fn as_view(&self) -> impl AudioBlock<S> {
277        self.view()
278    }
279
280    #[nonblocking]
281    fn as_planar_view(&self) -> Option<AudioBlockPlanarView<'_, S, Self::PlanarView>> {
282        Some(self.view())
283    }
284}
285
286impl<S: Sample> AudioBlockMut<S> for AudioBlockPlanar<S> {
287    type PlanarViewMut = Box<[S]>;
288
289    #[nonblocking]
290    fn set_active_num_channels(&mut self, num_channels: u16) {
291        assert!(num_channels <= self.num_channels_allocated);
292        self.num_channels = num_channels;
293    }
294
295    #[nonblocking]
296    fn set_active_num_frames(&mut self, num_frames: usize) {
297        assert!(num_frames <= self.num_frames_allocated);
298        self.num_frames = num_frames;
299    }
300
301    #[nonblocking]
302    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
303        assert!(channel < self.num_channels);
304        assert!(frame < self.num_frames);
305        unsafe {
306            self.data
307                .get_unchecked_mut(channel as usize)
308                .get_unchecked_mut(frame)
309        }
310    }
311
312    #[nonblocking]
313    fn channel_iter_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
314        assert!(channel < self.num_channels);
315        unsafe {
316            self.data
317                .get_unchecked_mut(channel as usize)
318                .iter_mut()
319                .take(self.num_frames)
320        }
321    }
322
323    #[nonblocking]
324    fn channels_iter_mut(
325        &mut self,
326    ) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
327        let num_frames = self.num_frames;
328        self.data
329            .iter_mut()
330            .take(self.num_channels as usize)
331            .map(move |channel_data| channel_data.as_mut().iter_mut().take(num_frames))
332    }
333
334    #[nonblocking]
335    fn frame_iter_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
336        assert!(frame < self.num_frames);
337        self.data
338            .iter_mut()
339            .take(self.num_channels as usize)
340            .map(move |channel_data| unsafe { channel_data.get_unchecked_mut(frame) })
341    }
342
343    #[nonblocking]
344    fn frames_iter_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
345        let num_channels = self.num_channels as usize;
346        let num_frames = self.num_frames;
347        let data_slice: &mut [Box<[S]>] = &mut self.data;
348        let data_ptr: *mut [Box<[S]>] = data_slice;
349
350        (0..num_frames).map(move |frame_idx| {
351            // Re-borrow mutably inside the closure via the raw pointer.
352            // Safety: Safe because the outer iterator executes this sequentially per frame.
353            let current_channel_boxes: &mut [Box<[S]>] = unsafe { &mut *data_ptr };
354
355            // Iterate over the relevant channel boxes up to num_channels
356            current_channel_boxes[..num_channels]
357                .iter_mut() // Yields `&'a mut Box<[S]>`
358                .map(move |channel_slice_box| {
359                    // Get the mutable slice `&mut [S]` from the box.
360                    let channel_slice: &mut [S] = channel_slice_box;
361                    // Access the sample for the current channel at the current frame index.
362                    // Safety: Relies on `frame_idx < channel_slice.len()`.
363                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
364                })
365        })
366    }
367
368    #[nonblocking]
369    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
370        self.view_mut()
371    }
372
373    #[nonblocking]
374    fn as_planar_view_mut(
375        &mut self,
376    ) -> Option<AudioBlockPlanarViewMut<'_, S, Self::PlanarViewMut>> {
377        Some(self.view_mut())
378    }
379}
380
381impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockPlanar<S> {
382    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
383        writeln!(f, "AudioBlockPlanar {{")?;
384        writeln!(f, "  num_channels: {}", self.num_channels)?;
385        writeln!(f, "  num_frames: {}", self.num_frames)?;
386        writeln!(
387            f,
388            "  num_channels_allocated: {}",
389            self.num_channels_allocated
390        )?;
391        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
392        writeln!(f, "  channels:")?;
393
394        for (i, channel) in self.channels().enumerate() {
395            writeln!(f, "    {}: {:?}", i, channel)?;
396        }
397
398        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
399        writeln!(f, "}}")?;
400
401        Ok(())
402    }
403}
404
405#[cfg(test)]
406mod tests {
407    use super::*;
408    use crate::interleaved::AudioBlockInterleavedView;
409    use rtsan_standalone::no_sanitize_realtime;
410
411    #[test]
412    fn test_member_functions() {
413        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
414        block.channel_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
415        block.channel_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
416
417        block.set_active_size(2, 3);
418
419        // single frame
420        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
421        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
422
423        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
424        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
425
426        // all frames
427        let mut channels = block.channels();
428        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
429        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
430        assert_eq!(channels.next(), None);
431        drop(channels);
432
433        let mut channels = block.channels_mut();
434        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
435        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
436        assert_eq!(channels.next(), None);
437        drop(channels);
438
439        // raw data
440        assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
441        assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
442        assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
443
444        assert_eq!(block.raw_data_mut()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
445        assert_eq!(block.raw_data_mut()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
446        assert_eq!(block.raw_data_mut()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
447
448        // views
449        let view = block.view();
450        assert_eq!(view.num_channels(), block.num_channels());
451        assert_eq!(view.num_frames(), block.num_frames());
452        assert_eq!(
453            view.num_channels_allocated(),
454            block.num_channels_allocated()
455        );
456        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
457        assert_eq!(view.raw_data(), block.raw_data());
458
459        let num_channels = block.num_channels();
460        let num_frames = block.num_frames();
461        let num_channels_allocated = block.num_channels_allocated();
462        let num_frames_allocated = block.num_frames_allocated();
463        let data = block.raw_data().to_vec();
464        let view = block.view_mut();
465        assert_eq!(view.num_channels(), num_channels);
466        assert_eq!(view.num_frames(), num_frames);
467        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
468        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
469        assert_eq!(view.raw_data(), &data);
470    }
471
472    #[test]
473    fn test_samples() {
474        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
475
476        let num_frames = block.num_frames();
477        for ch in 0..block.num_channels() {
478            for f in 0..block.num_frames() {
479                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
480            }
481        }
482
483        for ch in 0..block.num_channels() {
484            for f in 0..block.num_frames() {
485                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
486            }
487        }
488
489        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
490        assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
491    }
492
493    #[test]
494    fn test_channel_iter() {
495        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
496
497        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
498        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
499        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
500        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
501
502        block
503            .channel_iter_mut(0)
504            .enumerate()
505            .for_each(|(i, v)| *v = i as f32);
506        block
507            .channel_iter_mut(1)
508            .enumerate()
509            .for_each(|(i, v)| *v = i as f32 + 10.0);
510
511        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
512        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
513        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
514        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
515    }
516
517    #[test]
518    fn test_channel_iters() {
519        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
520
521        let mut channels_iter = block.channels_iter();
522        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
523        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
524        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
525        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
526        assert!(channels_iter.next().is_none());
527        drop(channels_iter);
528
529        let mut channels_iter = block.channels_iter_mut();
530        channels_iter
531            .next()
532            .unwrap()
533            .enumerate()
534            .for_each(|(i, v)| *v = i as f32);
535        channels_iter
536            .next()
537            .unwrap()
538            .enumerate()
539            .for_each(|(i, v)| *v = i as f32 + 10.0);
540        assert!(channels_iter.next().is_none());
541        drop(channels_iter);
542
543        let mut channels_iter = block.channels_iter();
544        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
545        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
546        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
547        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
548        assert!(channels_iter.next().is_none());
549        drop(channels_iter);
550    }
551
552    #[test]
553    fn test_frame_iter() {
554        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
555
556        for i in 0..block.num_frames() {
557            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
558            assert_eq!(frame, vec![0.0, 0.0]);
559        }
560
561        for i in 0..block.num_frames() {
562            let add = i as f32 * 10.0;
563            block
564                .frame_iter_mut(i)
565                .enumerate()
566                .for_each(|(i, v)| *v = i as f32 + add);
567        }
568
569        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
570        assert_eq!(channel, vec![0.0, 1.0]);
571        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
572        assert_eq!(channel, vec![10.0, 11.0]);
573        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
574        assert_eq!(channel, vec![20.0, 21.0]);
575        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
576        assert_eq!(channel, vec![30.0, 31.0]);
577        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
578        assert_eq!(channel, vec![40.0, 41.0]);
579    }
580
581    #[test]
582    fn test_frame_iters() {
583        let mut block = AudioBlockPlanar::<f32>::new(3, 6);
584        block.set_active_size(2, 5);
585
586        let num_frames = block.num_frames;
587        let mut frames_iter = block.frame_iters();
588        for _ in 0..num_frames {
589            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
590            assert_eq!(frame, vec![0.0, 0.0]);
591        }
592        assert!(frames_iter.next().is_none());
593        drop(frames_iter);
594
595        let mut frames_iter = block.frames_iter_mut();
596        for i in 0..num_frames {
597            let add = i as f32 * 10.0;
598            frames_iter
599                .next()
600                .unwrap()
601                .enumerate()
602                .for_each(|(i, v)| *v = i as f32 + add);
603        }
604        assert!(frames_iter.next().is_none());
605        drop(frames_iter);
606
607        let mut frames_iter = block.frame_iters();
608        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
609        assert_eq!(frame, vec![0.0, 1.0]);
610        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
611        assert_eq!(frame, vec![10.0, 11.0]);
612        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
613        assert_eq!(frame, vec![20.0, 21.0]);
614        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
615        assert_eq!(frame, vec![30.0, 31.0]);
616        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
617        assert_eq!(frame, vec![40.0, 41.0]);
618        assert!(frames_iter.next().is_none());
619    }
620
621    #[test]
622    fn test_from_block() {
623        let block = AudioBlockPlanar::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
624            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
625            2,
626            5,
627        ));
628        assert_eq!(block.num_channels(), 2);
629        assert_eq!(block.num_channels_allocated(), 2);
630        assert_eq!(block.num_frames(), 5);
631        assert_eq!(block.num_frames_allocated(), 5);
632        assert_eq!(
633            block.channel_iter(0).copied().collect::<Vec<_>>(),
634            vec![0.0, 2.0, 4.0, 6.0, 8.0]
635        );
636        assert_eq!(
637            block.channel_iter(1).copied().collect::<Vec<_>>(),
638            vec![1.0, 3.0, 5.0, 7.0, 9.0]
639        );
640        assert_eq!(
641            block.frame_iter(0).copied().collect::<Vec<_>>(),
642            vec![0.0, 1.0]
643        );
644        assert_eq!(
645            block.frame_iter(1).copied().collect::<Vec<_>>(),
646            vec![2.0, 3.0]
647        );
648        assert_eq!(
649            block.frame_iter(2).copied().collect::<Vec<_>>(),
650            vec![4.0, 5.0]
651        );
652        assert_eq!(
653            block.frame_iter(3).copied().collect::<Vec<_>>(),
654            vec![6.0, 7.0]
655        );
656        assert_eq!(
657            block.frame_iter(4).copied().collect::<Vec<_>>(),
658            vec![8.0, 9.0]
659        );
660    }
661
662    #[test]
663    fn test_view() {
664        let block = AudioBlockPlanar::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
665            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
666            2,
667            5,
668        ));
669
670        assert!(block.as_interleaved_view().is_none());
671        assert!(block.as_planar_view().is_some());
672        assert!(block.as_sequential_view().is_none());
673
674        let view = block.view();
675        assert_eq!(
676            view.channel_iter(0).copied().collect::<Vec<_>>(),
677            vec![0.0, 2.0, 4.0, 6.0, 8.0]
678        );
679        assert_eq!(
680            view.channel_iter(1).copied().collect::<Vec<_>>(),
681            vec![1.0, 3.0, 5.0, 7.0, 9.0]
682        );
683    }
684
685    #[test]
686    fn test_view_mut() {
687        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
688        assert!(block.as_interleaved_view().is_none());
689        assert!(block.as_planar_view().is_some());
690        assert!(block.as_sequential_view().is_none());
691        {
692            let mut view = block.view_mut();
693            view.channel_iter_mut(0)
694                .enumerate()
695                .for_each(|(i, v)| *v = i as f32);
696            view.channel_iter_mut(1)
697                .enumerate()
698                .for_each(|(i, v)| *v = i as f32 + 10.0);
699        }
700
701        assert_eq!(
702            block.channel_iter(0).copied().collect::<Vec<_>>(),
703            vec![0.0, 1.0, 2.0, 3.0, 4.0]
704        );
705        assert_eq!(
706            block.channel_iter(1).copied().collect::<Vec<_>>(),
707            vec![10.0, 11.0, 12.0, 13.0, 14.0]
708        );
709    }
710
711    #[test]
712    fn test_resize() {
713        let mut block = AudioBlockPlanar::<f32>::new(3, 10);
714        assert_eq!(block.num_channels(), 3);
715        assert_eq!(block.num_frames(), 10);
716        assert_eq!(block.num_channels_allocated(), 3);
717        assert_eq!(block.num_frames_allocated(), 10);
718
719        for i in 0..block.num_channels() {
720            assert_eq!(block.channel_iter(i).count(), 10);
721            assert_eq!(block.channel_iter_mut(i).count(), 10);
722        }
723        for i in 0..block.num_frames() {
724            assert_eq!(block.frame_iter(i).count(), 3);
725            assert_eq!(block.frame_iter_mut(i).count(), 3);
726        }
727
728        block.set_active_size(3, 10);
729        block.set_active_size(2, 5);
730
731        assert_eq!(block.num_channels(), 2);
732        assert_eq!(block.num_frames(), 5);
733        assert_eq!(block.num_channels_allocated(), 3);
734        assert_eq!(block.num_frames_allocated(), 10);
735
736        for i in 0..block.num_channels() {
737            assert_eq!(block.channel_iter(i).count(), 5);
738            assert_eq!(block.channel_iter_mut(i).count(), 5);
739        }
740        for i in 0..block.num_frames() {
741            assert_eq!(block.frame_iter(i).count(), 2);
742            assert_eq!(block.frame_iter_mut(i).count(), 2);
743        }
744    }
745
746    #[test]
747    #[should_panic]
748    #[no_sanitize_realtime]
749    fn test_wrong_resize_channels() {
750        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
751        block.set_active_size(3, 10);
752    }
753
754    #[test]
755    #[should_panic]
756    #[no_sanitize_realtime]
757    fn test_wrong_resize_frames() {
758        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
759        block.set_active_size(2, 11);
760    }
761
762    #[test]
763    #[should_panic]
764    #[no_sanitize_realtime]
765    fn test_wrong_channel() {
766        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
767        block.set_active_size(1, 10);
768        let _ = block.channel_iter(1);
769    }
770
771    #[test]
772    #[should_panic]
773    #[no_sanitize_realtime]
774    fn test_wrong_frame() {
775        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
776        block.set_active_size(2, 5);
777        let _ = block.frame_iter(5);
778    }
779
780    #[test]
781    #[should_panic]
782    #[no_sanitize_realtime]
783    fn test_wrong_channel_mut() {
784        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
785        block.set_active_size(1, 10);
786        let _ = block.channel_iter_mut(1);
787    }
788
789    #[test]
790    #[should_panic]
791    #[no_sanitize_realtime]
792    fn test_wrong_frame_mut() {
793        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
794        block.set_active_size(2, 5);
795        let _ = block.frame_iter_mut(5);
796    }
797
798    #[test]
799    #[should_panic]
800    #[no_sanitize_realtime]
801    fn test_slice_out_of_bounds() {
802        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
803        block.set_active_size(2, 3);
804
805        block.channel(2);
806    }
807
808    #[test]
809    #[should_panic]
810    #[no_sanitize_realtime]
811    fn test_slice_out_of_bounds_mut() {
812        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
813        block.set_active_size(2, 3);
814
815        block.channel_mut(2);
816    }
817}