audio_blocks/interleaved/
view_mut.rs

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