Skip to main content

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