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::InterleavedView;
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 = InterleavedViewMut::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 InterleavedViewMut<'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> InterleavedViewMut<'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) -> InterleavedView<'_, S> {
227        InterleavedView::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) -> InterleavedViewMut<'_, S> {
238        InterleavedViewMut::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 InterleavedViewMut<'_, 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<InterleavedView<'_, S>> {
355        Some(self.view())
356    }
357}
358
359impl<S: Sample> AudioBlockMut<S> for InterleavedViewMut<'_, 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<InterleavedViewMut<'_, S>> {
453        Some(self.view_mut())
454    }
455}
456
457impl<S: Sample + core::fmt::Debug> core::fmt::Debug for InterleavedViewMut<'_, S> {
458    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
459        writeln!(f, "audio_blocks::InterleavedViewMut {{")?;
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 = InterleavedViewMut::<f32>::from_slice_limited(&mut data, 3, 2, 4, 3);
490
491        block.set_visible(3, 2);
492
493        // single frame
494        assert_eq!(block.frame(0), &[0.0, 1.0, 2.0]);
495        assert_eq!(block.frame(1), &[4.0, 5.0, 6.0]);
496
497        assert_eq!(block.frame_mut(0), &[0.0, 1.0, 2.0]);
498        assert_eq!(block.frame_mut(1), &[4.0, 5.0, 6.0]);
499
500        // all frames
501        let mut frames = block.frames();
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        let mut frames = block.frames_mut();
508        assert_eq!(frames.next().unwrap(), &[0.0, 1.0, 2.0]);
509        assert_eq!(frames.next().unwrap(), &[4.0, 5.0, 6.0]);
510        assert_eq!(frames.next(), None);
511        drop(frames);
512
513        // raw data
514        assert_eq!(
515            block.raw_data(),
516            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
517        );
518
519        assert_eq!(
520            block.raw_data_mut(),
521            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
522        );
523
524        // views
525        let view = block.view();
526        assert_eq!(view.num_channels(), block.num_channels());
527        assert_eq!(view.num_frames(), block.num_frames());
528        assert_eq!(
529            view.num_channels_allocated(),
530            block.num_channels_allocated()
531        );
532        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
533        assert_eq!(view.raw_data(), block.raw_data());
534
535        let num_channels = block.num_channels();
536        let num_frames = block.num_frames();
537        let num_channels_allocated = block.num_channels_allocated();
538        let num_frames_allocated = block.num_frames_allocated();
539        let data = block.raw_data().to_vec();
540        let view = block.view_mut();
541        assert_eq!(view.num_channels(), num_channels);
542        assert_eq!(view.num_frames(), num_frames);
543        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
544        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
545        assert_eq!(view.raw_data(), &data);
546    }
547
548    #[test]
549    fn test_samples() {
550        let mut data = vec![0.0; 10];
551        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
552
553        let num_frames = block.num_frames();
554        for ch in 0..block.num_channels() {
555            for f in 0..block.num_frames() {
556                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
557            }
558        }
559
560        for ch in 0..block.num_channels() {
561            for f in 0..block.num_frames() {
562                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
563            }
564        }
565
566        assert_eq!(
567            block.raw_data(),
568            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
569        );
570    }
571
572    #[test]
573    fn test_channel_iter() {
574        let mut data = vec![0.0; 10];
575        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
576
577        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
578        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
579        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
580        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
581
582        block
583            .channel_iter_mut(0)
584            .enumerate()
585            .for_each(|(i, v)| *v = i as f32);
586        block
587            .channel_iter_mut(1)
588            .enumerate()
589            .for_each(|(i, v)| *v = i as f32 + 10.0);
590
591        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
592        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
593        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
594        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
595    }
596
597    #[test]
598    fn test_channel_iters() {
599        let mut data = vec![0.0; 10];
600        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
601
602        let mut channels_iter = block.channels_iter();
603        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
604        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
605        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
606        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
607        assert!(channels_iter.next().is_none());
608        drop(channels_iter);
609
610        let mut channels_iter = block.channels_iter_mut();
611        channels_iter
612            .next()
613            .unwrap()
614            .enumerate()
615            .for_each(|(i, v)| *v = i as f32);
616        channels_iter
617            .next()
618            .unwrap()
619            .enumerate()
620            .for_each(|(i, v)| *v = i as f32 + 10.0);
621        assert!(channels_iter.next().is_none());
622        drop(channels_iter);
623
624        let mut channels_iter = block.channels_iter();
625        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
626        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
627        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
628        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
629        assert!(channels_iter.next().is_none());
630        drop(channels_iter);
631    }
632
633    #[test]
634    fn test_frame_iter() {
635        let mut data = vec![0.0; 10];
636        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
637
638        for i in 0..block.num_frames() {
639            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
640            assert_eq!(frame, vec![0.0, 0.0]);
641        }
642
643        for i in 0..block.num_frames() {
644            let add = i as f32 * 10.0;
645            block
646                .frame_iter_mut(i)
647                .enumerate()
648                .for_each(|(i, v)| *v = i as f32 + add);
649        }
650
651        let frame = block.frame_iter(0).copied().collect::<Vec<_>>();
652        assert_eq!(frame, vec![0.0, 1.0]);
653        let frame = block.frame_iter(1).copied().collect::<Vec<_>>();
654        assert_eq!(frame, vec![10.0, 11.0]);
655        let frame = block.frame_iter(2).copied().collect::<Vec<_>>();
656        assert_eq!(frame, vec![20.0, 21.0]);
657        let frame = block.frame_iter(3).copied().collect::<Vec<_>>();
658        assert_eq!(frame, vec![30.0, 31.0]);
659        let frame = block.frame_iter(4).copied().collect::<Vec<_>>();
660        assert_eq!(frame, vec![40.0, 41.0]);
661    }
662
663    #[test]
664    fn test_frame_iters() {
665        let mut data = vec![0.0; 10];
666        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
667
668        let num_frames = block.num_frames;
669        let mut frames_iter = block.frames_iter();
670        for _ in 0..num_frames {
671            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
672            assert_eq!(frame, vec![0.0, 0.0]);
673        }
674        assert!(frames_iter.next().is_none());
675        drop(frames_iter);
676
677        let mut frames_iter = block.frames_iter_mut();
678        for i in 0..num_frames {
679            let add = i as f32 * 10.0;
680            frames_iter
681                .next()
682                .unwrap()
683                .enumerate()
684                .for_each(|(i, v)| *v = i as f32 + add);
685        }
686        assert!(frames_iter.next().is_none());
687        drop(frames_iter);
688
689        let mut frames_iter = block.frames_iter();
690        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
691        assert_eq!(frame, vec![0.0, 1.0]);
692        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
693        assert_eq!(frame, vec![10.0, 11.0]);
694        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
695        assert_eq!(frame, vec![20.0, 21.0]);
696        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
697        assert_eq!(frame, vec![30.0, 31.0]);
698        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
699        assert_eq!(frame, vec![40.0, 41.0]);
700        assert!(frames_iter.next().is_none());
701    }
702
703    #[test]
704    fn test_from_slice() {
705        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
706        let block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
707        assert_eq!(block.num_channels(), 2);
708        assert_eq!(block.num_channels_allocated, 2);
709        assert_eq!(block.num_frames(), 5);
710        assert_eq!(block.num_frames_allocated, 5);
711        assert_eq!(
712            block.channel_iter(0).copied().collect::<Vec<_>>(),
713            vec![0.0, 2.0, 4.0, 6.0, 8.0]
714        );
715        assert_eq!(
716            block.channel_iter(1).copied().collect::<Vec<_>>(),
717            vec![1.0, 3.0, 5.0, 7.0, 9.0]
718        );
719        assert_eq!(
720            block.frame_iter(0).copied().collect::<Vec<_>>(),
721            vec![0.0, 1.0]
722        );
723        assert_eq!(
724            block.frame_iter(1).copied().collect::<Vec<_>>(),
725            vec![2.0, 3.0]
726        );
727        assert_eq!(
728            block.frame_iter(2).copied().collect::<Vec<_>>(),
729            vec![4.0, 5.0]
730        );
731        assert_eq!(
732            block.frame_iter(3).copied().collect::<Vec<_>>(),
733            vec![6.0, 7.0]
734        );
735        assert_eq!(
736            block.frame_iter(4).copied().collect::<Vec<_>>(),
737            vec![8.0, 9.0]
738        );
739    }
740
741    #[test]
742    fn test_view() {
743        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
744        let block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
745
746        assert!(block.as_interleaved_view().is_some());
747        assert!(block.as_planar_view().is_none());
748        assert!(block.as_sequential_view().is_none());
749
750        let view = block.as_view();
751
752        assert_eq!(
753            view.channel_iter(0).copied().collect::<Vec<_>>(),
754            vec![0.0, 2.0, 4.0, 6.0, 8.0]
755        );
756        assert_eq!(
757            view.channel_iter(1).copied().collect::<Vec<_>>(),
758            vec![1.0, 3.0, 5.0, 7.0, 9.0]
759        );
760    }
761
762    #[test]
763    fn test_view_mut() {
764        let mut data = vec![0.0; 10];
765        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2);
766
767        assert!(block.as_interleaved_view_mut().is_some());
768        assert!(block.as_planar_view_mut().is_none());
769        assert!(block.as_sequential_view_mut().is_none());
770
771        {
772            let mut view = block.as_view_mut();
773            view.channel_iter_mut(0)
774                .enumerate()
775                .for_each(|(i, v)| *v = i as f32);
776            view.channel_iter_mut(1)
777                .enumerate()
778                .for_each(|(i, v)| *v = i as f32 + 10.0);
779        }
780
781        assert_eq!(
782            block.channel_iter(0).copied().collect::<Vec<_>>(),
783            vec![0.0, 1.0, 2.0, 3.0, 4.0]
784        );
785        assert_eq!(
786            block.channel_iter(1).copied().collect::<Vec<_>>(),
787            vec![10.0, 11.0, 12.0, 13.0, 14.0]
788        );
789    }
790
791    #[test]
792    fn test_limited() {
793        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];
794
795        let mut block = InterleavedViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
796
797        assert_eq!(block.num_channels(), 2);
798        assert_eq!(block.num_frames(), 3);
799        assert_eq!(block.num_channels_allocated, 3);
800        assert_eq!(block.num_frames_allocated, 4);
801
802        for i in 0..block.num_channels() {
803            assert_eq!(block.channel_iter(i).count(), 3);
804            assert_eq!(block.channel_iter_mut(i).count(), 3);
805        }
806        for i in 0..block.num_frames() {
807            assert_eq!(block.frame_iter(i).count(), 2);
808            assert_eq!(block.frame_iter_mut(i).count(), 2);
809        }
810    }
811
812    #[test]
813    fn test_from_ptr() {
814        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
815        let block = unsafe { InterleavedViewMut::<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 =
855            unsafe { InterleavedViewMut::from_ptr_limited(data.as_mut_ptr(), 2, 3, 3, 4) };
856
857        assert_eq!(block.num_channels(), 2);
858        assert_eq!(block.num_frames(), 3);
859        assert_eq!(block.num_channels_allocated, 3);
860        assert_eq!(block.num_frames_allocated, 4);
861
862        for i in 0..block.num_channels() {
863            assert_eq!(block.channel_iter(i).count(), 3);
864            assert_eq!(block.channel_iter_mut(i).count(), 3);
865        }
866        for i in 0..block.num_frames() {
867            assert_eq!(block.frame_iter(i).count(), 2);
868            assert_eq!(block.frame_iter_mut(i).count(), 2);
869        }
870    }
871
872    #[test]
873    #[should_panic]
874    #[no_sanitize_realtime]
875    fn test_slice_out_of_bounds() {
876        let mut data = [0.0; 12];
877        let mut block = InterleavedViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
878        block.set_visible(2, 5);
879        block.frame(5);
880    }
881
882    #[test]
883    #[should_panic]
884    #[no_sanitize_realtime]
885    fn test_slice_out_of_bounds_mut() {
886        let mut data = [0.0; 12];
887        let mut block = InterleavedViewMut::<f32>::from_slice_limited(&mut data, 2, 3, 3, 4);
888        block.set_visible(2, 5);
889        block.frame(5);
890    }
891}