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