audio_blocks/sequential/
view_mut.rs

1use rtsan_standalone::nonblocking;
2
3use core::{marker::PhantomData, ptr::NonNull};
4
5use super::view::SequentialView;
6use crate::{
7    AudioBlock, AudioBlockMut, Sample,
8    iter::{StridedSampleIter, StridedSampleIterMut},
9};
10
11///  A mutable view of sequential / planar audio data.
12///
13/// * **Layout:** `[ch0, ch0, ch0, ch1, ch1, ch1]`
14/// * **Interpretation:** All samples from `ch0` are stored first, followed by all from `ch1`, etc.
15/// * **Terminology:** Described as “planar” or “channels first” in the sense that all data for one channel appears before any data for the next.
16/// * **Usage:** Used in DSP pipelines where per-channel processing is easier and more efficient.
17///
18/// # Example
19///
20/// ```
21/// use audio_blocks::*;
22///
23/// let mut data = vec![0.0, 0.0, 0.0, 1.0, 1.0, 1.0];
24///
25/// let block = SequentialViewMut::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 SequentialViewMut<'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> SequentialViewMut<'a, S> {
39    /// Creates a new [`SequentialViewMut`] from a mutable slice of sequential audio data.
40    ///
41    /// # Parameters
42    /// * `data` - The mutable slice containing sequential 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 [`SequentialViewMut`] 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 sequential 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!(num_channels_visible <= num_channels_available);
85        assert!(num_frames_visible <= num_frames_available);
86        assert_eq!(
87            data.len(),
88            num_channels_available as usize * num_frames_available
89        );
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 [`SequentialViewMut`] from a pointer.
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_ptr(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 [`SequentialViewMut`] from a pointer 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_ptr_limited(
130        ptr: *mut S,
131        num_channels_visible: u16,
132        num_frames_visible: usize,
133        num_channels_allocated: u16,
134        num_frames_allocated: usize,
135    ) -> Self {
136        assert!(num_channels_visible <= num_channels_allocated);
137        assert!(num_frames_visible <= num_frames_allocated);
138        Self {
139            data: unsafe {
140                std::slice::from_raw_parts_mut(
141                    ptr,
142                    num_channels_allocated as usize * num_frames_allocated,
143                )
144            },
145            num_channels: num_channels_visible,
146            num_frames: num_frames_visible,
147            num_channels_allocated,
148            num_frames_allocated,
149        }
150    }
151}
152
153impl<S: Sample> AudioBlock<S> for SequentialViewMut<'_, S> {
154    #[nonblocking]
155    fn num_frames(&self) -> usize {
156        self.num_frames
157    }
158
159    #[nonblocking]
160    fn num_channels(&self) -> u16 {
161        self.num_channels
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(channel as usize * self.num_frames_allocated + frame)
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 * self.num_frames_allocated)
191            .take(self.num_frames)
192    }
193
194    #[nonblocking]
195    fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
196        let num_frames = self.num_frames; // Active frames per channel
197        let num_frames_allocated = self.num_frames_allocated; // Allocated frames per channel (chunk size)
198
199        self.data
200            .chunks(num_frames_allocated)
201            .take(self.num_channels as usize)
202            .map(move |channel_chunk| channel_chunk.iter().take(num_frames))
203    }
204
205    #[nonblocking]
206    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
207        assert!(frame < self.num_frames);
208        self.data
209            .iter()
210            .skip(frame)
211            .step_by(self.num_frames_allocated)
212            .take(self.num_channels as usize)
213    }
214
215    #[nonblocking]
216    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
217        let num_channels = self.num_channels as usize;
218        let num_frames = self.num_frames;
219        let stride = self.num_frames_allocated;
220        let data_ptr = self.data.as_ptr();
221
222        (0..num_frames).map(move |frame_idx| {
223            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
224            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
225            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
226            // But if data is empty, num_channels or num_frames must be 0.
227            let start_ptr = if self.data.is_empty() {
228                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
229            } else {
230                // Safety: channel_idx is < num_channels <= num_channels_allocated.
231                // Adding it to a valid data_ptr is safe within slice bounds.
232                unsafe { data_ptr.add(frame_idx) }
233            };
234
235            StridedSampleIter::<'_, S> {
236                // Note: '_ lifetime from &self borrow
237                // Safety: Pointer is either dangling (if empty) or valid start pointer.
238                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
239                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
240                stride,
241                remaining: num_channels, // If 0, iterator yields None immediately
242                _marker: PhantomData,
243            }
244        })
245    }
246
247    #[nonblocking]
248    fn view(&self) -> impl AudioBlock<S> {
249        SequentialView::from_slice_limited(
250            self.data,
251            self.num_channels,
252            self.num_frames,
253            self.num_channels_allocated,
254            self.num_frames_allocated,
255        )
256    }
257
258    #[nonblocking]
259    fn layout(&self) -> crate::BlockLayout {
260        crate::BlockLayout::Sequential
261    }
262
263    #[nonblocking]
264    fn raw_data(&self, _: Option<u16>) -> &[S] {
265        self.data
266    }
267}
268
269impl<S: Sample> AudioBlockMut<S> for SequentialViewMut<'_, S> {
270    #[nonblocking]
271    fn resize(&mut self, num_channels: u16, num_frames: usize) {
272        assert!(num_channels <= self.num_channels_allocated);
273        assert!(num_frames <= self.num_frames_allocated);
274        self.num_channels = num_channels;
275        self.num_frames = num_frames;
276    }
277
278    #[nonblocking]
279    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
280        assert!(channel < self.num_channels);
281        assert!(frame < self.num_frames);
282        unsafe {
283            self.data
284                .get_unchecked_mut(channel as usize * self.num_frames_allocated + frame)
285        }
286    }
287
288    #[nonblocking]
289    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
290        assert!(channel < self.num_channels);
291        self.data
292            .iter_mut()
293            .skip(channel as usize * self.num_frames_allocated)
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_frames = self.num_frames;
300        let num_frames_allocated = self.num_frames_allocated;
301        self.data
302            .chunks_mut(num_frames_allocated)
303            .take(self.num_channels as usize)
304            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_frames))
305    }
306
307    #[nonblocking]
308    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
309        assert!(frame < self.num_frames);
310        self.data
311            .iter_mut()
312            .skip(frame)
313            .step_by(self.num_frames_allocated)
314            .take(self.num_channels as usize)
315    }
316
317    #[nonblocking]
318    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
319        let num_channels = self.num_channels as usize;
320        let num_frames = self.num_frames;
321        let stride = self.num_frames_allocated;
322        let data_ptr = self.data.as_mut_ptr();
323
324        (0..num_frames).map(move |frame_idx| {
325            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
326            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
327            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
328            // But if data is empty, num_channels or num_frames must be 0.
329            let start_ptr = if self.data.is_empty() {
330                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
331            } else {
332                // Safety: channel_idx is < num_channels <= num_channels_allocated.
333                // Adding it to a valid data_ptr is safe within slice bounds.
334                unsafe { data_ptr.add(frame_idx) }
335            };
336
337            StridedSampleIterMut::<'_, S> {
338                // Note: '_ lifetime from &self borrow
339                // Safety: Pointer is either dangling (if empty) or valid start pointer.
340                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
341                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
342                stride,
343                remaining: num_channels, // If 0, iterator yields None immediately
344                _marker: PhantomData,
345            }
346        })
347    }
348
349    #[nonblocking]
350    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
351        SequentialViewMut::from_slice_limited(
352            self.data,
353            self.num_channels,
354            self.num_frames,
355            self.num_channels_allocated,
356            self.num_frames_allocated,
357        )
358    }
359
360    #[nonblocking]
361    fn raw_data_mut(&mut self, _: Option<u16>) -> &mut [S] {
362        self.data
363    }
364}
365
366#[cfg(test)]
367mod tests {
368    use super::*;
369
370    #[test]
371    fn test_samples() {
372        let mut data = vec![0.0; 10];
373        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
374
375        let num_frames = block.num_frames();
376        for ch in 0..block.num_channels() {
377            for f in 0..block.num_frames() {
378                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
379            }
380        }
381
382        for ch in 0..block.num_channels() {
383            for f in 0..block.num_frames() {
384                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
385            }
386        }
387
388        assert_eq!(
389            block.raw_data(None),
390            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
391        );
392    }
393
394    #[test]
395    fn test_channel() {
396        let mut data = vec![0.0; 10];
397        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
398
399        let channel = block.channel(0).copied().collect::<Vec<_>>();
400        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
401        let channel = block.channel(1).copied().collect::<Vec<_>>();
402        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
403
404        block
405            .channel_mut(0)
406            .enumerate()
407            .for_each(|(i, v)| *v = i as f32);
408        block
409            .channel_mut(1)
410            .enumerate()
411            .for_each(|(i, v)| *v = i as f32 + 10.0);
412
413        let channel = block.channel(0).copied().collect::<Vec<_>>();
414        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
415        let channel = block.channel(1).copied().collect::<Vec<_>>();
416        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
417    }
418
419    #[test]
420    fn test_channels() {
421        let mut data = vec![0.0; 10];
422        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
423
424        let mut channels_iter = block.channels();
425        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
426        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
427        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
428        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
429        assert!(channels_iter.next().is_none());
430        drop(channels_iter);
431
432        let mut channels_iter = block.channels_mut();
433        channels_iter
434            .next()
435            .unwrap()
436            .enumerate()
437            .for_each(|(i, v)| *v = i as f32);
438        channels_iter
439            .next()
440            .unwrap()
441            .enumerate()
442            .for_each(|(i, v)| *v = i as f32 + 10.0);
443        assert!(channels_iter.next().is_none());
444        drop(channels_iter);
445
446        let mut channels_iter = block.channels();
447        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
448        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
449        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
450        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
451        assert!(channels_iter.next().is_none());
452        drop(channels_iter);
453    }
454
455    #[test]
456    fn test_frame() {
457        let mut data = vec![0.0; 12];
458        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 6);
459        block.resize(2, 5);
460
461        for i in 0..block.num_frames() {
462            let frame = block.frame(i).copied().collect::<Vec<_>>();
463            assert_eq!(frame, vec![0.0, 0.0]);
464        }
465
466        for i in 0..block.num_frames() {
467            let add = i as f32 * 10.0;
468            block
469                .frame_mut(i)
470                .enumerate()
471                .for_each(|(i, v)| *v = i as f32 + add);
472        }
473
474        let channel = block.frame(0).copied().collect::<Vec<_>>();
475        assert_eq!(channel, vec![0.0, 1.0]);
476        let channel = block.frame(1).copied().collect::<Vec<_>>();
477        assert_eq!(channel, vec![10.0, 11.0]);
478        let channel = block.frame(2).copied().collect::<Vec<_>>();
479        assert_eq!(channel, vec![20.0, 21.0]);
480        let channel = block.frame(3).copied().collect::<Vec<_>>();
481        assert_eq!(channel, vec![30.0, 31.0]);
482        let channel = block.frame(4).copied().collect::<Vec<_>>();
483        assert_eq!(channel, vec![40.0, 41.0]);
484    }
485
486    #[test]
487    fn test_frames() {
488        let mut data = vec![0.0; 12];
489        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 6);
490        block.resize(2, 5);
491
492        let num_frames = block.num_frames;
493        let mut frames_iter = block.frames();
494        for _ in 0..num_frames {
495            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
496            assert_eq!(frame, vec![0.0, 0.0]);
497        }
498        assert!(frames_iter.next().is_none());
499        drop(frames_iter);
500
501        let mut frames_iter = block.frames_mut();
502        for i in 0..num_frames {
503            let add = i as f32 * 10.0;
504            frames_iter
505                .next()
506                .unwrap()
507                .enumerate()
508                .for_each(|(i, v)| *v = i as f32 + add);
509        }
510        assert!(frames_iter.next().is_none());
511        drop(frames_iter);
512
513        let mut frames_iter = block.frames();
514        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
515        assert_eq!(frame, vec![0.0, 1.0]);
516        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
517        assert_eq!(frame, vec![10.0, 11.0]);
518        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
519        assert_eq!(frame, vec![20.0, 21.0]);
520        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
521        assert_eq!(frame, vec![30.0, 31.0]);
522        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
523        assert_eq!(frame, vec![40.0, 41.0]);
524        assert!(frames_iter.next().is_none());
525    }
526
527    #[test]
528    fn test_from_slice() {
529        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
530        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
531        assert_eq!(block.num_channels(), 2);
532        assert_eq!(block.num_channels_allocated, 2);
533        assert_eq!(block.num_frames(), 5);
534        assert_eq!(block.num_frames_allocated, 5);
535        assert_eq!(
536            block.channel(0).copied().collect::<Vec<_>>(),
537            vec![0.0, 1.0, 2.0, 3.0, 4.0]
538        );
539        assert_eq!(
540            block.channel(1).copied().collect::<Vec<_>>(),
541            vec![5.0, 6.0, 7.0, 8.0, 9.0]
542        );
543        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 5.0]);
544        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![1.0, 6.0]);
545        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![2.0, 7.0]);
546        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![3.0, 8.0]);
547        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![4.0, 9.0]);
548    }
549
550    #[test]
551    fn test_view() {
552        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
553        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
554        let view = block.view();
555        assert_eq!(
556            view.channel(0).copied().collect::<Vec<_>>(),
557            vec![0.0, 1.0, 2.0, 3.0, 4.0]
558        );
559        assert_eq!(
560            view.channel(1).copied().collect::<Vec<_>>(),
561            vec![5.0, 6.0, 7.0, 8.0, 9.0]
562        );
563    }
564
565    #[test]
566    fn test_view_mut() {
567        let mut data = vec![0.0; 10];
568        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
569
570        {
571            let mut view = block.view_mut();
572            view.channel_mut(0)
573                .enumerate()
574                .for_each(|(i, v)| *v = i as f32);
575            view.channel_mut(1)
576                .enumerate()
577                .for_each(|(i, v)| *v = i as f32 + 10.0);
578        }
579
580        assert_eq!(
581            block.channel(0).copied().collect::<Vec<_>>(),
582            vec![0.0, 1.0, 2.0, 3.0, 4.0]
583        );
584        assert_eq!(
585            block.channel(1).copied().collect::<Vec<_>>(),
586            vec![10.0, 11.0, 12.0, 13.0, 14.0]
587        );
588    }
589
590    #[test]
591    fn test_limited() {
592        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];
593
594        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
595
596        assert_eq!(block.num_channels(), 2);
597        assert_eq!(block.num_frames(), 3);
598        assert_eq!(block.num_channels_allocated, 3);
599        assert_eq!(block.num_frames_allocated, 4);
600
601        for i in 0..block.num_channels() {
602            assert_eq!(block.channel(i).count(), 3);
603            assert_eq!(block.channel_mut(i).count(), 3);
604        }
605        for i in 0..block.num_frames() {
606            assert_eq!(block.frame(i).count(), 2);
607            assert_eq!(block.frame_mut(i).count(), 2);
608        }
609    }
610
611    #[test]
612    fn test_from_raw() {
613        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
614        let block = unsafe { SequentialViewMut::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
615        assert_eq!(block.num_channels(), 2);
616        assert_eq!(block.num_channels_allocated, 2);
617        assert_eq!(block.num_frames(), 5);
618        assert_eq!(block.num_frames_allocated, 5);
619        assert_eq!(
620            block.channel(0).copied().collect::<Vec<_>>(),
621            vec![0.0, 1.0, 2.0, 3.0, 4.0]
622        );
623        assert_eq!(
624            block.channel(1).copied().collect::<Vec<_>>(),
625            vec![5.0, 6.0, 7.0, 8.0, 9.0]
626        );
627        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 5.0]);
628        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![1.0, 6.0]);
629        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![2.0, 7.0]);
630        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![3.0, 8.0]);
631        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![4.0, 9.0]);
632    }
633
634    #[test]
635    fn test_from_raw_limited() {
636        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];
637
638        let mut block =
639            unsafe { SequentialViewMut::from_ptr_limited(data.as_mut_ptr(), 2, 3, 3, 4) };
640
641        assert_eq!(block.num_channels(), 2);
642        assert_eq!(block.num_frames(), 3);
643        assert_eq!(block.num_channels_allocated, 3);
644        assert_eq!(block.num_frames_allocated, 4);
645
646        for i in 0..block.num_channels() {
647            assert_eq!(block.channel(i).count(), 3);
648            assert_eq!(block.channel_mut(i).count(), 3);
649        }
650        for i in 0..block.num_frames() {
651            assert_eq!(block.frame(i).count(), 2);
652            assert_eq!(block.frame_mut(i).count(), 2);
653        }
654    }
655
656    #[test]
657    fn test_raw_data() {
658        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
659        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
660
661        assert_eq!(block.layout(), crate::BlockLayout::Sequential);
662
663        assert_eq!(
664            block.raw_data(None),
665            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
666        );
667
668        assert_eq!(
669            block.raw_data_mut(None),
670            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
671        );
672    }
673}