Skip to main content

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