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, 3);
26///
27/// block.channel(0).for_each(|&v| assert_eq!(v, 0.0));
28/// block.channel(1).for_each(|&v| assert_eq!(v, 1.0));
29/// ```
30pub struct InterleavedViewMut<'a, S: Sample> {
31    data: &'a mut [S],
32    num_channels: u16,
33    num_frames: usize,
34    num_channels_allocated: u16,
35    num_frames_allocated: usize,
36}
37
38impl<'a, S: Sample> InterleavedViewMut<'a, S> {
39    /// Creates a new [`InterleavedViewMut`] from a mutable slice of interleaved audio data.
40    ///
41    /// # Parameters
42    /// * `data` - The slice containing mutable interleaved audio samples
43    /// * `num_channels` - Number of audio channels in the data
44    /// * `num_frames` - Number of audio frames in the data
45    ///
46    /// # Panics
47    /// Panics if the length of `data` doesn't equal `num_channels * num_frames`.
48    #[nonblocking]
49    pub fn from_slice(data: &'a mut [S], num_channels: u16, num_frames: usize) -> Self {
50        assert_eq!(data.len(), num_channels as usize * num_frames);
51        Self {
52            data,
53            num_channels,
54            num_frames,
55            num_channels_allocated: num_channels,
56            num_frames_allocated: num_frames,
57        }
58    }
59
60    /// Creates a new [`InterleavedViewMut`] from a mutable slice with limited visibility.
61    ///
62    /// This function allows creating a view that exposes only a subset of the allocated channels
63    /// and frames, which is useful for working with a logical section of a larger buffer.
64    ///
65    /// # Parameters
66    /// * `data` - The mutable slice containing interleaved audio samples
67    /// * `num_channels_visible` - Number of audio channels to expose in the view
68    /// * `num_frames_visible` - Number of audio frames to expose in the view
69    /// * `num_channels_allocated` - Total number of channels allocated in the data buffer
70    /// * `num_frames_allocated` - Total number of frames allocated in the data buffer
71    ///
72    /// # Panics
73    /// * Panics if the length of `data` doesn't equal `num_channels_allocated * num_frames_allocated`
74    /// * Panics if `num_channels_visible` exceeds `num_channels_allocated`
75    /// * Panics if `num_frames_visible` exceeds `num_frames_allocated`
76    #[nonblocking]
77    pub fn from_slice_limited(
78        data: &'a mut [S],
79        num_channels_visible: u16,
80        num_frames_visible: usize,
81        num_channels_available: u16,
82        num_frames_available: usize,
83    ) -> Self {
84        assert_eq!(
85            data.len(),
86            num_channels_available as usize * num_frames_available
87        );
88        assert!(num_channels_visible <= num_channels_available);
89        assert!(num_frames_visible <= num_frames_available);
90        Self {
91            data,
92            num_channels: num_channels_visible,
93            num_frames: num_frames_visible,
94            num_channels_allocated: num_channels_available,
95            num_frames_allocated: num_frames_available,
96        }
97    }
98
99    /// Creates a new [`InterleavedViewMut`] from raw parts with.
100    ///
101    /// # Safety
102    ///
103    /// The caller must ensure that:
104    /// - `ptr` points to valid memory containing at least `num_channels_available * num_frames_available` elements
105    /// - The memory referenced by `ptr` must be valid for the lifetime of the returned `SequentialView`
106    /// - The memory must not be mutated through other pointers while this view exists
107    #[nonblocking]
108    pub unsafe fn from_raw(ptr: *mut S, num_channels: u16, num_frames: usize) -> Self {
109        Self {
110            data: unsafe {
111                std::slice::from_raw_parts_mut(ptr, num_channels as usize * num_frames)
112            },
113            num_channels,
114            num_frames,
115            num_channels_allocated: num_channels,
116            num_frames_allocated: num_frames,
117        }
118    }
119
120    /// Creates a new [`InterleavedViewMut`] from raw parts with a limited amount of channels and/or frames.
121    ///
122    /// # Safety
123    ///
124    /// The caller must ensure that:
125    /// - `ptr` points to valid memory containing at least `num_channels_available * num_frames_available` elements
126    /// - The memory referenced by `ptr` must be valid for the lifetime of the returned `SequentialView`
127    /// - The memory must not be mutated through other pointers while this view exists
128    #[nonblocking]
129    pub unsafe fn from_raw_limited(
130        ptr: *mut S,
131        num_channels_visible: u16,
132        num_frames_visible: usize,
133        num_channels_available: u16,
134        num_frames_available: usize,
135    ) -> Self {
136        assert!(num_channels_visible <= num_channels_available);
137        assert!(num_frames_visible <= num_frames_available);
138        Self {
139            data: unsafe {
140                std::slice::from_raw_parts_mut(
141                    ptr,
142                    num_channels_available as usize * num_frames_available,
143                )
144            },
145            num_channels: num_channels_visible,
146            num_frames: num_frames_visible,
147            num_channels_allocated: num_channels_available,
148            num_frames_allocated: num_frames_available,
149        }
150    }
151}
152
153impl<S: Sample> AudioBlock<S> for InterleavedViewMut<'_, S> {
154    #[nonblocking]
155    fn num_channels(&self) -> u16 {
156        self.num_channels
157    }
158
159    #[nonblocking]
160    fn num_frames(&self) -> usize {
161        self.num_frames
162    }
163
164    #[nonblocking]
165    fn num_channels_allocated(&self) -> u16 {
166        self.num_channels_allocated
167    }
168
169    #[nonblocking]
170    fn num_frames_allocated(&self) -> usize {
171        self.num_frames_allocated
172    }
173
174    #[nonblocking]
175    fn sample(&self, channel: u16, frame: usize) -> S {
176        assert!(channel < self.num_channels);
177        assert!(frame < self.num_frames);
178        unsafe {
179            *self
180                .data
181                .get_unchecked(frame * self.num_channels_allocated as usize + channel as usize)
182        }
183    }
184
185    #[nonblocking]
186    fn channel(&self, channel: u16) -> impl Iterator<Item = &S> {
187        assert!(channel < self.num_channels);
188        self.data
189            .iter()
190            .skip(channel as usize)
191            .step_by(self.num_channels_allocated as usize)
192            .take(self.num_frames)
193    }
194
195    #[nonblocking]
196    fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
197        let num_channels = self.num_channels as usize;
198        let num_frames = self.num_frames;
199        let stride = self.num_channels_allocated as usize;
200        let data_ptr = self.data.as_ptr();
201
202        (0..num_channels).map(move |channel_idx| {
203            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
204            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
205            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
206            // But if data is empty, num_channels or num_frames must be 0.
207            let start_ptr = if self.data.is_empty() {
208                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
209            } else {
210                // Safety: channel_idx is < num_channels <= num_channels_allocated.
211                // Adding it to a valid data_ptr is safe within slice bounds.
212                unsafe { data_ptr.add(channel_idx) }
213            };
214
215            StridedSampleIter::<'_, S> {
216                // Note: '_ lifetime from &self borrow
217                // Safety: Pointer is either dangling (if empty) or valid start pointer.
218                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
219                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
220                stride,
221                remaining: num_frames, // If 0, iterator yields None immediately
222                _marker: PhantomData,
223            }
224        })
225    }
226
227    #[nonblocking]
228    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
229        assert!(frame < self.num_frames);
230        self.data
231            .iter()
232            .skip(frame * self.num_channels_allocated as usize)
233            .take(self.num_channels as usize)
234    }
235
236    #[nonblocking]
237    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
238        let num_channels = self.num_channels as usize;
239        let num_channels_allocated = self.num_channels_allocated as usize;
240        self.data
241            .chunks(num_channels_allocated)
242            .take(self.num_frames)
243            .map(move |channel_chunk| channel_chunk.iter().take(num_channels))
244    }
245
246    #[nonblocking]
247    fn view(&self) -> impl AudioBlock<S> {
248        InterleavedView::from_slice_limited(
249            self.data,
250            self.num_channels,
251            self.num_frames,
252            self.num_channels_allocated,
253            self.num_frames_allocated,
254        )
255    }
256
257    #[nonblocking]
258    fn layout(&self) -> crate::BlockLayout {
259        crate::BlockLayout::Interleaved
260    }
261
262    #[nonblocking]
263    fn raw_data(&self, _: Option<u16>) -> &[S] {
264        self.data
265    }
266}
267
268impl<S: Sample> AudioBlockMut<S> for InterleavedViewMut<'_, S> {
269    #[nonblocking]
270    fn resize(&mut self, num_channels: u16, num_frames: usize) {
271        assert!(num_channels <= self.num_channels_allocated);
272        assert!(num_frames <= self.num_frames_allocated);
273        self.num_channels = num_channels;
274        self.num_frames = num_frames;
275    }
276
277    #[nonblocking]
278    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
279        assert!(channel < self.num_channels);
280        assert!(frame < self.num_frames);
281        unsafe {
282            self.data
283                .get_unchecked_mut(frame * self.num_channels_allocated as usize + channel as usize)
284        }
285    }
286
287    #[nonblocking]
288    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
289        assert!(channel < self.num_channels);
290        self.data
291            .iter_mut()
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_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut 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_mut_ptr(); // Mutable pointer
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            StridedSampleIterMut::<'_, S> {
318                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()),
319                stride,
320                remaining: num_frames,
321                _marker: PhantomData,
322            }
323        })
324    }
325
326    #[nonblocking]
327    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
328        assert!(frame < self.num_frames);
329        self.data
330            .iter_mut()
331            .skip(frame * self.num_channels_allocated as usize)
332            .take(self.num_channels as usize)
333    }
334
335    #[nonblocking]
336    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
337        let num_channels = self.num_channels as usize;
338        let num_channels_allocated = self.num_channels_allocated as usize;
339        self.data
340            .chunks_mut(num_channels_allocated)
341            .take(self.num_frames)
342            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_channels))
343    }
344
345    #[nonblocking]
346    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
347        InterleavedViewMut::from_slice_limited(
348            self.data,
349            self.num_channels,
350            self.num_frames,
351            self.num_channels_allocated,
352            self.num_frames_allocated,
353        )
354    }
355
356    #[nonblocking]
357    fn raw_data_mut(&mut self, _: Option<u16>) -> &mut [S] {
358        self.data
359    }
360}
361
362#[cfg(test)]
363mod tests {
364    use super::*;
365
366    #[test]
367    fn test_samples() {
368        let mut data = vec![0.0; 10];
369        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
370
371        let num_frames = block.num_frames();
372        for ch in 0..block.num_channels() {
373            for f in 0..block.num_frames() {
374                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
375            }
376        }
377
378        for ch in 0..block.num_channels() {
379            for f in 0..block.num_frames() {
380                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
381            }
382        }
383
384        assert_eq!(
385            block.raw_data(None),
386            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
387        );
388    }
389
390    #[test]
391    fn test_channel() {
392        let mut data = vec![0.0; 10];
393        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
394
395        let channel = block.channel(0).copied().collect::<Vec<_>>();
396        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
397        let channel = block.channel(1).copied().collect::<Vec<_>>();
398        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
399
400        block
401            .channel_mut(0)
402            .enumerate()
403            .for_each(|(i, v)| *v = i as f32);
404        block
405            .channel_mut(1)
406            .enumerate()
407            .for_each(|(i, v)| *v = i as f32 + 10.0);
408
409        let channel = block.channel(0).copied().collect::<Vec<_>>();
410        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
411        let channel = block.channel(1).copied().collect::<Vec<_>>();
412        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
413    }
414
415    #[test]
416    fn test_channels() {
417        let mut data = vec![0.0; 10];
418        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
419
420        let mut channels_iter = block.channels();
421        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
422        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
423        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
424        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
425        assert!(channels_iter.next().is_none());
426        drop(channels_iter);
427
428        let mut channels_iter = block.channels_mut();
429        channels_iter
430            .next()
431            .unwrap()
432            .enumerate()
433            .for_each(|(i, v)| *v = i as f32);
434        channels_iter
435            .next()
436            .unwrap()
437            .enumerate()
438            .for_each(|(i, v)| *v = i as f32 + 10.0);
439        assert!(channels_iter.next().is_none());
440        drop(channels_iter);
441
442        let mut channels_iter = block.channels();
443        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
444        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
445        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
446        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
447        assert!(channels_iter.next().is_none());
448        drop(channels_iter);
449    }
450
451    #[test]
452    fn test_frame() {
453        let mut data = vec![0.0; 10];
454        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
455
456        for i in 0..block.num_frames() {
457            let frame = block.frame(i).copied().collect::<Vec<_>>();
458            assert_eq!(frame, vec![0.0, 0.0]);
459        }
460
461        for i in 0..block.num_frames() {
462            let add = i as f32 * 10.0;
463            block
464                .frame_mut(i)
465                .enumerate()
466                .for_each(|(i, v)| *v = i as f32 + add);
467        }
468
469        let frame = block.frame(0).copied().collect::<Vec<_>>();
470        assert_eq!(frame, vec![0.0, 1.0]);
471        let frame = block.frame(1).copied().collect::<Vec<_>>();
472        assert_eq!(frame, vec![10.0, 11.0]);
473        let frame = block.frame(2).copied().collect::<Vec<_>>();
474        assert_eq!(frame, vec![20.0, 21.0]);
475        let frame = block.frame(3).copied().collect::<Vec<_>>();
476        assert_eq!(frame, vec![30.0, 31.0]);
477        let frame = block.frame(4).copied().collect::<Vec<_>>();
478        assert_eq!(frame, vec![40.0, 41.0]);
479    }
480
481    #[test]
482    fn test_frames() {
483        let mut data = vec![0.0; 10];
484        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
485
486        let num_frames = block.num_frames;
487        let mut frames_iter = block.frames();
488        for _ in 0..num_frames {
489            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
490            assert_eq!(frame, vec![0.0, 0.0]);
491        }
492        assert!(frames_iter.next().is_none());
493        drop(frames_iter);
494
495        let mut frames_iter = block.frames_mut();
496        for i in 0..num_frames {
497            let add = i as f32 * 10.0;
498            frames_iter
499                .next()
500                .unwrap()
501                .enumerate()
502                .for_each(|(i, v)| *v = i as f32 + add);
503        }
504        assert!(frames_iter.next().is_none());
505        drop(frames_iter);
506
507        let mut frames_iter = block.frames();
508        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
509        assert_eq!(frame, vec![0.0, 1.0]);
510        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
511        assert_eq!(frame, vec![10.0, 11.0]);
512        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
513        assert_eq!(frame, vec![20.0, 21.0]);
514        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
515        assert_eq!(frame, vec![30.0, 31.0]);
516        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
517        assert_eq!(frame, vec![40.0, 41.0]);
518        assert!(frames_iter.next().is_none());
519    }
520
521    #[test]
522    fn test_from_slice() {
523        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
524        let block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
525        assert_eq!(block.num_channels(), 2);
526        assert_eq!(block.num_channels_allocated, 2);
527        assert_eq!(block.num_frames(), 5);
528        assert_eq!(block.num_frames_allocated, 5);
529        assert_eq!(
530            block.channel(0).copied().collect::<Vec<_>>(),
531            vec![0.0, 2.0, 4.0, 6.0, 8.0]
532        );
533        assert_eq!(
534            block.channel(1).copied().collect::<Vec<_>>(),
535            vec![1.0, 3.0, 5.0, 7.0, 9.0]
536        );
537        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
538        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
539        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
540        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
541        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
542    }
543
544    #[test]
545    fn test_view() {
546        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
547        let block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
548        let view = block.view();
549        assert_eq!(
550            view.channel(0).copied().collect::<Vec<_>>(),
551            vec![0.0, 2.0, 4.0, 6.0, 8.0]
552        );
553        assert_eq!(
554            view.channel(1).copied().collect::<Vec<_>>(),
555            vec![1.0, 3.0, 5.0, 7.0, 9.0]
556        );
557    }
558
559    #[test]
560    fn test_view_mut() {
561        let mut data = vec![0.0; 10];
562        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
563
564        {
565            let mut view = block.view_mut();
566            view.channel_mut(0)
567                .enumerate()
568                .for_each(|(i, v)| *v = i as f32);
569            view.channel_mut(1)
570                .enumerate()
571                .for_each(|(i, v)| *v = i as f32 + 10.0);
572        }
573
574        assert_eq!(
575            block.channel(0).copied().collect::<Vec<_>>(),
576            vec![0.0, 1.0, 2.0, 3.0, 4.0]
577        );
578        assert_eq!(
579            block.channel(1).copied().collect::<Vec<_>>(),
580            vec![10.0, 11.0, 12.0, 13.0, 14.0]
581        );
582    }
583
584    #[test]
585    fn test_limited() {
586        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];
587
588        let mut block = InterleavedViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
589
590        assert_eq!(block.num_channels(), 2);
591        assert_eq!(block.num_frames(), 3);
592        assert_eq!(block.num_channels_allocated, 3);
593        assert_eq!(block.num_frames_allocated, 4);
594
595        for i in 0..block.num_channels() {
596            assert_eq!(block.channel(i).count(), 3);
597            assert_eq!(block.channel_mut(i).count(), 3);
598        }
599        for i in 0..block.num_frames() {
600            assert_eq!(block.frame(i).count(), 2);
601            assert_eq!(block.frame_mut(i).count(), 2);
602        }
603    }
604
605    #[test]
606    fn test_from_raw() {
607        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
608        let block = unsafe { InterleavedViewMut::<f32>::from_raw(data.as_mut_ptr(), 2, 5) };
609        assert_eq!(block.num_channels(), 2);
610        assert_eq!(block.num_channels_allocated, 2);
611        assert_eq!(block.num_frames(), 5);
612        assert_eq!(block.num_frames_allocated, 5);
613        assert_eq!(
614            block.channel(0).copied().collect::<Vec<_>>(),
615            vec![0.0, 2.0, 4.0, 6.0, 8.0]
616        );
617        assert_eq!(
618            block.channel(1).copied().collect::<Vec<_>>(),
619            vec![1.0, 3.0, 5.0, 7.0, 9.0]
620        );
621        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
622        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
623        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
624        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
625        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
626    }
627
628    #[test]
629    fn test_from_raw_limited() {
630        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];
631
632        let mut block =
633            unsafe { InterleavedViewMut::from_raw_limited(data.as_mut_ptr(), 2, 3, 3, 4) };
634
635        assert_eq!(block.num_channels(), 2);
636        assert_eq!(block.num_frames(), 3);
637        assert_eq!(block.num_channels_allocated, 3);
638        assert_eq!(block.num_frames_allocated, 4);
639
640        for i in 0..block.num_channels() {
641            assert_eq!(block.channel(i).count(), 3);
642            assert_eq!(block.channel_mut(i).count(), 3);
643        }
644        for i in 0..block.num_frames() {
645            assert_eq!(block.frame(i).count(), 2);
646            assert_eq!(block.frame_mut(i).count(), 2);
647        }
648    }
649
650    #[test]
651    fn test_raw_data() {
652        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
653        let mut block = InterleavedViewMut::<f32>::from_slice(&mut data, 2, 5);
654
655        assert_eq!(block.layout(), crate::BlockLayout::Interleaved);
656
657        assert_eq!(
658            block.raw_data(None),
659            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
660        );
661
662        assert_eq!(
663            block.raw_data_mut(None),
664            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
665        );
666    }
667}