Skip to main content

audio_blocks/interleaved/
owned.rs

1use rtsan_standalone::{blocking, nonblocking};
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::{boxed::Box, vec, vec::Vec};
5use core::{marker::PhantomData, ptr::NonNull};
6#[cfg(all(feature = "std", not(feature = "alloc")))]
7use std::{boxed::Box, vec, vec::Vec};
8#[cfg(all(feature = "std", feature = "alloc"))]
9use std::{boxed::Box, vec, vec::Vec};
10
11use super::{view::InterleavedView, view_mut::InterleavedViewMut};
12use crate::{
13    AudioBlock, AudioBlockMut, Sample,
14    iter::{StridedSampleIter, StridedSampleIterMut},
15};
16
17/// An interleaved audio block that owns its data.
18///
19/// * **Layout:** `[ch0, ch1, ch0, ch1, ch0, ch1]`
20/// * **Interpretation:** Each group of channel samples represents a frame. So, this layout stores frames one after another.
21/// * **Terminology:** Described as “packed” or “frames first” because each time step is grouped and processed as a unit (a frame).
22/// * **Usage:** Often used in APIs or hardware-level interfaces, where synchronized playback across channels is crucial.
23///
24/// # Example
25///
26/// ```
27/// use audio_blocks::*;
28///
29/// let block = Interleaved::new(2, 3);
30/// let mut block = Interleaved::from_block(&block);
31///
32/// block.frame_mut(0).fill(0.0);
33/// block.frame_mut(1).fill(1.0);
34/// block.frame_mut(2).fill(2.0);
35///
36/// assert_eq!(block.raw_data(), &[0.0, 0.0, 1.0, 1.0, 2.0, 2.0]);
37/// ```
38#[derive(Default, Clone)]
39pub struct Interleaved<S: Sample> {
40    data: Box<[S]>,
41    num_channels: u16,
42    num_frames: usize,
43    num_channels_allocated: u16,
44    num_frames_allocated: usize,
45}
46
47impl<S: Sample + Default> Interleaved<S> {
48    /// Creates a new interleaved audio block with the specified dimensions.
49    ///
50    /// Allocates memory for a new interleaved audio block with exactly the specified
51    /// number of channels and frames. The block is initialized with the default value
52    /// for the sample type.
53    ///
54    /// Do not use in real-time processes!
55    ///
56    /// # Arguments
57    ///
58    /// * `num_channels` - The number of audio channels
59    /// * `num_frames` - The number of frames per channel
60    ///
61    /// # Panics
62    ///
63    /// Panics if the multiplication of `num_channels` and `num_frames` would overflow a usize.
64    #[blocking]
65    pub fn new(num_channels: u16, num_frames: usize) -> Self {
66        let total_samples = (num_channels as usize)
67            .checked_mul(num_frames)
68            .expect("Multiplication overflow: num_channels * num_frames is too large");
69
70        Self {
71            data: vec![S::default(); total_samples].into_boxed_slice(),
72            num_channels,
73            num_frames,
74            num_channels_allocated: num_channels,
75            num_frames_allocated: num_frames,
76        }
77    }
78}
79
80impl<S: Sample> Interleaved<S> {
81    /// Creates a new interleaved audio block by copying the data from a slice of interleaved audio data.
82    ///
83    /// # Parameters
84    /// * `data` - The slice containing interleaved audio samples
85    /// * `num_channels` - Number of audio channels in the data
86    ///
87    /// # Panics
88    /// Panics if the length of `data` is not evenly divisible by `num_channels`.
89    #[blocking]
90    pub fn from_slice(data: &[S], num_channels: u16) -> Self {
91        assert!(
92            num_channels > 0 && data.len() % num_channels as usize == 0,
93            "data length {} must be divisible by num_channels {}",
94            data.len(),
95            num_channels
96        );
97        let num_frames = data.len() / num_channels as usize;
98        Self {
99            data: data.to_vec().into_boxed_slice(),
100            num_channels,
101            num_frames,
102            num_channels_allocated: num_channels,
103            num_frames_allocated: num_frames,
104        }
105    }
106
107    /// Creates a new interleaved audio block by copying the data from a slice of interleaved audio data with limited visibility.
108    ///
109    /// This function allows creating a block that exposes only a subset of the allocated channels
110    /// and frames, which is useful for working with a logical section of a larger buffer.
111    ///
112    /// # Parameters
113    /// * `data` - The slice containing interleaved audio samples
114    /// * `num_channels_visible` - Number of audio channels to expose
115    /// * `num_frames_visible` - Number of audio frames to expose
116    /// * `num_channels_allocated` - Total number of channels allocated in the data buffer
117    /// * `num_frames_allocated` - Total number of frames allocated in the data buffer
118    ///
119    /// # Panics
120    /// * Panics if the length of `data` doesn't equal `num_channels_allocated * num_frames_allocated`
121    /// * Panics if `num_channels_visible` exceeds `num_channels_allocated`
122    /// * Panics if `num_frames_visible` exceeds `num_frames_allocated`
123    #[blocking]
124    pub fn from_slice_limited(
125        data: &[S],
126        num_channels_visible: u16,
127        num_frames_visible: usize,
128        num_channels_allocated: u16,
129        num_frames_allocated: usize,
130    ) -> Self {
131        assert_eq!(
132            data.len(),
133            num_channels_allocated as usize * num_frames_allocated
134        );
135        assert!(num_channels_visible <= num_channels_allocated);
136        assert!(num_frames_visible <= num_frames_allocated);
137        Self {
138            data: data.to_vec().into_boxed_slice(),
139            num_channels: num_channels_visible,
140            num_frames: num_frames_visible,
141            num_channels_allocated,
142            num_frames_allocated,
143        }
144    }
145
146    /// Creates a new audio block by copying data from another [`AudioBlock`].
147    ///
148    /// Converts any [`AudioBlock`] implementation to an interleaved format by iterating
149    /// through each frame of the source block and copying its samples. The new block
150    /// will have the same dimensions as the source block.
151    ///
152    /// # Warning
153    ///
154    /// This function allocates memory and should not be used in real-time audio processing contexts.
155    ///
156    /// # Arguments
157    ///
158    /// * `block` - The source audio block to copy data from
159    #[blocking]
160    pub fn from_block(block: &impl AudioBlock<S>) -> Self {
161        let mut data = Vec::with_capacity(block.num_channels() as usize * block.num_frames());
162        block
163            .frames_iter()
164            .for_each(|f| f.for_each(|&v| data.push(v)));
165        Self {
166            data: data.into_boxed_slice(),
167            num_channels: block.num_channels(),
168            num_frames: block.num_frames(),
169            num_channels_allocated: block.num_channels(),
170            num_frames_allocated: block.num_frames(),
171        }
172    }
173
174    /// Returns a slice for a single frame.
175    ///
176    /// # Panics
177    ///
178    /// Panics if frame index is out of bounds.
179    #[nonblocking]
180    pub fn frame(&self, frame: usize) -> &[S] {
181        assert!(frame < self.num_frames);
182        let start = frame * self.num_channels_allocated as usize;
183        let end = start + self.num_channels as usize;
184        &self.data[start..end]
185    }
186
187    /// Returns a mutable slice for a single frame.
188    ///
189    /// # Panics
190    ///
191    /// Panics if frame index is out of bounds.
192    #[nonblocking]
193    pub fn frame_mut(&mut self, frame: usize) -> &mut [S] {
194        assert!(frame < self.num_frames);
195        let start = frame * self.num_channels_allocated as usize;
196        let end = start + self.num_channels as usize;
197        &mut self.data[start..end]
198    }
199
200    /// Returns an iterator over all frames in the block.
201    ///
202    /// Each frame is represented as a slice of samples.
203    #[nonblocking]
204    pub fn frames(&self) -> impl ExactSizeIterator<Item = &[S]> {
205        self.data
206            .chunks(self.num_channels_allocated as usize)
207            .take(self.num_frames)
208            .map(move |frame| &frame[..self.num_channels as usize])
209    }
210
211    /// Returns a mutable iterator over all frames in the block.
212    ///
213    /// Each frame is represented as a mutable slice of samples.
214    #[nonblocking]
215    pub fn frames_mut(&mut self) -> impl ExactSizeIterator<Item = &mut [S]> {
216        let num_channels = self.num_channels as usize;
217        self.data
218            .chunks_mut(self.num_channels_allocated as usize)
219            .take(self.num_frames)
220            .map(move |frame| &mut frame[..num_channels])
221    }
222
223    /// Provides direct access to the underlying memory as an interleaved slice.
224    ///
225    /// This function gives access to all allocated data, including any reserved capacity
226    /// beyond the visible range.
227    #[nonblocking]
228    pub fn raw_data(&self) -> &[S] {
229        &self.data
230    }
231
232    /// Provides direct mutable access to the underlying memory as an interleaved slice.
233    ///
234    /// This function gives mutable access to all allocated data, including any reserved capacity
235    /// beyond the visible range.
236    #[nonblocking]
237    pub fn raw_data_mut(&mut self) -> &mut [S] {
238        &mut self.data
239    }
240
241    #[nonblocking]
242    pub fn view(&self) -> InterleavedView<'_, S> {
243        InterleavedView::from_slice_limited(
244            &self.data,
245            self.num_channels,
246            self.num_frames,
247            self.num_channels_allocated,
248            self.num_frames_allocated,
249        )
250    }
251
252    #[nonblocking]
253    pub fn view_mut(&mut self) -> InterleavedViewMut<'_, S> {
254        InterleavedViewMut::from_slice_limited(
255            &mut self.data,
256            self.num_channels,
257            self.num_frames,
258            self.num_channels_allocated,
259            self.num_frames_allocated,
260        )
261    }
262}
263
264impl<S: Sample> AudioBlock<S> for Interleaved<S> {
265    type PlanarView = [S; 0];
266
267    #[nonblocking]
268    fn num_channels(&self) -> u16 {
269        self.num_channels
270    }
271
272    #[nonblocking]
273    fn num_frames(&self) -> usize {
274        self.num_frames
275    }
276
277    #[nonblocking]
278    fn num_channels_allocated(&self) -> u16 {
279        self.num_channels_allocated
280    }
281
282    #[nonblocking]
283    fn num_frames_allocated(&self) -> usize {
284        self.num_frames_allocated
285    }
286
287    #[nonblocking]
288    fn layout(&self) -> crate::BlockLayout {
289        crate::BlockLayout::Interleaved
290    }
291
292    #[nonblocking]
293    fn sample(&self, channel: u16, frame: usize) -> S {
294        assert!(channel < self.num_channels);
295        assert!(frame < self.num_frames);
296        unsafe {
297            *self
298                .data
299                .get_unchecked(frame * self.num_channels_allocated as usize + channel as usize)
300        }
301    }
302
303    #[nonblocking]
304    fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
305        assert!(channel < self.num_channels);
306        self.data
307            .iter()
308            .skip(channel as usize)
309            .step_by(self.num_channels_allocated as usize)
310            .take(self.num_frames)
311    }
312
313    #[nonblocking]
314    fn channels_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        let stride = self.num_channels_allocated as usize;
318
319        // If the data slice is empty (num_channels or num_frames was 0),
320        // the effective number of frames any iterator should yield is 0.
321        let effective_num_frames = if self.data.is_empty() { 0 } else { num_frames };
322
323        // Get base pointer. If data is empty, it's dangling, but this is fine
324        // because effective_num_frames will be 0, preventing its use in next().
325        let data_ptr = self.data.as_ptr();
326
327        (0..num_channels).map(move |channel_idx| {
328            // Calculate start pointer for the channel.
329            // Safety: If data is not empty, data_ptr is valid and channel_idx is
330            // within bounds [0, num_channels), which is <= num_channels_allocated.
331            // Pointer arithmetic is contained within the allocation.
332            // If data is empty, data_ptr is dangling, but add(0) is okay.
333            // If channel_idx > 0 and data is empty, this relies on num_channels being 0
334            // (so this closure doesn't run) or effective_num_frames being 0
335            // (so the resulting iterator is a no-op).
336            // We rely on effective_num_frames == 0 when data is empty.
337            let start_ptr = unsafe { data_ptr.add(channel_idx) };
338
339            StridedSampleIter::<'_, S> {
340                // Safety: Cast to *mut S for NonNull::new.
341                // If effective_num_frames is 0, ptr can be dangling (NonNull::dangling()).
342                // If effective_num_frames > 0, data is not empty, start_ptr is valid and non-null.
343                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()),
344                stride,
345                remaining: effective_num_frames, // Use the safe frame count
346                _marker: PhantomData,
347            }
348        })
349    }
350
351    #[nonblocking]
352    fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
353        assert!(frame < self.num_frames);
354        self.data
355            .iter()
356            .skip(frame * self.num_channels_allocated as usize)
357            .take(self.num_channels as usize)
358    }
359
360    #[nonblocking]
361    fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
362        let num_channels = self.num_channels as usize;
363        let num_channels_allocated = self.num_channels_allocated as usize;
364        self.data
365            .chunks(num_channels_allocated)
366            .take(self.num_frames)
367            .map(move |channel_chunk| channel_chunk.iter().take(num_channels))
368    }
369
370    #[nonblocking]
371    fn as_view(&self) -> impl AudioBlock<S> {
372        self.view()
373    }
374
375    #[nonblocking]
376    fn as_interleaved_view(&self) -> Option<InterleavedView<'_, S>> {
377        Some(self.view())
378    }
379}
380
381impl<S: Sample> AudioBlockMut<S> for Interleaved<S> {
382    type PlanarViewMut = [S; 0];
383
384    #[nonblocking]
385    fn set_num_channels_visible(&mut self, num_channels: u16) {
386        assert!(num_channels <= self.num_channels_allocated);
387        self.num_channels = num_channels;
388    }
389
390    #[nonblocking]
391    fn set_num_frames_visible(&mut self, num_frames: usize) {
392        assert!(num_frames <= self.num_frames_allocated);
393        self.num_frames = num_frames;
394    }
395
396    #[nonblocking]
397    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
398        assert!(channel < self.num_channels);
399        assert!(frame < self.num_frames);
400        unsafe {
401            self.data
402                .get_unchecked_mut(frame * self.num_channels_allocated as usize + channel as usize)
403        }
404    }
405
406    #[nonblocking]
407    fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S> {
408        assert!(channel < self.num_channels);
409        self.data
410            .iter_mut()
411            .skip(channel as usize)
412            .step_by(self.num_channels_allocated as usize)
413            .take(self.num_frames)
414    }
415
416    #[nonblocking]
417    fn channels_iter_mut(
418        &mut self,
419    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
420        let num_channels = self.num_channels as usize;
421        let num_frames = self.num_frames;
422        let stride = self.num_channels_allocated as usize;
423
424        // Ensure iterator is empty if underlying data is empty.
425        let effective_num_frames = if self.data.is_empty() { 0 } else { num_frames };
426
427        // Get base mutable pointer.
428        let data_ptr = self.data.as_mut_ptr();
429
430        (0..num_channels).map(move |channel_idx| {
431            // Calculate start pointer.
432            // Safety: Same reasoning as the immutable version applies.
433            let start_ptr = unsafe { data_ptr.add(channel_idx) };
434
435            StridedSampleIterMut::<'_, S> {
436                // Safety: Same reasoning as the immutable version applies.
437                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()),
438                stride,
439                remaining: effective_num_frames, // Use the safe frame count
440                _marker: PhantomData,
441            }
442        })
443    }
444
445    #[nonblocking]
446    fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S> {
447        assert!(frame < self.num_frames);
448        self.data
449            .iter_mut()
450            .skip(frame * self.num_channels_allocated as usize)
451            .take(self.num_channels as usize)
452    }
453
454    #[nonblocking]
455    fn frames_iter_mut(
456        &mut self,
457    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S> + ExactSizeIterator>
458    {
459        let num_channels = self.num_channels as usize;
460        let num_channels_allocated = self.num_channels_allocated as usize;
461        self.data
462            .chunks_mut(num_channels_allocated)
463            .take(self.num_frames)
464            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_channels))
465    }
466
467    #[nonblocking]
468    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
469        self.view_mut()
470    }
471
472    #[nonblocking]
473    fn as_interleaved_view_mut(&mut self) -> Option<InterleavedViewMut<'_, S>> {
474        Some(self.view_mut())
475    }
476}
477
478impl<S: Sample + core::fmt::Debug> core::fmt::Debug for Interleaved<S> {
479    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
480        writeln!(f, "audio_blocks::Interleaved {{")?;
481        writeln!(f, "  num_channels: {}", self.num_channels)?;
482        writeln!(f, "  num_frames: {}", self.num_frames)?;
483        writeln!(
484            f,
485            "  num_channels_allocated: {}",
486            self.num_channels_allocated
487        )?;
488        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
489        writeln!(f, "  frames:")?;
490
491        for (i, frame) in self.frames().enumerate() {
492            writeln!(f, "    {}: {:?}", i, frame)?;
493        }
494
495        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
496        writeln!(f, "}}")?;
497
498        Ok(())
499    }
500}
501
502#[cfg(test)]
503mod tests {
504    use super::*;
505    use crate::sequential::SequentialView;
506    use rtsan_standalone::no_sanitize_realtime;
507
508    #[test]
509    fn test_member_functions() {
510        let mut block = Interleaved::<f32>::new(4, 3);
511        block.frame_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
512        block.frame_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
513
514        block.set_visible(3, 2);
515
516        // single frame
517        assert_eq!(block.frame(0), &[0.0, 1.0, 2.0]);
518        assert_eq!(block.frame(1), &[4.0, 5.0, 6.0]);
519
520        assert_eq!(block.frame_mut(0), &[0.0, 1.0, 2.0]);
521        assert_eq!(block.frame_mut(1), &[4.0, 5.0, 6.0]);
522
523        // all frames
524        let mut frames = block.frames();
525        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
526        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
527        assert_eq!(frames.next(), None);
528        drop(frames);
529
530        let mut frames = block.frames_mut();
531        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
532        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
533        assert_eq!(frames.next(), None);
534        drop(frames);
535
536        // raw data
537        assert_eq!(
538            block.raw_data(),
539            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
540        );
541
542        assert_eq!(
543            block.raw_data_mut(),
544            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
545        );
546
547        // views
548        let view = block.view();
549        assert_eq!(view.num_channels(), block.num_channels());
550        assert_eq!(view.num_frames(), block.num_frames());
551        assert_eq!(
552            view.num_channels_allocated(),
553            block.num_channels_allocated()
554        );
555        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
556        assert_eq!(view.raw_data(), block.raw_data());
557
558        let num_channels = block.num_channels();
559        let num_frames = block.num_frames();
560        let num_channels_allocated = block.num_channels_allocated();
561        let num_frames_allocated = block.num_frames_allocated();
562        let data = block.raw_data().to_vec();
563        let view = block.view_mut();
564        assert_eq!(view.num_channels(), num_channels);
565        assert_eq!(view.num_frames(), num_frames);
566        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
567        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
568        assert_eq!(view.raw_data(), &data);
569    }
570
571    #[test]
572    fn test_samples() {
573        let mut block = Interleaved::<f32>::new(2, 5);
574
575        let num_frames = block.num_frames();
576        for ch in 0..block.num_channels() {
577            for f in 0..block.num_frames() {
578                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
579            }
580        }
581
582        for ch in 0..block.num_channels() {
583            for f in 0..block.num_frames() {
584                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
585            }
586        }
587
588        assert_eq!(
589            block.raw_data(),
590            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
591        );
592    }
593
594    #[test]
595    fn test_channel_iter() {
596        let mut block = Interleaved::<f32>::new(2, 5);
597
598        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
599        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
600        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
601        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
602
603        block
604            .channel_iter_mut(0)
605            .enumerate()
606            .for_each(|(i, v)| *v = i as f32);
607        block
608            .channel_iter_mut(1)
609            .enumerate()
610            .for_each(|(i, v)| *v = i as f32 + 10.0);
611
612        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
613        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
614        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
615        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
616    }
617
618    #[test]
619    fn test_channel_iters() {
620        let mut block = Interleaved::<f32>::new(2, 5);
621
622        let mut channels_iter = block.channels_iter();
623        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
624        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
625        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
626        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
627        assert!(channels_iter.next().is_none());
628        drop(channels_iter);
629
630        let mut channels_iter = block.channels_iter_mut();
631        channels_iter
632            .next()
633            .unwrap()
634            .enumerate()
635            .for_each(|(i, v)| *v = i as f32);
636        channels_iter
637            .next()
638            .unwrap()
639            .enumerate()
640            .for_each(|(i, v)| *v = i as f32 + 10.0);
641        assert!(channels_iter.next().is_none());
642        drop(channels_iter);
643
644        let mut channels_iter = block.channels_iter();
645        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
646        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
647        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
648        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
649        assert!(channels_iter.next().is_none());
650        drop(channels_iter);
651    }
652
653    #[test]
654    fn test_frame_iter() {
655        let mut block = Interleaved::<f32>::new(2, 5);
656
657        for i in 0..block.num_frames() {
658            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
659            assert_eq!(frame, vec![0.0, 0.0]);
660        }
661
662        for i in 0..block.num_frames() {
663            let add = i as f32 * 10.0;
664            block
665                .frame_iter_mut(i)
666                .enumerate()
667                .for_each(|(i, v)| *v = i as f32 + add);
668        }
669
670        let frame = block.frame_iter(0).copied().collect::<Vec<_>>();
671        assert_eq!(frame, vec![0.0, 1.0]);
672        let frame = block.frame_iter(1).copied().collect::<Vec<_>>();
673        assert_eq!(frame, vec![10.0, 11.0]);
674        let frame = block.frame_iter(2).copied().collect::<Vec<_>>();
675        assert_eq!(frame, vec![20.0, 21.0]);
676        let frame = block.frame_iter(3).copied().collect::<Vec<_>>();
677        assert_eq!(frame, vec![30.0, 31.0]);
678        let frame = block.frame_iter(4).copied().collect::<Vec<_>>();
679        assert_eq!(frame, vec![40.0, 41.0]);
680    }
681
682    #[test]
683    fn test_frame_iters() {
684        let mut block = Interleaved::<f32>::new(2, 5);
685        let num_frames = block.num_frames;
686        let mut frames_iter = block.frames_iter();
687        for _ in 0..num_frames {
688            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
689            assert_eq!(frame, vec![0.0, 0.0]);
690        }
691        assert!(frames_iter.next().is_none());
692        drop(frames_iter);
693
694        let mut frames_iter = block.frames_iter_mut();
695        for i in 0..num_frames {
696            let add = i as f32 * 10.0;
697            frames_iter
698                .next()
699                .unwrap()
700                .enumerate()
701                .for_each(|(i, v)| *v = i as f32 + add);
702        }
703        assert!(frames_iter.next().is_none());
704        drop(frames_iter);
705
706        let mut frames_iter = block.frames_iter();
707        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
708        assert_eq!(frame, vec![0.0, 1.0]);
709        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
710        assert_eq!(frame, vec![10.0, 11.0]);
711        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
712        assert_eq!(frame, vec![20.0, 21.0]);
713        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
714        assert_eq!(frame, vec![30.0, 31.0]);
715        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
716        assert_eq!(frame, vec![40.0, 41.0]);
717        assert!(frames_iter.next().is_none());
718    }
719
720    #[test]
721    fn test_view() {
722        let block = Interleaved::<f32>::from_block(&InterleavedView::from_slice(
723            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
724            2,
725        ));
726
727        assert!(block.as_interleaved_view().is_some());
728        assert!(block.as_planar_view().is_none());
729        assert!(block.as_sequential_view().is_none());
730
731        let view = block.as_view();
732        assert_eq!(
733            view.channel_iter(0).copied().collect::<Vec<_>>(),
734            vec![0.0, 2.0, 4.0, 6.0, 8.0]
735        );
736        assert_eq!(
737            view.channel_iter(1).copied().collect::<Vec<_>>(),
738            vec![1.0, 3.0, 5.0, 7.0, 9.0]
739        );
740    }
741
742    #[test]
743    fn test_view_mut() {
744        let mut block = Interleaved::<f32>::new(2, 5);
745        assert!(block.as_interleaved_view_mut().is_some());
746        assert!(block.as_planar_view_mut().is_none());
747        assert!(block.as_sequential_view_mut().is_none());
748
749        {
750            let mut view = block.as_view_mut();
751            view.channel_iter_mut(0)
752                .enumerate()
753                .for_each(|(i, v)| *v = i as f32);
754            view.channel_iter_mut(1)
755                .enumerate()
756                .for_each(|(i, v)| *v = i as f32 + 10.0);
757        }
758
759        assert_eq!(
760            block.channel_iter(0).copied().collect::<Vec<_>>(),
761            vec![0.0, 1.0, 2.0, 3.0, 4.0]
762        );
763        assert_eq!(
764            block.channel_iter(1).copied().collect::<Vec<_>>(),
765            vec![10.0, 11.0, 12.0, 13.0, 14.0]
766        );
767    }
768
769    #[test]
770    fn test_from_slice() {
771        let block = Interleaved::<f32>::from_block(&InterleavedView::from_slice(
772            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
773            2,
774        ));
775        assert_eq!(block.num_channels(), 2);
776        assert_eq!(block.num_channels_allocated(), 2);
777        assert_eq!(block.num_frames(), 5);
778        assert_eq!(block.num_frames_allocated(), 5);
779        assert_eq!(
780            block.channel_iter(0).copied().collect::<Vec<_>>(),
781            vec![0.0, 2.0, 4.0, 6.0, 8.0]
782        );
783        assert_eq!(
784            block.channel_iter(1).copied().collect::<Vec<_>>(),
785            vec![1.0, 3.0, 5.0, 7.0, 9.0]
786        );
787        assert_eq!(
788            block.frame_iter(0).copied().collect::<Vec<_>>(),
789            vec![0.0, 1.0]
790        );
791        assert_eq!(
792            block.frame_iter(1).copied().collect::<Vec<_>>(),
793            vec![2.0, 3.0]
794        );
795        assert_eq!(
796            block.frame_iter(2).copied().collect::<Vec<_>>(),
797            vec![4.0, 5.0]
798        );
799        assert_eq!(
800            block.frame_iter(3).copied().collect::<Vec<_>>(),
801            vec![6.0, 7.0]
802        );
803        assert_eq!(
804            block.frame_iter(4).copied().collect::<Vec<_>>(),
805            vec![8.0, 9.0]
806        );
807    }
808
809    #[test]
810    fn test_from_block() {
811        let block = SequentialView::<f32>::from_slice(
812            &[0.0, 2.0, 4.0, 6.0, 8.0, 1.0, 3.0, 5.0, 7.0, 9.0],
813            2,
814        );
815
816        let block = Interleaved::<f32>::from_block(&block);
817
818        assert_eq!(
819            block.channel_iter(0).copied().collect::<Vec<_>>(),
820            vec![0.0, 2.0, 4.0, 6.0, 8.0]
821        );
822        assert_eq!(
823            block.channel_iter(1).copied().collect::<Vec<_>>(),
824            vec![1.0, 3.0, 5.0, 7.0, 9.0]
825        );
826    }
827
828    #[test]
829    fn test_resize() {
830        let mut block = Interleaved::<f32>::new(3, 10);
831        assert_eq!(block.num_channels(), 3);
832        assert_eq!(block.num_frames(), 10);
833        assert_eq!(block.num_channels_allocated(), 3);
834        assert_eq!(block.num_frames_allocated(), 10);
835
836        for i in 0..block.num_channels() {
837            assert_eq!(block.channel_iter(i).count(), 10);
838            assert_eq!(block.channel_iter_mut(i).count(), 10);
839        }
840        for i in 0..block.num_frames() {
841            assert_eq!(block.frame_iter(i).count(), 3);
842            assert_eq!(block.frame_iter_mut(i).count(), 3);
843        }
844
845        block.set_visible(2, 5);
846
847        assert_eq!(block.num_channels(), 2);
848        assert_eq!(block.num_frames(), 5);
849        assert_eq!(block.num_channels_allocated(), 3);
850        assert_eq!(block.num_frames_allocated(), 10);
851
852        for i in 0..block.num_channels() {
853            assert_eq!(block.channel_iter(i).count(), 5);
854            assert_eq!(block.channel_iter_mut(i).count(), 5);
855        }
856        for i in 0..block.num_frames() {
857            assert_eq!(block.frame_iter(i).count(), 2);
858            assert_eq!(block.frame_iter_mut(i).count(), 2);
859        }
860    }
861
862    #[test]
863    #[should_panic]
864    #[no_sanitize_realtime]
865    fn test_wrong_resize_channels() {
866        let mut block = Interleaved::<f32>::new(2, 10);
867        block.set_visible(3, 10);
868    }
869
870    #[test]
871    #[should_panic]
872    #[no_sanitize_realtime]
873    fn test_wrong_resize_frames() {
874        let mut block = Interleaved::<f32>::new(2, 10);
875        block.set_visible(2, 11);
876    }
877
878    #[test]
879    #[should_panic]
880    #[no_sanitize_realtime]
881    fn test_wrong_channel() {
882        let mut block = Interleaved::<f32>::new(2, 10);
883        block.set_visible(1, 10);
884        let _ = block.channel_iter(1);
885    }
886
887    #[test]
888    #[should_panic]
889    #[no_sanitize_realtime]
890    fn test_wrong_frame() {
891        let mut block = Interleaved::<f32>::new(2, 10);
892        block.set_visible(2, 5);
893        let _ = block.frame_iter(5);
894    }
895
896    #[test]
897    #[should_panic]
898    #[no_sanitize_realtime]
899    fn test_wrong_channel_mut() {
900        let mut block = Interleaved::<f32>::new(2, 10);
901        block.set_visible(1, 10);
902        let _ = block.channel_iter_mut(1);
903    }
904
905    #[test]
906    #[should_panic]
907    #[no_sanitize_realtime]
908    fn test_wrong_frame_mut() {
909        let mut block = Interleaved::<f32>::new(2, 10);
910        block.set_visible(2, 5);
911        let _ = block.frame_iter_mut(5);
912    }
913
914    #[test]
915    #[should_panic]
916    #[no_sanitize_realtime]
917    fn test_slice_out_of_bounds() {
918        let mut block = Interleaved::<f32>::new(3, 6);
919        block.set_visible(2, 5);
920        block.frame(5);
921    }
922
923    #[test]
924    #[should_panic]
925    #[no_sanitize_realtime]
926    fn test_slice_out_of_bounds_mut() {
927        let mut block = Interleaved::<f32>::new(3, 6);
928        block.set_visible(2, 5);
929        block.frame_mut(5);
930    }
931}