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