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 Iterator<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 Iterator<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 Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
436        let num_channels = self.num_channels as usize;
437        let num_channels_allocated = self.num_channels_allocated as usize;
438        self.data
439            .chunks_mut(num_channels_allocated)
440            .take(self.num_frames)
441            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_channels))
442    }
443
444    #[nonblocking]
445    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
446        self.view_mut()
447    }
448
449    #[nonblocking]
450    fn as_interleaved_view_mut(&mut self) -> Option<AudioBlockInterleavedViewMut<'_, S>> {
451        Some(self.view_mut())
452    }
453}
454
455impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockInterleavedViewMut<'_, S> {
456    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
457        writeln!(f, "AudioBlockInterleavedViewMut {{")?;
458        writeln!(f, "  num_channels: {}", self.num_channels)?;
459        writeln!(f, "  num_frames: {}", self.num_frames)?;
460        writeln!(
461            f,
462            "  num_channels_allocated: {}",
463            self.num_channels_allocated
464        )?;
465        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
466        writeln!(f, "  frames:")?;
467
468        for (i, frame) in self.frames().enumerate() {
469            writeln!(f, "    {}: {:?}", i, frame)?;
470        }
471
472        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
473        writeln!(f, "}}")?;
474
475        Ok(())
476    }
477}
478
479#[cfg(test)]
480mod tests {
481    use super::*;
482    use rtsan_standalone::no_sanitize_realtime;
483
484    #[test]
485    fn test_member_functions() {
486        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];
487        let mut block =
488            AudioBlockInterleavedViewMut::<f32>::from_slice_limited(&mut data, 3, 2, 4, 3);
489
490        block.set_visible(3, 2);
491
492        // single frame
493        assert_eq!(block.frame(0), &[0.0, 1.0, 2.0]);
494        assert_eq!(block.frame(1), &[4.0, 5.0, 6.0]);
495
496        assert_eq!(block.frame_mut(0), &[0.0, 1.0, 2.0]);
497        assert_eq!(block.frame_mut(1), &[4.0, 5.0, 6.0]);
498
499        // all frames
500        let mut frames = block.frames();
501        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
502        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
503        assert_eq!(frames.next(), None);
504        drop(frames);
505
506        let mut frames = block.frames_mut();
507        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
508        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
509        assert_eq!(frames.next(), None);
510        drop(frames);
511
512        // raw data
513        assert_eq!(
514            block.raw_data(),
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        assert_eq!(
519            block.raw_data_mut(),
520            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
521        );
522
523        // views
524        let view = block.view();
525        assert_eq!(view.num_channels(), block.num_channels());
526        assert_eq!(view.num_frames(), block.num_frames());
527        assert_eq!(
528            view.num_channels_allocated(),
529            block.num_channels_allocated()
530        );
531        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
532        assert_eq!(view.raw_data(), block.raw_data());
533
534        let num_channels = block.num_channels();
535        let num_frames = block.num_frames();
536        let num_channels_allocated = block.num_channels_allocated();
537        let num_frames_allocated = block.num_frames_allocated();
538        let data = block.raw_data().to_vec();
539        let view = block.view_mut();
540        assert_eq!(view.num_channels(), num_channels);
541        assert_eq!(view.num_frames(), num_frames);
542        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
543        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
544        assert_eq!(view.raw_data(), &data);
545    }
546
547    #[test]
548    fn test_samples() {
549        let mut data = vec![0.0; 10];
550        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
551
552        let num_frames = block.num_frames();
553        for ch in 0..block.num_channels() {
554            for f in 0..block.num_frames() {
555                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
556            }
557        }
558
559        for ch in 0..block.num_channels() {
560            for f in 0..block.num_frames() {
561                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
562            }
563        }
564
565        assert_eq!(
566            block.raw_data(),
567            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
568        );
569    }
570
571    #[test]
572    fn test_channel_iter() {
573        let mut data = vec![0.0; 10];
574        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
575
576        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
577        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
578        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
579        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
580
581        block
582            .channel_iter_mut(0)
583            .enumerate()
584            .for_each(|(i, v)| *v = i as f32);
585        block
586            .channel_iter_mut(1)
587            .enumerate()
588            .for_each(|(i, v)| *v = i as f32 + 10.0);
589
590        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
591        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
592        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
593        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
594    }
595
596    #[test]
597    fn test_channel_iters() {
598        let mut data = vec![0.0; 10];
599        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
600
601        let mut channels_iter = block.channels_iter();
602        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
603        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
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        assert!(channels_iter.next().is_none());
607        drop(channels_iter);
608
609        let mut channels_iter = block.channels_iter_mut();
610        channels_iter
611            .next()
612            .unwrap()
613            .enumerate()
614            .for_each(|(i, v)| *v = i as f32);
615        channels_iter
616            .next()
617            .unwrap()
618            .enumerate()
619            .for_each(|(i, v)| *v = i as f32 + 10.0);
620        assert!(channels_iter.next().is_none());
621        drop(channels_iter);
622
623        let mut channels_iter = block.channels_iter();
624        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
625        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
626        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
627        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
628        assert!(channels_iter.next().is_none());
629        drop(channels_iter);
630    }
631
632    #[test]
633    fn test_frame_iter() {
634        let mut data = vec![0.0; 10];
635        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
636
637        for i in 0..block.num_frames() {
638            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
639            assert_eq!(frame, vec![0.0, 0.0]);
640        }
641
642        for i in 0..block.num_frames() {
643            let add = i as f32 * 10.0;
644            block
645                .frame_iter_mut(i)
646                .enumerate()
647                .for_each(|(i, v)| *v = i as f32 + add);
648        }
649
650        let frame = block.frame_iter(0).copied().collect::<Vec<_>>();
651        assert_eq!(frame, vec![0.0, 1.0]);
652        let frame = block.frame_iter(1).copied().collect::<Vec<_>>();
653        assert_eq!(frame, vec![10.0, 11.0]);
654        let frame = block.frame_iter(2).copied().collect::<Vec<_>>();
655        assert_eq!(frame, vec![20.0, 21.0]);
656        let frame = block.frame_iter(3).copied().collect::<Vec<_>>();
657        assert_eq!(frame, vec![30.0, 31.0]);
658        let frame = block.frame_iter(4).copied().collect::<Vec<_>>();
659        assert_eq!(frame, vec![40.0, 41.0]);
660    }
661
662    #[test]
663    fn test_frame_iters() {
664        let mut data = vec![0.0; 10];
665        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
666
667        let num_frames = block.num_frames;
668        let mut frames_iter = block.frames_iter();
669        for _ in 0..num_frames {
670            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
671            assert_eq!(frame, vec![0.0, 0.0]);
672        }
673        assert!(frames_iter.next().is_none());
674        drop(frames_iter);
675
676        let mut frames_iter = block.frames_iter_mut();
677        for i in 0..num_frames {
678            let add = i as f32 * 10.0;
679            frames_iter
680                .next()
681                .unwrap()
682                .enumerate()
683                .for_each(|(i, v)| *v = i as f32 + add);
684        }
685        assert!(frames_iter.next().is_none());
686        drop(frames_iter);
687
688        let mut frames_iter = block.frames_iter();
689        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
690        assert_eq!(frame, vec![0.0, 1.0]);
691        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
692        assert_eq!(frame, vec![10.0, 11.0]);
693        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
694        assert_eq!(frame, vec![20.0, 21.0]);
695        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
696        assert_eq!(frame, vec![30.0, 31.0]);
697        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
698        assert_eq!(frame, vec![40.0, 41.0]);
699        assert!(frames_iter.next().is_none());
700    }
701
702    #[test]
703    fn test_from_slice() {
704        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
705        let block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
706        assert_eq!(block.num_channels(), 2);
707        assert_eq!(block.num_channels_allocated, 2);
708        assert_eq!(block.num_frames(), 5);
709        assert_eq!(block.num_frames_allocated, 5);
710        assert_eq!(
711            block.channel_iter(0).copied().collect::<Vec<_>>(),
712            vec![0.0, 2.0, 4.0, 6.0, 8.0]
713        );
714        assert_eq!(
715            block.channel_iter(1).copied().collect::<Vec<_>>(),
716            vec![1.0, 3.0, 5.0, 7.0, 9.0]
717        );
718        assert_eq!(
719            block.frame_iter(0).copied().collect::<Vec<_>>(),
720            vec![0.0, 1.0]
721        );
722        assert_eq!(
723            block.frame_iter(1).copied().collect::<Vec<_>>(),
724            vec![2.0, 3.0]
725        );
726        assert_eq!(
727            block.frame_iter(2).copied().collect::<Vec<_>>(),
728            vec![4.0, 5.0]
729        );
730        assert_eq!(
731            block.frame_iter(3).copied().collect::<Vec<_>>(),
732            vec![6.0, 7.0]
733        );
734        assert_eq!(
735            block.frame_iter(4).copied().collect::<Vec<_>>(),
736            vec![8.0, 9.0]
737        );
738    }
739
740    #[test]
741    fn test_view() {
742        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
743        let block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
744
745        assert!(block.as_interleaved_view().is_some());
746        assert!(block.as_planar_view().is_none());
747        assert!(block.as_sequential_view().is_none());
748
749        let view = block.as_view();
750
751        assert_eq!(
752            view.channel_iter(0).copied().collect::<Vec<_>>(),
753            vec![0.0, 2.0, 4.0, 6.0, 8.0]
754        );
755        assert_eq!(
756            view.channel_iter(1).copied().collect::<Vec<_>>(),
757            vec![1.0, 3.0, 5.0, 7.0, 9.0]
758        );
759    }
760
761    #[test]
762    fn test_view_mut() {
763        let mut data = vec![0.0; 10];
764        let mut block = AudioBlockInterleavedViewMut::<f32>::from_slice(&mut data, 2);
765
766        assert!(block.as_interleaved_view_mut().is_some());
767        assert!(block.as_planar_view_mut().is_none());
768        assert!(block.as_sequential_view_mut().is_none());
769
770        {
771            let mut view = block.as_view_mut();
772            view.channel_iter_mut(0)
773                .enumerate()
774                .for_each(|(i, v)| *v = i as f32);
775            view.channel_iter_mut(1)
776                .enumerate()
777                .for_each(|(i, v)| *v = i as f32 + 10.0);
778        }
779
780        assert_eq!(
781            block.channel_iter(0).copied().collect::<Vec<_>>(),
782            vec![0.0, 1.0, 2.0, 3.0, 4.0]
783        );
784        assert_eq!(
785            block.channel_iter(1).copied().collect::<Vec<_>>(),
786            vec![10.0, 11.0, 12.0, 13.0, 14.0]
787        );
788    }
789
790    #[test]
791    fn test_limited() {
792        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];
793
794        let mut block = AudioBlockInterleavedViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
795
796        assert_eq!(block.num_channels(), 2);
797        assert_eq!(block.num_frames(), 3);
798        assert_eq!(block.num_channels_allocated, 3);
799        assert_eq!(block.num_frames_allocated, 4);
800
801        for i in 0..block.num_channels() {
802            assert_eq!(block.channel_iter(i).count(), 3);
803            assert_eq!(block.channel_iter_mut(i).count(), 3);
804        }
805        for i in 0..block.num_frames() {
806            assert_eq!(block.frame_iter(i).count(), 2);
807            assert_eq!(block.frame_iter_mut(i).count(), 2);
808        }
809    }
810
811    #[test]
812    fn test_from_ptr() {
813        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
814        let block =
815            unsafe { AudioBlockInterleavedViewMut::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
816        assert_eq!(block.num_channels(), 2);
817        assert_eq!(block.num_channels_allocated, 2);
818        assert_eq!(block.num_frames(), 5);
819        assert_eq!(block.num_frames_allocated, 5);
820        assert_eq!(
821            block.channel_iter(0).copied().collect::<Vec<_>>(),
822            vec![0.0, 2.0, 4.0, 6.0, 8.0]
823        );
824        assert_eq!(
825            block.channel_iter(1).copied().collect::<Vec<_>>(),
826            vec![1.0, 3.0, 5.0, 7.0, 9.0]
827        );
828        assert_eq!(
829            block.frame_iter(0).copied().collect::<Vec<_>>(),
830            vec![0.0, 1.0]
831        );
832        assert_eq!(
833            block.frame_iter(1).copied().collect::<Vec<_>>(),
834            vec![2.0, 3.0]
835        );
836        assert_eq!(
837            block.frame_iter(2).copied().collect::<Vec<_>>(),
838            vec![4.0, 5.0]
839        );
840        assert_eq!(
841            block.frame_iter(3).copied().collect::<Vec<_>>(),
842            vec![6.0, 7.0]
843        );
844        assert_eq!(
845            block.frame_iter(4).copied().collect::<Vec<_>>(),
846            vec![8.0, 9.0]
847        );
848    }
849
850    #[test]
851    fn test_from_ptr_limited() {
852        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];
853
854        let mut block = unsafe {
855            AudioBlockInterleavedViewMut::from_ptr_limited(data.as_mut_ptr(), 2, 3, 3, 4)
856        };
857
858        assert_eq!(block.num_channels(), 2);
859        assert_eq!(block.num_frames(), 3);
860        assert_eq!(block.num_channels_allocated, 3);
861        assert_eq!(block.num_frames_allocated, 4);
862
863        for i in 0..block.num_channels() {
864            assert_eq!(block.channel_iter(i).count(), 3);
865            assert_eq!(block.channel_iter_mut(i).count(), 3);
866        }
867        for i in 0..block.num_frames() {
868            assert_eq!(block.frame_iter(i).count(), 2);
869            assert_eq!(block.frame_iter_mut(i).count(), 2);
870        }
871    }
872
873    #[test]
874    #[should_panic]
875    #[no_sanitize_realtime]
876    fn test_slice_out_of_bounds() {
877        let mut data = [0.0; 12];
878        let mut block =
879            AudioBlockInterleavedViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
880        block.set_visible(2, 5);
881        block.frame(5);
882    }
883
884    #[test]
885    #[should_panic]
886    #[no_sanitize_realtime]
887    fn test_slice_out_of_bounds_mut() {
888        let mut data = [0.0; 12];
889        let mut block =
890            AudioBlockInterleavedViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
891        block.set_visible(2, 5);
892        block.frame(5);
893    }
894}