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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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(
455        &mut self,
456    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S> + ExactSizeIterator>
457    {
458        let num_channels = self.num_channels as usize;
459        let num_channels_allocated = self.num_channels_allocated as usize;
460        self.data
461            .chunks_mut(num_channels_allocated)
462            .take(self.num_frames)
463            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_channels))
464    }
465
466    #[nonblocking]
467    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
468        self.view_mut()
469    }
470
471    #[nonblocking]
472    fn as_interleaved_view_mut(&mut self) -> Option<AudioBlockInterleavedViewMut<'_, S>> {
473        Some(self.view_mut())
474    }
475}
476
477impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockInterleaved<S> {
478    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
479        writeln!(f, "AudioBlockInterleaved {{")?;
480        writeln!(f, "  num_channels: {}", self.num_channels)?;
481        writeln!(f, "  num_frames: {}", self.num_frames)?;
482        writeln!(
483            f,
484            "  num_channels_allocated: {}",
485            self.num_channels_allocated
486        )?;
487        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
488        writeln!(f, "  frames:")?;
489
490        for (i, frame) in self.frames().enumerate() {
491            writeln!(f, "    {}: {:?}", i, frame)?;
492        }
493
494        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
495        writeln!(f, "}}")?;
496
497        Ok(())
498    }
499}
500
501#[cfg(test)]
502mod tests {
503    use super::*;
504    use crate::sequential::AudioBlockSequentialView;
505    use rtsan_standalone::no_sanitize_realtime;
506
507    #[test]
508    fn test_member_functions() {
509        let mut block = AudioBlockInterleaved::<f32>::new(4, 3);
510        block.frame_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
511        block.frame_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
512
513        block.set_visible(3, 2);
514
515        // single frame
516        assert_eq!(block.frame(0), &[0.0, 1.0, 2.0]);
517        assert_eq!(block.frame(1), &[4.0, 5.0, 6.0]);
518
519        assert_eq!(block.frame_mut(0), &[0.0, 1.0, 2.0]);
520        assert_eq!(block.frame_mut(1), &[4.0, 5.0, 6.0]);
521
522        // all frames
523        let mut frames = block.frames();
524        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
525        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
526        assert_eq!(frames.next(), None);
527        drop(frames);
528
529        let mut frames = block.frames_mut();
530        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
531        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
532        assert_eq!(frames.next(), None);
533        drop(frames);
534
535        // raw data
536        assert_eq!(
537            block.raw_data(),
538            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
539        );
540
541        assert_eq!(
542            block.raw_data_mut(),
543            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
544        );
545
546        // views
547        let view = block.view();
548        assert_eq!(view.num_channels(), block.num_channels());
549        assert_eq!(view.num_frames(), block.num_frames());
550        assert_eq!(
551            view.num_channels_allocated(),
552            block.num_channels_allocated()
553        );
554        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
555        assert_eq!(view.raw_data(), block.raw_data());
556
557        let num_channels = block.num_channels();
558        let num_frames = block.num_frames();
559        let num_channels_allocated = block.num_channels_allocated();
560        let num_frames_allocated = block.num_frames_allocated();
561        let data = block.raw_data().to_vec();
562        let view = block.view_mut();
563        assert_eq!(view.num_channels(), num_channels);
564        assert_eq!(view.num_frames(), num_frames);
565        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
566        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
567        assert_eq!(view.raw_data(), &data);
568    }
569
570    #[test]
571    fn test_samples() {
572        let mut block = AudioBlockInterleaved::<f32>::new(2, 5);
573
574        let num_frames = block.num_frames();
575        for ch in 0..block.num_channels() {
576            for f in 0..block.num_frames() {
577                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
578            }
579        }
580
581        for ch in 0..block.num_channels() {
582            for f in 0..block.num_frames() {
583                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
584            }
585        }
586
587        assert_eq!(
588            block.raw_data(),
589            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
590        );
591    }
592
593    #[test]
594    fn test_channel_iter() {
595        let mut block = AudioBlockInterleaved::<f32>::new(2, 5);
596
597        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
598        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
599        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
600        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
601
602        block
603            .channel_iter_mut(0)
604            .enumerate()
605            .for_each(|(i, v)| *v = i as f32);
606        block
607            .channel_iter_mut(1)
608            .enumerate()
609            .for_each(|(i, v)| *v = i as f32 + 10.0);
610
611        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
612        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
613        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
614        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
615    }
616
617    #[test]
618    fn test_channel_iters() {
619        let mut block = AudioBlockInterleaved::<f32>::new(2, 5);
620
621        let mut channels_iter = block.channels_iter();
622        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
623        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
624        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
625        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
626        assert!(channels_iter.next().is_none());
627        drop(channels_iter);
628
629        let mut channels_iter = block.channels_iter_mut();
630        channels_iter
631            .next()
632            .unwrap()
633            .enumerate()
634            .for_each(|(i, v)| *v = i as f32);
635        channels_iter
636            .next()
637            .unwrap()
638            .enumerate()
639            .for_each(|(i, v)| *v = i as f32 + 10.0);
640        assert!(channels_iter.next().is_none());
641        drop(channels_iter);
642
643        let mut channels_iter = block.channels_iter();
644        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
645        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
646        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
647        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
648        assert!(channels_iter.next().is_none());
649        drop(channels_iter);
650    }
651
652    #[test]
653    fn test_frame_iter() {
654        let mut block = AudioBlockInterleaved::<f32>::new(2, 5);
655
656        for i in 0..block.num_frames() {
657            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
658            assert_eq!(frame, vec![0.0, 0.0]);
659        }
660
661        for i in 0..block.num_frames() {
662            let add = i as f32 * 10.0;
663            block
664                .frame_iter_mut(i)
665                .enumerate()
666                .for_each(|(i, v)| *v = i as f32 + add);
667        }
668
669        let frame = block.frame_iter(0).copied().collect::<Vec<_>>();
670        assert_eq!(frame, vec![0.0, 1.0]);
671        let frame = block.frame_iter(1).copied().collect::<Vec<_>>();
672        assert_eq!(frame, vec![10.0, 11.0]);
673        let frame = block.frame_iter(2).copied().collect::<Vec<_>>();
674        assert_eq!(frame, vec![20.0, 21.0]);
675        let frame = block.frame_iter(3).copied().collect::<Vec<_>>();
676        assert_eq!(frame, vec![30.0, 31.0]);
677        let frame = block.frame_iter(4).copied().collect::<Vec<_>>();
678        assert_eq!(frame, vec![40.0, 41.0]);
679    }
680
681    #[test]
682    fn test_frame_iters() {
683        let mut block = AudioBlockInterleaved::<f32>::new(2, 5);
684        let num_frames = block.num_frames;
685        let mut frames_iter = block.frames_iter();
686        for _ in 0..num_frames {
687            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
688            assert_eq!(frame, vec![0.0, 0.0]);
689        }
690        assert!(frames_iter.next().is_none());
691        drop(frames_iter);
692
693        let mut frames_iter = block.frames_iter_mut();
694        for i in 0..num_frames {
695            let add = i as f32 * 10.0;
696            frames_iter
697                .next()
698                .unwrap()
699                .enumerate()
700                .for_each(|(i, v)| *v = i as f32 + add);
701        }
702        assert!(frames_iter.next().is_none());
703        drop(frames_iter);
704
705        let mut frames_iter = block.frames_iter();
706        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
707        assert_eq!(frame, vec![0.0, 1.0]);
708        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
709        assert_eq!(frame, vec![10.0, 11.0]);
710        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
711        assert_eq!(frame, vec![20.0, 21.0]);
712        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
713        assert_eq!(frame, vec![30.0, 31.0]);
714        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
715        assert_eq!(frame, vec![40.0, 41.0]);
716        assert!(frames_iter.next().is_none());
717    }
718
719    #[test]
720    fn test_view() {
721        let block =
722            AudioBlockInterleaved::<f32>::from_block(&AudioBlockInterleavedView::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 = AudioBlockInterleaved::<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 =
772            AudioBlockInterleaved::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
773                &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
774                2,
775            ));
776        assert_eq!(block.num_channels(), 2);
777        assert_eq!(block.num_channels_allocated(), 2);
778        assert_eq!(block.num_frames(), 5);
779        assert_eq!(block.num_frames_allocated(), 5);
780        assert_eq!(
781            block.channel_iter(0).copied().collect::<Vec<_>>(),
782            vec![0.0, 2.0, 4.0, 6.0, 8.0]
783        );
784        assert_eq!(
785            block.channel_iter(1).copied().collect::<Vec<_>>(),
786            vec![1.0, 3.0, 5.0, 7.0, 9.0]
787        );
788        assert_eq!(
789            block.frame_iter(0).copied().collect::<Vec<_>>(),
790            vec![0.0, 1.0]
791        );
792        assert_eq!(
793            block.frame_iter(1).copied().collect::<Vec<_>>(),
794            vec![2.0, 3.0]
795        );
796        assert_eq!(
797            block.frame_iter(2).copied().collect::<Vec<_>>(),
798            vec![4.0, 5.0]
799        );
800        assert_eq!(
801            block.frame_iter(3).copied().collect::<Vec<_>>(),
802            vec![6.0, 7.0]
803        );
804        assert_eq!(
805            block.frame_iter(4).copied().collect::<Vec<_>>(),
806            vec![8.0, 9.0]
807        );
808    }
809
810    #[test]
811    fn test_from_block() {
812        let block = AudioBlockSequentialView::<f32>::from_slice(
813            &[0.0, 2.0, 4.0, 6.0, 8.0, 1.0, 3.0, 5.0, 7.0, 9.0],
814            2,
815        );
816
817        let block = AudioBlockInterleaved::<f32>::from_block(&block);
818
819        assert_eq!(
820            block.channel_iter(0).copied().collect::<Vec<_>>(),
821            vec![0.0, 2.0, 4.0, 6.0, 8.0]
822        );
823        assert_eq!(
824            block.channel_iter(1).copied().collect::<Vec<_>>(),
825            vec![1.0, 3.0, 5.0, 7.0, 9.0]
826        );
827    }
828
829    #[test]
830    fn test_resize() {
831        let mut block = AudioBlockInterleaved::<f32>::new(3, 10);
832        assert_eq!(block.num_channels(), 3);
833        assert_eq!(block.num_frames(), 10);
834        assert_eq!(block.num_channels_allocated(), 3);
835        assert_eq!(block.num_frames_allocated(), 10);
836
837        for i in 0..block.num_channels() {
838            assert_eq!(block.channel_iter(i).count(), 10);
839            assert_eq!(block.channel_iter_mut(i).count(), 10);
840        }
841        for i in 0..block.num_frames() {
842            assert_eq!(block.frame_iter(i).count(), 3);
843            assert_eq!(block.frame_iter_mut(i).count(), 3);
844        }
845
846        block.set_visible(2, 5);
847
848        assert_eq!(block.num_channels(), 2);
849        assert_eq!(block.num_frames(), 5);
850        assert_eq!(block.num_channels_allocated(), 3);
851        assert_eq!(block.num_frames_allocated(), 10);
852
853        for i in 0..block.num_channels() {
854            assert_eq!(block.channel_iter(i).count(), 5);
855            assert_eq!(block.channel_iter_mut(i).count(), 5);
856        }
857        for i in 0..block.num_frames() {
858            assert_eq!(block.frame_iter(i).count(), 2);
859            assert_eq!(block.frame_iter_mut(i).count(), 2);
860        }
861    }
862
863    #[test]
864    #[should_panic]
865    #[no_sanitize_realtime]
866    fn test_wrong_resize_channels() {
867        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
868        block.set_visible(3, 10);
869    }
870
871    #[test]
872    #[should_panic]
873    #[no_sanitize_realtime]
874    fn test_wrong_resize_frames() {
875        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
876        block.set_visible(2, 11);
877    }
878
879    #[test]
880    #[should_panic]
881    #[no_sanitize_realtime]
882    fn test_wrong_channel() {
883        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
884        block.set_visible(1, 10);
885        let _ = block.channel_iter(1);
886    }
887
888    #[test]
889    #[should_panic]
890    #[no_sanitize_realtime]
891    fn test_wrong_frame() {
892        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
893        block.set_visible(2, 5);
894        let _ = block.frame_iter(5);
895    }
896
897    #[test]
898    #[should_panic]
899    #[no_sanitize_realtime]
900    fn test_wrong_channel_mut() {
901        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
902        block.set_visible(1, 10);
903        let _ = block.channel_iter_mut(1);
904    }
905
906    #[test]
907    #[should_panic]
908    #[no_sanitize_realtime]
909    fn test_wrong_frame_mut() {
910        let mut block = AudioBlockInterleaved::<f32>::new(2, 10);
911        block.set_visible(2, 5);
912        let _ = block.frame_iter_mut(5);
913    }
914
915    #[test]
916    #[should_panic]
917    #[no_sanitize_realtime]
918    fn test_slice_out_of_bounds() {
919        let mut block = AudioBlockInterleaved::<f32>::new(3, 6);
920        block.set_visible(2, 5);
921        block.frame(5);
922    }
923
924    #[test]
925    #[should_panic]
926    #[no_sanitize_realtime]
927    fn test_slice_out_of_bounds_mut() {
928        let mut block = AudioBlockInterleaved::<f32>::new(3, 6);
929        block.set_visible(2, 5);
930        block.frame_mut(5);
931    }
932}