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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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(
410        &mut self,
411    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
412        let num_channels = self.num_channels as usize;
413        let num_frames = self.num_frames;
414        let data_slice: &mut [Box<[S]>] = &mut self.data;
415        let data_ptr: *mut [Box<[S]>] = data_slice;
416
417        (0..num_frames).map(move |frame_idx| {
418            // Re-borrow mutably inside the closure via the raw pointer.
419            // Safety: Safe because the outer iterator executes this sequentially per frame.
420            let current_channel_boxes: &mut [Box<[S]>] = unsafe { &mut *data_ptr };
421
422            // Iterate over the relevant channel boxes up to num_channels
423            current_channel_boxes[..num_channels]
424                .iter_mut() // Yields `&'a mut Box<[S]>`
425                .map(move |channel_slice_box| {
426                    // Get the mutable slice `&mut [S]` from the box.
427                    let channel_slice: &mut [S] = channel_slice_box;
428                    // Access the sample for the current channel at the current frame index.
429                    // Safety: Relies on `frame_idx < channel_slice.len()`.
430                    unsafe { channel_slice.get_unchecked_mut(frame_idx) }
431                })
432        })
433    }
434
435    #[nonblocking]
436    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
437        self.view_mut()
438    }
439
440    #[nonblocking]
441    fn as_planar_view_mut(
442        &mut self,
443    ) -> Option<AudioBlockPlanarViewMut<'_, S, Self::PlanarViewMut>> {
444        Some(self.view_mut())
445    }
446}
447
448impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockPlanar<S> {
449    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
450        writeln!(f, "AudioBlockPlanar {{")?;
451        writeln!(f, "  num_channels: {}", self.num_channels)?;
452        writeln!(f, "  num_frames: {}", self.num_frames)?;
453        writeln!(
454            f,
455            "  num_channels_allocated: {}",
456            self.num_channels_allocated
457        )?;
458        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
459        writeln!(f, "  channels:")?;
460
461        for (i, channel) in self.channels().enumerate() {
462            writeln!(f, "    {}: {:?}", i, channel)?;
463        }
464
465        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
466        writeln!(f, "}}")?;
467
468        Ok(())
469    }
470}
471
472#[cfg(test)]
473mod tests {
474    use super::*;
475    use crate::interleaved::AudioBlockInterleavedView;
476    use rtsan_standalone::no_sanitize_realtime;
477
478    #[test]
479    fn test_member_functions() {
480        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
481        block.channel_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
482        block.channel_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
483
484        block.set_visible(2, 3);
485
486        // single frame
487        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
488        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
489
490        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
491        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
492
493        // all frames
494        let mut channels = block.channels();
495        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
496        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
497        assert_eq!(channels.next(), None);
498        drop(channels);
499
500        let mut channels = block.channels_mut();
501        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
502        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
503        assert_eq!(channels.next(), None);
504        drop(channels);
505
506        // raw data
507        assert_eq!(block.raw_data()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
508        assert_eq!(block.raw_data()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
509        assert_eq!(block.raw_data()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
510
511        assert_eq!(block.raw_data_mut()[0].as_ref(), &[0.0, 1.0, 2.0, 3.0]);
512        assert_eq!(block.raw_data_mut()[1].as_ref(), &[4.0, 5.0, 6.0, 7.0]);
513        assert_eq!(block.raw_data_mut()[2].as_ref(), &[0.0, 0.0, 0.0, 0.0]);
514
515        // views
516        let view = block.view();
517        assert_eq!(view.num_channels(), block.num_channels());
518        assert_eq!(view.num_frames(), block.num_frames());
519        assert_eq!(
520            view.num_channels_allocated(),
521            block.num_channels_allocated()
522        );
523        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
524        assert_eq!(view.raw_data(), block.raw_data());
525
526        let num_channels = block.num_channels();
527        let num_frames = block.num_frames();
528        let num_channels_allocated = block.num_channels_allocated();
529        let num_frames_allocated = block.num_frames_allocated();
530        let data = block.raw_data().to_vec();
531        let view = block.view_mut();
532        assert_eq!(view.num_channels(), num_channels);
533        assert_eq!(view.num_frames(), num_frames);
534        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
535        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
536        assert_eq!(view.raw_data(), &data);
537    }
538
539    #[test]
540    fn test_samples() {
541        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
542
543        let num_frames = block.num_frames();
544        for ch in 0..block.num_channels() {
545            for f in 0..block.num_frames() {
546                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
547            }
548        }
549
550        for ch in 0..block.num_channels() {
551            for f in 0..block.num_frames() {
552                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
553            }
554        }
555
556        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0, 3.0, 4.0]);
557        assert_eq!(block.channel(1), &[5.0, 6.0, 7.0, 8.0, 9.0]);
558    }
559
560    #[test]
561    fn test_channel_iter() {
562        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
563
564        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
565        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
566        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
567        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
568
569        block
570            .channel_iter_mut(0)
571            .enumerate()
572            .for_each(|(i, v)| *v = i as f32);
573        block
574            .channel_iter_mut(1)
575            .enumerate()
576            .for_each(|(i, v)| *v = i as f32 + 10.0);
577
578        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
579        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
580        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
581        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
582    }
583
584    #[test]
585    fn test_channel_iters() {
586        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
587
588        let mut channels_iter = block.channels_iter();
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        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
592        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
593        assert!(channels_iter.next().is_none());
594        drop(channels_iter);
595
596        let mut channels_iter = block.channels_iter_mut();
597        channels_iter
598            .next()
599            .unwrap()
600            .enumerate()
601            .for_each(|(i, v)| *v = i as f32);
602        channels_iter
603            .next()
604            .unwrap()
605            .enumerate()
606            .for_each(|(i, v)| *v = i as f32 + 10.0);
607        assert!(channels_iter.next().is_none());
608        drop(channels_iter);
609
610        let mut channels_iter = block.channels_iter();
611        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
612        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
613        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
614        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
615        assert!(channels_iter.next().is_none());
616        drop(channels_iter);
617    }
618
619    #[test]
620    fn test_frame_iter() {
621        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
622
623        for i in 0..block.num_frames() {
624            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
625            assert_eq!(frame, vec![0.0, 0.0]);
626        }
627
628        for i in 0..block.num_frames() {
629            let add = i as f32 * 10.0;
630            block
631                .frame_iter_mut(i)
632                .enumerate()
633                .for_each(|(i, v)| *v = i as f32 + add);
634        }
635
636        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
637        assert_eq!(channel, vec![0.0, 1.0]);
638        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
639        assert_eq!(channel, vec![10.0, 11.0]);
640        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
641        assert_eq!(channel, vec![20.0, 21.0]);
642        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
643        assert_eq!(channel, vec![30.0, 31.0]);
644        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
645        assert_eq!(channel, vec![40.0, 41.0]);
646    }
647
648    #[test]
649    fn test_frame_iters() {
650        let mut block = AudioBlockPlanar::<f32>::new(3, 6);
651        block.set_visible(2, 5);
652
653        let num_frames = block.num_frames;
654        let mut frames_iter = block.frames_iter();
655        for _ in 0..num_frames {
656            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
657            assert_eq!(frame, vec![0.0, 0.0]);
658        }
659        assert!(frames_iter.next().is_none());
660        drop(frames_iter);
661
662        let mut frames_iter = block.frames_iter_mut();
663        for i in 0..num_frames {
664            let add = i as f32 * 10.0;
665            frames_iter
666                .next()
667                .unwrap()
668                .enumerate()
669                .for_each(|(i, v)| *v = i as f32 + add);
670        }
671        assert!(frames_iter.next().is_none());
672        drop(frames_iter);
673
674        let mut frames_iter = block.frames_iter();
675        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
676        assert_eq!(frame, vec![0.0, 1.0]);
677        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
678        assert_eq!(frame, vec![10.0, 11.0]);
679        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
680        assert_eq!(frame, vec![20.0, 21.0]);
681        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
682        assert_eq!(frame, vec![30.0, 31.0]);
683        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
684        assert_eq!(frame, vec![40.0, 41.0]);
685        assert!(frames_iter.next().is_none());
686    }
687
688    #[test]
689    fn test_from_block() {
690        let block = AudioBlockPlanar::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
691            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
692            2,
693        ));
694        assert_eq!(block.num_channels(), 2);
695        assert_eq!(block.num_channels_allocated(), 2);
696        assert_eq!(block.num_frames(), 5);
697        assert_eq!(block.num_frames_allocated(), 5);
698        assert_eq!(
699            block.channel_iter(0).copied().collect::<Vec<_>>(),
700            vec![0.0, 2.0, 4.0, 6.0, 8.0]
701        );
702        assert_eq!(
703            block.channel_iter(1).copied().collect::<Vec<_>>(),
704            vec![1.0, 3.0, 5.0, 7.0, 9.0]
705        );
706        assert_eq!(
707            block.frame_iter(0).copied().collect::<Vec<_>>(),
708            vec![0.0, 1.0]
709        );
710        assert_eq!(
711            block.frame_iter(1).copied().collect::<Vec<_>>(),
712            vec![2.0, 3.0]
713        );
714        assert_eq!(
715            block.frame_iter(2).copied().collect::<Vec<_>>(),
716            vec![4.0, 5.0]
717        );
718        assert_eq!(
719            block.frame_iter(3).copied().collect::<Vec<_>>(),
720            vec![6.0, 7.0]
721        );
722        assert_eq!(
723            block.frame_iter(4).copied().collect::<Vec<_>>(),
724            vec![8.0, 9.0]
725        );
726    }
727
728    #[test]
729    fn test_view() {
730        let block = AudioBlockPlanar::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
731            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
732            2,
733        ));
734
735        assert!(block.as_interleaved_view().is_none());
736        assert!(block.as_planar_view().is_some());
737        assert!(block.as_sequential_view().is_none());
738
739        let view = block.view();
740        assert_eq!(
741            view.channel_iter(0).copied().collect::<Vec<_>>(),
742            vec![0.0, 2.0, 4.0, 6.0, 8.0]
743        );
744        assert_eq!(
745            view.channel_iter(1).copied().collect::<Vec<_>>(),
746            vec![1.0, 3.0, 5.0, 7.0, 9.0]
747        );
748    }
749
750    #[test]
751    fn test_view_mut() {
752        let mut block = AudioBlockPlanar::<f32>::new(2, 5);
753        assert!(block.as_interleaved_view().is_none());
754        assert!(block.as_planar_view().is_some());
755        assert!(block.as_sequential_view().is_none());
756        {
757            let mut view = block.view_mut();
758            view.channel_iter_mut(0)
759                .enumerate()
760                .for_each(|(i, v)| *v = i as f32);
761            view.channel_iter_mut(1)
762                .enumerate()
763                .for_each(|(i, v)| *v = i as f32 + 10.0);
764        }
765
766        assert_eq!(
767            block.channel_iter(0).copied().collect::<Vec<_>>(),
768            vec![0.0, 1.0, 2.0, 3.0, 4.0]
769        );
770        assert_eq!(
771            block.channel_iter(1).copied().collect::<Vec<_>>(),
772            vec![10.0, 11.0, 12.0, 13.0, 14.0]
773        );
774    }
775
776    #[test]
777    fn test_resize() {
778        let mut block = AudioBlockPlanar::<f32>::new(3, 10);
779        assert_eq!(block.num_channels(), 3);
780        assert_eq!(block.num_frames(), 10);
781        assert_eq!(block.num_channels_allocated(), 3);
782        assert_eq!(block.num_frames_allocated(), 10);
783
784        for i in 0..block.num_channels() {
785            assert_eq!(block.channel_iter(i).count(), 10);
786            assert_eq!(block.channel_iter_mut(i).count(), 10);
787        }
788        for i in 0..block.num_frames() {
789            assert_eq!(block.frame_iter(i).count(), 3);
790            assert_eq!(block.frame_iter_mut(i).count(), 3);
791        }
792
793        block.set_visible(3, 10);
794        block.set_visible(2, 5);
795
796        assert_eq!(block.num_channels(), 2);
797        assert_eq!(block.num_frames(), 5);
798        assert_eq!(block.num_channels_allocated(), 3);
799        assert_eq!(block.num_frames_allocated(), 10);
800
801        for i in 0..block.num_channels() {
802            assert_eq!(block.channel_iter(i).count(), 5);
803            assert_eq!(block.channel_iter_mut(i).count(), 5);
804        }
805        for i in 0..block.num_frames() {
806            assert_eq!(block.frame_iter(i).count(), 2);
807            assert_eq!(block.frame_iter_mut(i).count(), 2);
808        }
809    }
810
811    #[test]
812    #[should_panic]
813    #[no_sanitize_realtime]
814    fn test_wrong_resize_channels() {
815        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
816        block.set_visible(3, 10);
817    }
818
819    #[test]
820    #[should_panic]
821    #[no_sanitize_realtime]
822    fn test_wrong_resize_frames() {
823        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
824        block.set_visible(2, 11);
825    }
826
827    #[test]
828    #[should_panic]
829    #[no_sanitize_realtime]
830    fn test_wrong_channel() {
831        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
832        block.set_visible(1, 10);
833        let _ = block.channel_iter(1);
834    }
835
836    #[test]
837    #[should_panic]
838    #[no_sanitize_realtime]
839    fn test_wrong_frame() {
840        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
841        block.set_visible(2, 5);
842        let _ = block.frame_iter(5);
843    }
844
845    #[test]
846    #[should_panic]
847    #[no_sanitize_realtime]
848    fn test_wrong_channel_mut() {
849        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
850        block.set_visible(1, 10);
851        let _ = block.channel_iter_mut(1);
852    }
853
854    #[test]
855    #[should_panic]
856    #[no_sanitize_realtime]
857    fn test_wrong_frame_mut() {
858        let mut block = AudioBlockPlanar::<f32>::new(2, 10);
859        block.set_visible(2, 5);
860        let _ = block.frame_iter_mut(5);
861    }
862
863    #[test]
864    #[should_panic]
865    #[no_sanitize_realtime]
866    fn test_slice_out_of_bounds() {
867        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
868        block.set_visible(2, 3);
869
870        block.channel(2);
871    }
872
873    #[test]
874    #[should_panic]
875    #[no_sanitize_realtime]
876    fn test_slice_out_of_bounds_mut() {
877        let mut block = AudioBlockPlanar::<f32>::new(3, 4);
878        block.set_visible(2, 3);
879
880        block.channel_mut(2);
881    }
882}