audio_blocks/interleaved/
owned.rs

1use rtsan_standalone::{blocking, nonblocking};
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::{boxed::Box, vec, vec::Vec};
5use core::{marker::PhantomData, ptr::NonNull};
6#[cfg(all(feature = "std", not(feature = "alloc")))]
7use std::{boxed::Box, vec, vec::Vec};
8#[cfg(all(feature = "std", feature = "alloc"))]
9use std::{boxed::Box, vec, vec::Vec};
10
11use super::{view::InterleavedView, view_mut::InterleavedViewMut};
12use crate::{
13    AudioBlock, AudioBlockMut, Sample,
14    iter::{StridedSampleIter, StridedSampleIterMut},
15};
16
17/// An interleaved audio block that owns its data.
18///
19/// * **Layout:** `[ch0, ch1, ch0, ch1, ch0, ch1]`
20/// * **Interpretation:** Each group of channel samples represents a frame. So, this layout stores frames one after another.
21/// * **Terminology:** Described as “packed” or “frames first” because each time step is grouped and processed as a unit (a frame).
22/// * **Usage:** Often used in APIs or hardware-level interfaces, where synchronized playback across channels is crucial.
23///
24/// # Example
25///
26/// ```
27/// use audio_blocks::*;
28///
29/// let block = Interleaved::new(2, 3);
30/// let mut block = Interleaved::from_block(&block);
31///
32/// block.channel_mut(0).for_each(|v| *v = 0.0);
33/// block.channel_mut(1).for_each(|v| *v = 1.0);
34///
35/// assert_eq!(block.raw_data(None), &[0.0, 1.0, 0.0, 1.0, 0.0, 1.0]);
36/// ```
37pub struct Interleaved<S: Sample> {
38    data: Box<[S]>,
39    num_channels: u16,
40    num_frames: usize,
41    num_channels_allocated: u16,
42    num_frames_allocated: usize,
43}
44
45impl<S: Sample> Interleaved<S> {
46    /// Creates a new [`Interleaved`] audio block with the specified dimensions.
47    ///
48    /// Allocates memory for a new interleaved audio block with exactly the specified
49    /// number of channels and frames. The block is initialized with the default value
50    /// for the sample type.
51    ///
52    /// Do not use in real-time processes!
53    ///
54    /// # Arguments
55    ///
56    /// * `num_channels` - The number of audio channels
57    /// * `num_frames` - The number of frames per channel
58    ///
59    /// # Panics
60    ///
61    /// Panics if the multiplication of `num_channels` and `num_frames` would overflow a usize.
62    #[blocking]
63    pub fn new(num_channels: u16, num_frames: usize) -> Self {
64        let total_samples = (num_channels as usize)
65            .checked_mul(num_frames)
66            .expect("Multiplication overflow: num_channels * num_frames is too large");
67
68        Self {
69            data: vec![S::zero(); total_samples].into_boxed_slice(),
70            num_channels,
71            num_frames,
72            num_channels_allocated: num_channels,
73            num_frames_allocated: num_frames,
74        }
75    }
76
77    /// Creates a new [`Interleaved`] audio block by copying data from another [`AudioBlock`].
78    ///
79    /// Converts any [`AudioBlock`] implementation to an interleaved format by iterating
80    /// through each frame of the source block and copying its samples. The new block
81    /// will have the same dimensions as the source block.
82    ///
83    /// # Warning
84    ///
85    /// This function allocates memory and should not be used in real-time audio processing contexts.
86    ///
87    /// # Arguments
88    ///
89    /// * `block` - The source audio block to copy data from
90    #[blocking]
91    pub fn from_block(block: &impl AudioBlock<S>) -> Self {
92        let mut data = Vec::with_capacity(block.num_channels() as usize * block.num_frames());
93        block.frames().for_each(|f| f.for_each(|&v| data.push(v)));
94        Self {
95            data: data.into_boxed_slice(),
96            num_channels: block.num_channels(),
97            num_frames: block.num_frames(),
98            num_channels_allocated: block.num_channels(),
99            num_frames_allocated: block.num_frames(),
100        }
101    }
102}
103
104impl<S: Sample> AudioBlock<S> for Interleaved<S> {
105    #[nonblocking]
106    fn num_channels(&self) -> u16 {
107        self.num_channels
108    }
109
110    #[nonblocking]
111    fn num_frames(&self) -> usize {
112        self.num_frames
113    }
114
115    #[nonblocking]
116    fn num_channels_allocated(&self) -> u16 {
117        self.num_channels_allocated
118    }
119
120    #[nonblocking]
121    fn num_frames_allocated(&self) -> usize {
122        self.num_frames_allocated
123    }
124
125    #[nonblocking]
126    fn sample(&self, channel: u16, frame: usize) -> S {
127        assert!(channel < self.num_channels);
128        assert!(frame < self.num_frames);
129        unsafe {
130            *self
131                .data
132                .get_unchecked(frame * self.num_channels_allocated as usize + channel as usize)
133        }
134    }
135
136    #[nonblocking]
137    fn channel(&self, channel: u16) -> impl Iterator<Item = &S> {
138        assert!(channel < self.num_channels);
139        self.data
140            .iter()
141            .skip(channel as usize)
142            .step_by(self.num_channels_allocated as usize)
143            .take(self.num_frames)
144    }
145
146    #[nonblocking]
147    fn channels(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
148        let num_channels = self.num_channels as usize;
149        let num_frames = self.num_frames;
150        let stride = self.num_channels_allocated as usize;
151
152        // If the data slice is empty (num_channels or num_frames was 0),
153        // the effective number of frames any iterator should yield is 0.
154        let effective_num_frames = if self.data.is_empty() { 0 } else { num_frames };
155
156        // Get base pointer. If data is empty, it's dangling, but this is fine
157        // because effective_num_frames will be 0, preventing its use in next().
158        let data_ptr = self.data.as_ptr();
159
160        (0..num_channels).map(move |channel_idx| {
161            // Calculate start pointer for the channel.
162            // Safety: If data is not empty, data_ptr is valid and channel_idx is
163            // within bounds [0, num_channels), which is <= num_channels_allocated.
164            // Pointer arithmetic is contained within the allocation.
165            // If data is empty, data_ptr is dangling, but add(0) is okay.
166            // If channel_idx > 0 and data is empty, this relies on num_channels being 0
167            // (so this closure doesn't run) or effective_num_frames being 0
168            // (so the resulting iterator is a no-op).
169            // We rely on effective_num_frames == 0 when data is empty.
170            let start_ptr = unsafe { data_ptr.add(channel_idx) };
171
172            StridedSampleIter::<'_, S> {
173                // Safety: Cast to *mut S for NonNull::new.
174                // If effective_num_frames is 0, ptr can be dangling (NonNull::dangling()).
175                // If effective_num_frames > 0, data is not empty, start_ptr is valid and non-null.
176                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()),
177                stride,
178                remaining: effective_num_frames, // Use the safe frame count
179                _marker: PhantomData,
180            }
181        })
182    }
183
184    #[nonblocking]
185    fn frame(&self, frame: usize) -> impl Iterator<Item = &S> {
186        assert!(frame < self.num_frames);
187        self.data
188            .iter()
189            .skip(frame * self.num_channels_allocated as usize)
190            .take(self.num_channels as usize)
191    }
192
193    #[nonblocking]
194    fn frames(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
195        let num_channels = self.num_channels as usize;
196        let num_channels_allocated = self.num_channels_allocated as usize;
197        self.data
198            .chunks(num_channels_allocated)
199            .take(self.num_frames)
200            .map(move |channel_chunk| channel_chunk.iter().take(num_channels))
201    }
202
203    #[nonblocking]
204    fn frame_slice(&self, frame: usize) -> Option<&[S]> {
205        assert!(frame < self.num_frames);
206        let start = frame * self.num_channels_allocated as usize;
207        let end = start + self.num_channels as usize;
208        Some(&self.data[start..end])
209    }
210
211    #[nonblocking]
212    fn view(&self) -> impl AudioBlock<S> {
213        InterleavedView::from_slice_limited(
214            &self.data,
215            self.num_channels,
216            self.num_frames,
217            self.num_channels_allocated,
218            self.num_frames_allocated,
219        )
220    }
221
222    #[nonblocking]
223    fn layout(&self) -> crate::BlockLayout {
224        crate::BlockLayout::Interleaved
225    }
226
227    #[nonblocking]
228    fn raw_data(&self, _: Option<u16>) -> &[S] {
229        &self.data
230    }
231}
232
233impl<S: Sample> AudioBlockMut<S> for Interleaved<S> {
234    #[nonblocking]
235    fn set_active_num_channels(&mut self, num_channels: u16) {
236        assert!(num_channels <= self.num_channels_allocated);
237        self.num_channels = num_channels;
238    }
239
240    #[nonblocking]
241    fn set_active_num_frames(&mut self, num_frames: usize) {
242        assert!(num_frames <= self.num_frames_allocated);
243        self.num_frames = num_frames;
244    }
245
246    #[nonblocking]
247    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
248        assert!(channel < self.num_channels);
249        assert!(frame < self.num_frames);
250        unsafe {
251            self.data
252                .get_unchecked_mut(frame * self.num_channels_allocated as usize + channel as usize)
253        }
254    }
255
256    #[nonblocking]
257    fn channel_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
258        assert!(channel < self.num_channels);
259        self.data
260            .iter_mut()
261            .skip(channel as usize)
262            .step_by(self.num_channels_allocated as usize)
263            .take(self.num_frames)
264    }
265
266    #[nonblocking]
267    fn channels_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
268        let num_channels = self.num_channels as usize;
269        let num_frames = self.num_frames;
270        let stride = self.num_channels_allocated as usize;
271
272        // Ensure iterator is empty if underlying data is empty.
273        let effective_num_frames = if self.data.is_empty() { 0 } else { num_frames };
274
275        // Get base mutable pointer.
276        let data_ptr = self.data.as_mut_ptr();
277
278        (0..num_channels).map(move |channel_idx| {
279            // Calculate start pointer.
280            // Safety: Same reasoning as the immutable version applies.
281            let start_ptr = unsafe { data_ptr.add(channel_idx) };
282
283            StridedSampleIterMut::<'_, S> {
284                // Safety: Same reasoning as the immutable version applies.
285                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()),
286                stride,
287                remaining: effective_num_frames, // Use the safe frame count
288                _marker: PhantomData,
289            }
290        })
291    }
292
293    #[nonblocking]
294    fn frame_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
295        assert!(frame < self.num_frames);
296        self.data
297            .iter_mut()
298            .skip(frame * self.num_channels_allocated as usize)
299            .take(self.num_channels as usize)
300    }
301
302    #[nonblocking]
303    fn frames_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
304        let num_channels = self.num_channels as usize;
305        let num_channels_allocated = self.num_channels_allocated as usize;
306        self.data
307            .chunks_mut(num_channels_allocated)
308            .take(self.num_frames)
309            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_channels))
310    }
311
312    #[nonblocking]
313    fn frame_slice_mut(&mut self, frame: usize) -> Option<&mut [S]> {
314        assert!(frame < self.num_frames);
315        let start = frame * self.num_channels_allocated as usize;
316        let end = start + self.num_channels as usize;
317        Some(&mut self.data[start..end])
318    }
319
320    #[nonblocking]
321    fn view_mut(&mut self) -> impl AudioBlockMut<S> {
322        InterleavedViewMut::from_slice_limited(
323            &mut self.data,
324            self.num_channels,
325            self.num_frames,
326            self.num_channels_allocated,
327            self.num_frames_allocated,
328        )
329    }
330
331    #[nonblocking]
332    fn raw_data_mut(&mut self, _: Option<u16>) -> &mut [S] {
333        &mut self.data
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use rtsan_standalone::no_sanitize_realtime;
340
341    use super::*;
342    use crate::sequential::SequentialView;
343
344    #[test]
345    fn test_samples() {
346        let mut block = Interleaved::<f32>::new(2, 5);
347
348        let num_frames = block.num_frames();
349        for ch in 0..block.num_channels() {
350            for f in 0..block.num_frames() {
351                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
352            }
353        }
354
355        for ch in 0..block.num_channels() {
356            for f in 0..block.num_frames() {
357                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
358            }
359        }
360
361        assert_eq!(
362            block.raw_data(None),
363            &[0.0, 5.0, 1.0, 6.0, 2.0, 7.0, 3.0, 8.0, 4.0, 9.0]
364        );
365    }
366
367    #[test]
368    fn test_channel() {
369        let mut block = Interleaved::<f32>::new(2, 5);
370
371        let channel = block.channel(0).copied().collect::<Vec<_>>();
372        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
373        let channel = block.channel(1).copied().collect::<Vec<_>>();
374        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
375
376        block
377            .channel_mut(0)
378            .enumerate()
379            .for_each(|(i, v)| *v = i as f32);
380        block
381            .channel_mut(1)
382            .enumerate()
383            .for_each(|(i, v)| *v = i as f32 + 10.0);
384
385        let channel = block.channel(0).copied().collect::<Vec<_>>();
386        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
387        let channel = block.channel(1).copied().collect::<Vec<_>>();
388        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
389    }
390
391    #[test]
392    fn test_channels() {
393        let mut block = Interleaved::<f32>::new(2, 5);
394
395        let mut channels_iter = block.channels();
396        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
397        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
398        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
399        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
400        assert!(channels_iter.next().is_none());
401        drop(channels_iter);
402
403        let mut channels_iter = block.channels_mut();
404        channels_iter
405            .next()
406            .unwrap()
407            .enumerate()
408            .for_each(|(i, v)| *v = i as f32);
409        channels_iter
410            .next()
411            .unwrap()
412            .enumerate()
413            .for_each(|(i, v)| *v = i as f32 + 10.0);
414        assert!(channels_iter.next().is_none());
415        drop(channels_iter);
416
417        let mut channels_iter = block.channels();
418        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
419        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
420        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
421        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
422        assert!(channels_iter.next().is_none());
423        drop(channels_iter);
424    }
425
426    #[test]
427    fn test_frame() {
428        let mut block = Interleaved::<f32>::new(2, 5);
429
430        for i in 0..block.num_frames() {
431            let frame = block.frame(i).copied().collect::<Vec<_>>();
432            assert_eq!(frame, vec![0.0, 0.0]);
433        }
434
435        for i in 0..block.num_frames() {
436            let add = i as f32 * 10.0;
437            block
438                .frame_mut(i)
439                .enumerate()
440                .for_each(|(i, v)| *v = i as f32 + add);
441        }
442
443        let frame = block.frame(0).copied().collect::<Vec<_>>();
444        assert_eq!(frame, vec![0.0, 1.0]);
445        let frame = block.frame(1).copied().collect::<Vec<_>>();
446        assert_eq!(frame, vec![10.0, 11.0]);
447        let frame = block.frame(2).copied().collect::<Vec<_>>();
448        assert_eq!(frame, vec![20.0, 21.0]);
449        let frame = block.frame(3).copied().collect::<Vec<_>>();
450        assert_eq!(frame, vec![30.0, 31.0]);
451        let frame = block.frame(4).copied().collect::<Vec<_>>();
452        assert_eq!(frame, vec![40.0, 41.0]);
453    }
454
455    #[test]
456    fn test_frames() {
457        let mut block = Interleaved::<f32>::new(2, 5);
458        let num_frames = block.num_frames;
459        let mut frames_iter = block.frames();
460        for _ in 0..num_frames {
461            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
462            assert_eq!(frame, vec![0.0, 0.0]);
463        }
464        assert!(frames_iter.next().is_none());
465        drop(frames_iter);
466
467        let mut frames_iter = block.frames_mut();
468        for i in 0..num_frames {
469            let add = i as f32 * 10.0;
470            frames_iter
471                .next()
472                .unwrap()
473                .enumerate()
474                .for_each(|(i, v)| *v = i as f32 + add);
475        }
476        assert!(frames_iter.next().is_none());
477        drop(frames_iter);
478
479        let mut frames_iter = block.frames();
480        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
481        assert_eq!(frame, vec![0.0, 1.0]);
482        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
483        assert_eq!(frame, vec![10.0, 11.0]);
484        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
485        assert_eq!(frame, vec![20.0, 21.0]);
486        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
487        assert_eq!(frame, vec![30.0, 31.0]);
488        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
489        assert_eq!(frame, vec![40.0, 41.0]);
490        assert!(frames_iter.next().is_none());
491    }
492
493    #[test]
494    fn test_from_slice() {
495        let block = Interleaved::<f32>::from_block(&InterleavedView::from_slice(
496            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
497            2,
498            5,
499        ));
500        assert_eq!(block.num_channels(), 2);
501        assert_eq!(block.num_channels_allocated(), 2);
502        assert_eq!(block.num_frames(), 5);
503        assert_eq!(block.num_frames_allocated(), 5);
504        assert_eq!(
505            block.channel(0).copied().collect::<Vec<_>>(),
506            vec![0.0, 2.0, 4.0, 6.0, 8.0]
507        );
508        assert_eq!(
509            block.channel(1).copied().collect::<Vec<_>>(),
510            vec![1.0, 3.0, 5.0, 7.0, 9.0]
511        );
512        assert_eq!(block.frame(0).copied().collect::<Vec<_>>(), vec![0.0, 1.0]);
513        assert_eq!(block.frame(1).copied().collect::<Vec<_>>(), vec![2.0, 3.0]);
514        assert_eq!(block.frame(2).copied().collect::<Vec<_>>(), vec![4.0, 5.0]);
515        assert_eq!(block.frame(3).copied().collect::<Vec<_>>(), vec![6.0, 7.0]);
516        assert_eq!(block.frame(4).copied().collect::<Vec<_>>(), vec![8.0, 9.0]);
517    }
518
519    #[test]
520    fn test_view() {
521        let block = Interleaved::<f32>::from_block(&InterleavedView::from_slice(
522            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
523            2,
524            5,
525        ));
526        let view = block.view();
527        assert_eq!(
528            view.channel(0).copied().collect::<Vec<_>>(),
529            vec![0.0, 2.0, 4.0, 6.0, 8.0]
530        );
531        assert_eq!(
532            view.channel(1).copied().collect::<Vec<_>>(),
533            vec![1.0, 3.0, 5.0, 7.0, 9.0]
534        );
535    }
536
537    #[test]
538    fn test_view_mut() {
539        let mut block = Interleaved::<f32>::new(2, 5);
540        {
541            let mut view = block.view_mut();
542            view.channel_mut(0)
543                .enumerate()
544                .for_each(|(i, v)| *v = i as f32);
545            view.channel_mut(1)
546                .enumerate()
547                .for_each(|(i, v)| *v = i as f32 + 10.0);
548        }
549
550        assert_eq!(
551            block.channel(0).copied().collect::<Vec<_>>(),
552            vec![0.0, 1.0, 2.0, 3.0, 4.0]
553        );
554        assert_eq!(
555            block.channel(1).copied().collect::<Vec<_>>(),
556            vec![10.0, 11.0, 12.0, 13.0, 14.0]
557        );
558    }
559
560    #[test]
561    fn test_from_block() {
562        let block = SequentialView::<f32>::from_slice(
563            &[0.0, 2.0, 4.0, 6.0, 8.0, 1.0, 3.0, 5.0, 7.0, 9.0],
564            2,
565            5,
566        );
567
568        let block = Interleaved::<f32>::from_block(&block);
569
570        assert_eq!(
571            block.channel(0).copied().collect::<Vec<_>>(),
572            vec![0.0, 2.0, 4.0, 6.0, 8.0]
573        );
574        assert_eq!(
575            block.channel(1).copied().collect::<Vec<_>>(),
576            vec![1.0, 3.0, 5.0, 7.0, 9.0]
577        );
578    }
579
580    #[test]
581    fn test_resize() {
582        let mut block = Interleaved::<f32>::new(3, 10);
583        assert_eq!(block.num_channels(), 3);
584        assert_eq!(block.num_frames(), 10);
585        assert_eq!(block.num_channels_allocated(), 3);
586        assert_eq!(block.num_frames_allocated(), 10);
587
588        for i in 0..block.num_channels() {
589            assert_eq!(block.channel(i).count(), 10);
590            assert_eq!(block.channel_mut(i).count(), 10);
591        }
592        for i in 0..block.num_frames() {
593            assert_eq!(block.frame(i).count(), 3);
594            assert_eq!(block.frame_mut(i).count(), 3);
595        }
596
597        block.set_active_size(3, 10);
598        block.set_active_size(2, 5);
599
600        assert_eq!(block.num_channels(), 2);
601        assert_eq!(block.num_frames(), 5);
602        assert_eq!(block.num_channels_allocated(), 3);
603        assert_eq!(block.num_frames_allocated(), 10);
604
605        for i in 0..block.num_channels() {
606            assert_eq!(block.channel(i).count(), 5);
607            assert_eq!(block.channel_mut(i).count(), 5);
608        }
609        for i in 0..block.num_frames() {
610            assert_eq!(block.frame(i).count(), 2);
611            assert_eq!(block.frame_mut(i).count(), 2);
612        }
613    }
614
615    #[test]
616    #[should_panic]
617    #[no_sanitize_realtime]
618    fn test_wrong_resize_channels() {
619        let mut block = Interleaved::<f32>::new(2, 10);
620        block.set_active_size(3, 10);
621    }
622
623    #[test]
624    #[should_panic]
625    #[no_sanitize_realtime]
626    fn test_wrong_resize_frames() {
627        let mut block = Interleaved::<f32>::new(2, 10);
628        block.set_active_size(2, 11);
629    }
630
631    #[test]
632    #[should_panic]
633    #[no_sanitize_realtime]
634    fn test_wrong_channel() {
635        let mut block = Interleaved::<f32>::new(2, 10);
636        block.set_active_size(1, 10);
637        let _ = block.channel(1);
638    }
639
640    #[test]
641    #[should_panic]
642    #[no_sanitize_realtime]
643    fn test_wrong_frame() {
644        let mut block = Interleaved::<f32>::new(2, 10);
645        block.set_active_size(2, 5);
646        let _ = block.frame(5);
647    }
648
649    #[test]
650    #[should_panic]
651    #[no_sanitize_realtime]
652    fn test_wrong_channel_mut() {
653        let mut block = Interleaved::<f32>::new(2, 10);
654        block.set_active_size(1, 10);
655        let _ = block.channel_mut(1);
656    }
657
658    #[test]
659    #[should_panic]
660    #[no_sanitize_realtime]
661    fn test_wrong_frame_mut() {
662        let mut block = Interleaved::<f32>::new(2, 10);
663        block.set_active_size(2, 5);
664        let _ = block.frame_mut(5);
665    }
666
667    #[test]
668    fn test_slice() {
669        let mut block = Interleaved::<f32>::new(3, 6);
670        block.set_active_size(2, 5);
671        assert!(block.channel_slice(0).is_none());
672
673        block.frame_slice_mut(0).unwrap().fill(1.0);
674        block.frame_slice_mut(1).unwrap().fill(2.0);
675        block.frame_slice_mut(2).unwrap().fill(3.0);
676        assert_eq!(block.frame_slice(0).unwrap(), &[1.0; 2]);
677        assert_eq!(block.frame_slice(1).unwrap(), &[2.0; 2]);
678        assert_eq!(block.frame_slice(2).unwrap(), &[3.0; 2]);
679    }
680
681    #[test]
682    #[should_panic]
683    #[no_sanitize_realtime]
684    fn test_slice_out_of_bounds() {
685        let mut block = Interleaved::<f32>::new(3, 6);
686        block.set_active_size(2, 5);
687        block.frame_slice(5);
688    }
689
690    #[test]
691    #[should_panic]
692    #[no_sanitize_realtime]
693    fn test_slice_out_of_bounds_mut() {
694        let mut block = Interleaved::<f32>::new(3, 6);
695        block.set_active_size(2, 5);
696        block.frame_slice(5);
697    }
698
699    #[test]
700    fn test_raw_data() {
701        let data = [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
702        let mut block =
703            Interleaved::<f32>::from_block(&InterleavedView::<f32>::from_slice(&data, 2, 5));
704
705        assert_eq!(block.layout(), crate::BlockLayout::Interleaved);
706
707        assert_eq!(
708            block.raw_data(None),
709            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
710        );
711
712        assert_eq!(
713            block.raw_data_mut(None),
714            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
715        );
716    }
717}