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 channel_slice(&self, channel: u16) -> Option<&[S]> {
207        assert!(channel < self.num_channels);
208        let start = channel as usize * self.num_frames_allocated;
209        let end = start + self.num_frames;
210        Some(&self.data[start..end])
211    }
212
213    #[nonblocking]
214    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
215        assert!(frame < self.num_frames);
216        self.data
217            .iter()
218            .skip(frame)
219            .step_by(self.num_frames_allocated)
220            .take(self.num_channels as usize)
221    }
222
223    #[nonblocking]
224    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
225        let num_channels = self.num_channels as usize;
226        let num_frames = self.num_frames;
227        let stride = self.num_frames_allocated;
228        let data_ptr = self.data.as_ptr();
229
230        (0..num_frames).map(move |frame_idx| {
231            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
232            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
233            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
234            // But if data is empty, num_channels or num_frames must be 0.
235            let start_ptr = if self.data.is_empty() {
236                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
237            } else {
238                // Safety: channel_idx is < num_channels <= num_channels_allocated.
239                // Adding it to a valid data_ptr is safe within slice bounds.
240                unsafe { data_ptr.add(frame_idx) }
241            };
242
243            StridedSampleIter::<'_, S> {
244                // Note: '_ lifetime from &self borrow
245                // Safety: Pointer is either dangling (if empty) or valid start pointer.
246                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
247                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
248                stride,
249                remaining: num_channels, // If 0, iterator yields None immediately
250                _marker: PhantomData,
251            }
252        })
253    }
254
255    #[nonblocking]
256    fn view(&self) -> impl AudioBlock<S> {
257        SequentialView::from_slice_limited(
258            self.data,
259            self.num_channels,
260            self.num_frames,
261            self.num_channels_allocated,
262            self.num_frames_allocated,
263        )
264    }
265
266    #[nonblocking]
267    fn layout(&self) -> crate::BlockLayout {
268        crate::BlockLayout::Sequential
269    }
270
271    #[nonblocking]
272    fn raw_data(&self, _: Option<u16>) -> &[S] {
273        self.data
274    }
275}
276
277impl<S: Sample> AudioBlockMut<S> for SequentialViewMut<'_, S> {
278    #[nonblocking]
279    fn set_active_num_channels(&mut self, num_channels: u16) {
280        assert!(num_channels <= self.num_channels_allocated);
281        self.num_channels = num_channels;
282    }
283
284    #[nonblocking]
285    fn set_active_num_frames(&mut self, num_frames: usize) {
286        assert!(num_frames <= self.num_frames_allocated);
287        self.num_frames = num_frames;
288    }
289
290    #[nonblocking]
291    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
292        assert!(channel < self.num_channels);
293        assert!(frame < self.num_frames);
294        unsafe {
295            self.data
296                .get_unchecked_mut(channel as usize * self.num_frames_allocated + frame)
297        }
298    }
299
300    #[nonblocking]
301    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
302        assert!(channel < self.num_channels);
303        self.data
304            .iter_mut()
305            .skip(channel as usize * self.num_frames_allocated)
306            .take(self.num_frames)
307    }
308
309    #[nonblocking]
310    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
311        let num_frames = self.num_frames;
312        let num_frames_allocated = self.num_frames_allocated;
313        self.data
314            .chunks_mut(num_frames_allocated)
315            .take(self.num_channels as usize)
316            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_frames))
317    }
318
319    #[nonblocking]
320    fn channel_slice_mut(&mut self, channel: u16) -> Option<&mut [S]> {
321        assert!(channel < self.num_channels);
322        let start = channel as usize * self.num_frames_allocated;
323        let end = start + self.num_frames;
324        Some(&mut self.data[start..end])
325    }
326
327    #[nonblocking]
328    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
329        assert!(frame < self.num_frames);
330        self.data
331            .iter_mut()
332            .skip(frame)
333            .step_by(self.num_frames_allocated)
334            .take(self.num_channels as usize)
335    }
336
337    #[nonblocking]
338    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
339        let num_channels = self.num_channels as usize;
340        let num_frames = self.num_frames;
341        let stride = self.num_frames_allocated;
342        let data_ptr = self.data.as_mut_ptr();
343
344        (0..num_frames).map(move |frame_idx| {
345            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
346            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
347            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
348            // But if data is empty, num_channels or num_frames must be 0.
349            let start_ptr = if self.data.is_empty() {
350                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
351            } else {
352                // Safety: channel_idx is < num_channels <= num_channels_allocated.
353                // Adding it to a valid data_ptr is safe within slice bounds.
354                unsafe { data_ptr.add(frame_idx) }
355            };
356
357            StridedSampleIterMut::<'_, S> {
358                // Note: '_ lifetime from &self borrow
359                // Safety: Pointer is either dangling (if empty) or valid start pointer.
360                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
361                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
362                stride,
363                remaining: num_channels, // If 0, iterator yields None immediately
364                _marker: PhantomData,
365            }
366        })
367    }
368
369    #[nonblocking]
370    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
371        SequentialViewMut::from_slice_limited(
372            self.data,
373            self.num_channels,
374            self.num_frames,
375            self.num_channels_allocated,
376            self.num_frames_allocated,
377        )
378    }
379
380    #[nonblocking]
381    fn raw_data_mut(&mut self, _: Option<u16>) -> &mut [S] {
382        self.data
383    }
384}
385
386#[cfg(test)]
387mod tests {
388    use rtsan_standalone::no_sanitize_realtime;
389
390    use super::*;
391
392    #[test]
393    fn test_samples() {
394        let mut data = vec![0.0; 10];
395        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
396
397        let num_frames = block.num_frames();
398        for ch in 0..block.num_channels() {
399            for f in 0..block.num_frames() {
400                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
401            }
402        }
403
404        for ch in 0..block.num_channels() {
405            for f in 0..block.num_frames() {
406                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
407            }
408        }
409
410        assert_eq!(
411            block.raw_data(None),
412            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
413        );
414    }
415
416    #[test]
417    fn test_channel() {
418        let mut data = vec![0.0; 10];
419        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
420
421        let channel = block.channel(0).copied().collect::<Vec<_>>();
422        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
423        let channel = block.channel(1).copied().collect::<Vec<_>>();
424        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
425
426        block
427            .channel_mut(0)
428            .enumerate()
429            .for_each(|(i, v)| *v = i as f32);
430        block
431            .channel_mut(1)
432            .enumerate()
433            .for_each(|(i, v)| *v = i as f32 + 10.0);
434
435        let channel = block.channel(0).copied().collect::<Vec<_>>();
436        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
437        let channel = block.channel(1).copied().collect::<Vec<_>>();
438        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
439    }
440
441    #[test]
442    fn test_channels() {
443        let mut data = vec![0.0; 10];
444        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
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, 0.0, 0.0, 0.0, 0.0]);
449        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
450        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
451        assert!(channels_iter.next().is_none());
452        drop(channels_iter);
453
454        let mut channels_iter = block.channels_mut();
455        channels_iter
456            .next()
457            .unwrap()
458            .enumerate()
459            .for_each(|(i, v)| *v = i as f32);
460        channels_iter
461            .next()
462            .unwrap()
463            .enumerate()
464            .for_each(|(i, v)| *v = i as f32 + 10.0);
465        assert!(channels_iter.next().is_none());
466        drop(channels_iter);
467
468        let mut channels_iter = block.channels();
469        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
470        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
471        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
472        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
473        assert!(channels_iter.next().is_none());
474        drop(channels_iter);
475    }
476
477    #[test]
478    fn test_frame() {
479        let mut data = vec![0.0; 12];
480        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 6);
481        block.set_active_size(2, 5);
482
483        for i in 0..block.num_frames() {
484            let frame = block.frame(i).copied().collect::<Vec<_>>();
485            assert_eq!(frame, vec![0.0, 0.0]);
486        }
487
488        for i in 0..block.num_frames() {
489            let add = i as f32 * 10.0;
490            block
491                .frame_mut(i)
492                .enumerate()
493                .for_each(|(i, v)| *v = i as f32 + add);
494        }
495
496        let channel = block.frame(0).copied().collect::<Vec<_>>();
497        assert_eq!(channel, vec![0.0, 1.0]);
498        let channel = block.frame(1).copied().collect::<Vec<_>>();
499        assert_eq!(channel, vec![10.0, 11.0]);
500        let channel = block.frame(2).copied().collect::<Vec<_>>();
501        assert_eq!(channel, vec![20.0, 21.0]);
502        let channel = block.frame(3).copied().collect::<Vec<_>>();
503        assert_eq!(channel, vec![30.0, 31.0]);
504        let channel = block.frame(4).copied().collect::<Vec<_>>();
505        assert_eq!(channel, vec![40.0, 41.0]);
506    }
507
508    #[test]
509    fn test_frames() {
510        let mut data = vec![0.0; 12];
511        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 6);
512        block.set_active_size(2, 5);
513
514        let num_frames = block.num_frames;
515        let mut frames_iter = block.frames();
516        for _ in 0..num_frames {
517            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
518            assert_eq!(frame, vec![0.0, 0.0]);
519        }
520        assert!(frames_iter.next().is_none());
521        drop(frames_iter);
522
523        let mut frames_iter = block.frames_mut();
524        for i in 0..num_frames {
525            let add = i as f32 * 10.0;
526            frames_iter
527                .next()
528                .unwrap()
529                .enumerate()
530                .for_each(|(i, v)| *v = i as f32 + add);
531        }
532        assert!(frames_iter.next().is_none());
533        drop(frames_iter);
534
535        let mut frames_iter = block.frames();
536        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
537        assert_eq!(frame, vec![0.0, 1.0]);
538        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
539        assert_eq!(frame, vec![10.0, 11.0]);
540        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
541        assert_eq!(frame, vec![20.0, 21.0]);
542        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
543        assert_eq!(frame, vec![30.0, 31.0]);
544        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
545        assert_eq!(frame, vec![40.0, 41.0]);
546        assert!(frames_iter.next().is_none());
547    }
548
549    #[test]
550    fn test_from_slice() {
551        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
552        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
553        assert_eq!(block.num_channels(), 2);
554        assert_eq!(block.num_channels_allocated, 2);
555        assert_eq!(block.num_frames(), 5);
556        assert_eq!(block.num_frames_allocated, 5);
557        assert_eq!(
558            block.channel(0).copied().collect::<Vec<_>>(),
559            vec![0.0, 1.0, 2.0, 3.0, 4.0]
560        );
561        assert_eq!(
562            block.channel(1).copied().collect::<Vec<_>>(),
563            vec![5.0, 6.0, 7.0, 8.0, 9.0]
564        );
565        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 5.0]);
566        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![1.0, 6.0]);
567        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![2.0, 7.0]);
568        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![3.0, 8.0]);
569        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![4.0, 9.0]);
570    }
571
572    #[test]
573    fn test_view() {
574        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
575        let block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
576        let view = block.view();
577        assert_eq!(
578            view.channel(0).copied().collect::<Vec<_>>(),
579            vec![0.0, 1.0, 2.0, 3.0, 4.0]
580        );
581        assert_eq!(
582            view.channel(1).copied().collect::<Vec<_>>(),
583            vec![5.0, 6.0, 7.0, 8.0, 9.0]
584        );
585    }
586
587    #[test]
588    fn test_view_mut() {
589        let mut data = vec![0.0; 10];
590        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
591
592        {
593            let mut view = block.view_mut();
594            view.channel_mut(0)
595                .enumerate()
596                .for_each(|(i, v)| *v = i as f32);
597            view.channel_mut(1)
598                .enumerate()
599                .for_each(|(i, v)| *v = i as f32 + 10.0);
600        }
601
602        assert_eq!(
603            block.channel(0).copied().collect::<Vec<_>>(),
604            vec![0.0, 1.0, 2.0, 3.0, 4.0]
605        );
606        assert_eq!(
607            block.channel(1).copied().collect::<Vec<_>>(),
608            vec![10.0, 11.0, 12.0, 13.0, 14.0]
609        );
610    }
611
612    #[test]
613    fn test_limited() {
614        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];
615
616        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
617
618        assert_eq!(block.num_channels(), 2);
619        assert_eq!(block.num_frames(), 3);
620        assert_eq!(block.num_channels_allocated, 3);
621        assert_eq!(block.num_frames_allocated, 4);
622
623        for i in 0..block.num_channels() {
624            assert_eq!(block.channel(i).count(), 3);
625            assert_eq!(block.channel_mut(i).count(), 3);
626        }
627        for i in 0..block.num_frames() {
628            assert_eq!(block.frame(i).count(), 2);
629            assert_eq!(block.frame_mut(i).count(), 2);
630        }
631    }
632
633    #[test]
634    fn test_from_raw() {
635        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
636        let block = unsafe { SequentialViewMut::<f32>::from_ptr(data.as_mut_ptr(), 2, 5) };
637        assert_eq!(block.num_channels(), 2);
638        assert_eq!(block.num_channels_allocated, 2);
639        assert_eq!(block.num_frames(), 5);
640        assert_eq!(block.num_frames_allocated, 5);
641        assert_eq!(
642            block.channel(0).copied().collect::<Vec<_>>(),
643            vec![0.0, 1.0, 2.0, 3.0, 4.0]
644        );
645        assert_eq!(
646            block.channel(1).copied().collect::<Vec<_>>(),
647            vec![5.0, 6.0, 7.0, 8.0, 9.0]
648        );
649        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 5.0]);
650        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![1.0, 6.0]);
651        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![2.0, 7.0]);
652        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![3.0, 8.0]);
653        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![4.0, 9.0]);
654    }
655
656    #[test]
657    fn test_from_raw_limited() {
658        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];
659
660        let mut block =
661            unsafe { SequentialViewMut::from_ptr_limited(data.as_mut_ptr(), 2, 3, 3, 4) };
662
663        assert_eq!(block.num_channels(), 2);
664        assert_eq!(block.num_frames(), 3);
665        assert_eq!(block.num_channels_allocated, 3);
666        assert_eq!(block.num_frames_allocated, 4);
667
668        for i in 0..block.num_channels() {
669            assert_eq!(block.channel(i).count(), 3);
670            assert_eq!(block.channel_mut(i).count(), 3);
671        }
672        for i in 0..block.num_frames() {
673            assert_eq!(block.frame(i).count(), 2);
674            assert_eq!(block.frame_mut(i).count(), 2);
675        }
676    }
677
678    #[test]
679    fn test_slice() {
680        let mut data = [0.0; 3 * 4];
681        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
682
683        assert!(block.frame_slice(0).is_none());
684
685        block.channel_slice_mut(0).unwrap().fill(1.0);
686        block.channel_slice_mut(1).unwrap().fill(2.0);
687        assert_eq!(block.channel_slice(0).unwrap(), &[1.0; 3]);
688        assert_eq!(block.channel_slice(1).unwrap(), &[2.0; 3]);
689    }
690
691    #[test]
692    #[should_panic]
693    #[no_sanitize_realtime]
694    fn test_slice_out_of_bounds() {
695        let mut data = [0.0; 3 * 4];
696        let block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
697
698        block.channel_slice(2);
699    }
700
701    #[test]
702    #[should_panic]
703    #[no_sanitize_realtime]
704    fn test_slice_out_of_bounds_mut() {
705        let mut data = [0.0; 3 * 4];
706        let mut block = SequentialViewMut::from_slice_limited(&mut data, 2, 3, 3, 4);
707
708        block.channel_slice_mut(2);
709    }
710
711    #[test]
712    fn test_raw_data() {
713        let mut data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
714        let mut block = SequentialViewMut::<f32>::from_slice(&mut data, 2, 5);
715
716        assert_eq!(block.layout(), crate::BlockLayout::Sequential);
717
718        assert_eq!(
719            block.raw_data(None),
720            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
721        );
722
723        assert_eq!(
724            block.raw_data_mut(None),
725            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
726        );
727    }
728}