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