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::AudioBlockSequentialView, view_mut::AudioBlockSequentialViewMut};
12use crate::{
13    AudioBlock, AudioBlockMut, Sample,
14    iter::{StridedSampleIter, StridedSampleIterMut},
15};
16
17/// A sequential 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 “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 = AudioBlockSequential::new(2, 3);
30/// let mut block = AudioBlockSequential::from_block(&block);
31///
32/// block.channel_mut(0).fill(0.0);
33/// block.channel_mut(1).fill(1.0);
34///
35/// assert_eq!(block.channel(0), &[0.0, 0.0, 0.0]);
36/// assert_eq!(block.channel(1), &[1.0, 1.0, 1.0]);
37/// ```
38pub struct AudioBlockSequential<S: Sample> {
39    data: Box<[S]>,
40    num_channels: u16,
41    num_frames: usize,
42    num_channels_allocated: u16,
43    num_frames_allocated: usize,
44}
45
46impl<S: Sample> AudioBlockSequential<S> {
47    /// Creates a new audio block with the specified dimensions.
48    ///
49    /// Allocates memory with exactly the specified number of channels and
50    /// frames. The block is initialized with zeros.
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 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
93            .channels_iter()
94            .for_each(|c| c.for_each(|&v| data.push(v)));
95        Self {
96            data: data.into_boxed_slice(),
97            num_channels: block.num_channels(),
98            num_frames: block.num_frames(),
99            num_channels_allocated: block.num_channels(),
100            num_frames_allocated: block.num_frames(),
101        }
102    }
103
104    /// Returns a slice for a single channel.
105    ///
106    /// # Panics
107    ///
108    /// Panics if channel index is out of bounds.
109    #[nonblocking]
110    pub fn channel(&self, channel: u16) -> &[S] {
111        assert!(channel < self.num_channels);
112        let start = channel as usize * self.num_frames_allocated;
113        let end = start + self.num_frames;
114        &self.data[start..end]
115    }
116
117    /// Returns a mutable slice for a single channel.
118    ///
119    /// # Panics
120    ///
121    /// Panics if channel index is out of bounds.
122    #[nonblocking]
123    pub fn channel_mut(&mut self, channel: u16) -> &mut [S] {
124        assert!(channel < self.num_channels);
125        let start = channel as usize * self.num_frames_allocated;
126        let end = start + self.num_frames;
127        &mut self.data[start..end]
128    }
129
130    /// Returns an iterator over all channels in the block.
131    ///
132    /// Each channel is represented as a slice of samples.
133    #[nonblocking]
134    pub fn channels(&self) -> impl Iterator<Item = &[S]> {
135        self.data
136            .chunks(self.num_frames_allocated)
137            .take(self.num_channels as usize)
138            .map(|frame| &frame[..self.num_frames])
139    }
140
141    /// Returns a mutable iterator over all channels in the block.
142    ///
143    /// Each channel is represented as a mutable slice of samples.
144    #[nonblocking]
145    pub fn channels_mut(&mut self) -> impl Iterator<Item = &mut [S]> {
146        self.data
147            .chunks_mut(self.num_frames_allocated)
148            .take(self.num_channels as usize)
149            .map(|frame| &mut frame[..self.num_frames])
150    }
151
152    /// Provides direct access to the underlying memory as an interleaved slice.
153    ///
154    /// This function gives access to all allocated data, including any reserved capacity
155    /// beyond the active range.
156    #[nonblocking]
157    pub fn raw_data(&self) -> &[S] {
158        &self.data
159    }
160
161    /// Provides direct mutable access to the underlying memory as an interleaved slice.
162    ///
163    /// This function gives mutable access to all allocated data, including any reserved capacity
164    /// beyond the active range.
165    #[nonblocking]
166    pub fn raw_data_mut(&mut self) -> &mut [S] {
167        &mut self.data
168    }
169
170    #[nonblocking]
171    pub fn view(&self) -> AudioBlockSequentialView<'_, S> {
172        AudioBlockSequentialView::from_slice_limited(
173            &self.data,
174            self.num_channels,
175            self.num_frames,
176            self.num_channels_allocated,
177            self.num_frames_allocated,
178        )
179    }
180
181    #[nonblocking]
182    pub fn view_mut(&mut self) -> AudioBlockSequentialViewMut<'_, S> {
183        AudioBlockSequentialViewMut::from_slice_limited(
184            &mut self.data,
185            self.num_channels,
186            self.num_frames,
187            self.num_channels_allocated,
188            self.num_frames_allocated,
189        )
190    }
191}
192
193impl<S: Sample> AudioBlock<S> for AudioBlockSequential<S> {
194    type PlanarView = [S; 0];
195
196    #[nonblocking]
197    fn num_channels(&self) -> u16 {
198        self.num_channels
199    }
200
201    #[nonblocking]
202    fn num_frames(&self) -> usize {
203        self.num_frames
204    }
205
206    #[nonblocking]
207    fn num_channels_allocated(&self) -> u16 {
208        self.num_channels_allocated
209    }
210
211    #[nonblocking]
212    fn num_frames_allocated(&self) -> usize {
213        self.num_frames_allocated
214    }
215
216    #[nonblocking]
217    fn layout(&self) -> crate::BlockLayout {
218        crate::BlockLayout::Sequential
219    }
220
221    #[nonblocking]
222    fn sample(&self, channel: u16, frame: usize) -> S {
223        assert!(channel < self.num_channels);
224        assert!(frame < self.num_frames);
225        unsafe {
226            *self
227                .data
228                .get_unchecked(channel as usize * self.num_frames_allocated + frame)
229        }
230    }
231
232    #[nonblocking]
233    fn channel_iter(&self, channel: u16) -> impl Iterator<Item = &S> {
234        assert!(channel < self.num_channels);
235        self.data
236            .iter()
237            .skip(channel as usize * self.num_frames_allocated)
238            .take(self.num_frames)
239    }
240
241    #[nonblocking]
242    fn channels_iter(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
243        let num_frames = self.num_frames; // Active frames per channel
244        let num_frames_allocated = self.num_frames_allocated; // Allocated frames per channel (chunk size)
245
246        self.data
247            .chunks(num_frames_allocated)
248            .take(self.num_channels as usize)
249            .map(move |channel_chunk| channel_chunk.iter().take(num_frames))
250    }
251
252    #[nonblocking]
253    fn frame_iter(&self, frame: usize) -> impl Iterator<Item = &S> {
254        assert!(frame < self.num_frames);
255        self.data
256            .iter()
257            .skip(frame)
258            .step_by(self.num_frames_allocated)
259            .take(self.num_channels as usize)
260    }
261
262    #[nonblocking]
263    fn frame_iters(&self) -> impl Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
264        let num_channels = self.num_channels as usize;
265        let num_frames = self.num_frames;
266        let stride = self.num_frames_allocated;
267        let data_ptr = self.data.as_ptr();
268
269        (0..num_frames).map(move |frame_idx| {
270            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
271            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
272            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
273            // But if data is empty, num_channels or num_frames must be 0.
274            let start_ptr = if self.data.is_empty() {
275                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
276            } else {
277                // Safety: channel_idx is < num_channels <= num_channels_allocated.
278                // Adding it to a valid data_ptr is safe within slice bounds.
279                unsafe { data_ptr.add(frame_idx) }
280            };
281
282            StridedSampleIter::<'_, S> {
283                // Note: '_ lifetime from &self borrow
284                // Safety: Pointer is either dangling (if empty) or valid start pointer.
285                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
286                ptr: NonNull::new(start_ptr as *mut S).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
287                stride,
288                remaining: num_channels, // If 0, iterator yields None immediately
289                _marker: PhantomData,
290            }
291        })
292    }
293
294    #[nonblocking]
295    fn as_view(&self) -> impl AudioBlock<S> {
296        self.view()
297    }
298
299    #[nonblocking]
300    fn as_sequential_view(&self) -> Option<AudioBlockSequentialView<'_, S>> {
301        Some(self.view())
302    }
303}
304
305impl<S: Sample> AudioBlockMut<S> for AudioBlockSequential<S> {
306    type PlanarViewMut = [S; 0];
307
308    #[nonblocking]
309    fn set_active_num_channels(&mut self, num_channels: u16) {
310        assert!(num_channels <= self.num_channels_allocated);
311        self.num_channels = num_channels;
312    }
313
314    #[nonblocking]
315    fn set_active_num_frames(&mut self, num_frames: usize) {
316        assert!(num_frames <= self.num_frames_allocated);
317        self.num_frames = num_frames;
318    }
319
320    #[nonblocking]
321    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
322        assert!(channel < self.num_channels);
323        assert!(frame < self.num_frames);
324        unsafe {
325            self.data
326                .get_unchecked_mut(channel as usize * self.num_frames_allocated + frame)
327        }
328    }
329
330    #[nonblocking]
331    fn channel_iter_mut(&mut self, channel: u16) -> impl Iterator<Item = &mut S> {
332        assert!(channel < self.num_channels);
333        self.data
334            .iter_mut()
335            .skip(channel as usize * self.num_frames_allocated)
336            .take(self.num_frames)
337    }
338
339    #[nonblocking]
340    fn channels_iter_mut(
341        &mut self,
342    ) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
343        let num_frames = self.num_frames;
344        let num_frames_allocated = self.num_frames_allocated;
345        self.data
346            .chunks_mut(num_frames_allocated)
347            .take(self.num_channels as usize)
348            .map(move |channel_chunk| channel_chunk.iter_mut().take(num_frames))
349    }
350
351    #[nonblocking]
352    fn frame_iter_mut(&mut self, frame: usize) -> impl Iterator<Item = &mut S> {
353        assert!(frame < self.num_frames);
354        self.data
355            .iter_mut()
356            .skip(frame)
357            .step_by(self.num_frames_allocated)
358            .take(self.num_channels as usize)
359    }
360
361    #[nonblocking]
362    fn frames_iter_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
363        let num_channels = self.num_channels as usize;
364        let num_frames = self.num_frames;
365        let stride = self.num_frames_allocated;
366        let data_ptr = self.data.as_mut_ptr();
367
368        (0..num_frames).map(move |frame_idx| {
369            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
370            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
371            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
372            // But if data is empty, num_channels or num_frames must be 0.
373            let start_ptr = if self.data.is_empty() {
374                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
375            } else {
376                // Safety: channel_idx is < num_channels <= num_channels_allocated.
377                // Adding it to a valid data_ptr is safe within slice bounds.
378                unsafe { data_ptr.add(frame_idx) }
379            };
380
381            StridedSampleIterMut::<'_, S> {
382                // Note: '_ lifetime from &self borrow
383                // Safety: Pointer is either dangling (if empty) or valid start pointer.
384                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
385                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
386                stride,
387                remaining: num_channels, // If 0, iterator yields None immediately
388                _marker: PhantomData,
389            }
390        })
391    }
392
393    #[nonblocking]
394    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
395        self.view_mut()
396    }
397
398    #[nonblocking]
399    fn as_sequential_view_mut(&mut self) -> Option<AudioBlockSequentialViewMut<'_, S>> {
400        Some(self.view_mut())
401    }
402}
403
404impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockSequential<S> {
405    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
406        writeln!(f, "AudioBlockSequential {{")?;
407        writeln!(f, "  num_channels: {}", self.num_channels)?;
408        writeln!(f, "  num_frames: {}", self.num_frames)?;
409        writeln!(
410            f,
411            "  num_channels_allocated: {}",
412            self.num_channels_allocated
413        )?;
414        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
415        writeln!(f, "  channels:")?;
416
417        for (i, channel) in self.channels().enumerate() {
418            writeln!(f, "    {}: {:?}", i, channel)?;
419        }
420
421        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
422        writeln!(f, "}}")?;
423
424        Ok(())
425    }
426}
427
428#[cfg(test)]
429mod tests {
430    use super::*;
431    use crate::interleaved::AudioBlockInterleavedView;
432    use rtsan_standalone::no_sanitize_realtime;
433
434    #[test]
435    fn test_member_functions() {
436        let mut block = AudioBlockSequential::<f32>::new(3, 4);
437        block.channel_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
438        block.channel_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
439        block.set_active_size(2, 3);
440
441        // single frame
442        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
443        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
444
445        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
446        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
447
448        // all frames
449        let mut channels = block.channels();
450        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
451        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
452        assert_eq!(channels.next(), None);
453        drop(channels);
454
455        let mut channels = block.channels_mut();
456        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
457        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
458        assert_eq!(channels.next(), None);
459        drop(channels);
460
461        // raw data
462        assert_eq!(
463            block.raw_data(),
464            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
465        );
466
467        // views
468        let view = block.view();
469        assert_eq!(view.num_channels(), block.num_channels());
470        assert_eq!(view.num_frames(), block.num_frames());
471        assert_eq!(
472            view.num_channels_allocated(),
473            block.num_channels_allocated()
474        );
475        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
476        assert_eq!(view.raw_data(), block.raw_data());
477
478        let num_channels = block.num_channels();
479        let num_frames = block.num_frames();
480        let num_channels_allocated = block.num_channels_allocated();
481        let num_frames_allocated = block.num_frames_allocated();
482        let data = block.raw_data().to_vec();
483        let view = block.view_mut();
484        assert_eq!(view.num_channels(), num_channels);
485        assert_eq!(view.num_frames(), num_frames);
486        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
487        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
488        assert_eq!(view.raw_data(), &data);
489    }
490
491    #[test]
492    fn test_samples() {
493        let mut block = AudioBlockSequential::<f32>::new(2, 5);
494
495        let num_frames = block.num_frames();
496        for ch in 0..block.num_channels() {
497            for f in 0..block.num_frames() {
498                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
499            }
500        }
501
502        for ch in 0..block.num_channels() {
503            for f in 0..block.num_frames() {
504                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
505            }
506        }
507
508        assert_eq!(
509            block.raw_data(),
510            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
511        );
512    }
513
514    #[test]
515    fn test_channel_iter() {
516        let mut block = AudioBlockSequential::<f32>::new(2, 5);
517
518        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
519        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
520        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
521        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
522
523        block
524            .channel_iter_mut(0)
525            .enumerate()
526            .for_each(|(i, v)| *v = i as f32);
527        block
528            .channel_iter_mut(1)
529            .enumerate()
530            .for_each(|(i, v)| *v = i as f32 + 10.0);
531
532        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
533        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
534        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
535        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
536    }
537
538    #[test]
539    fn test_channel_iters() {
540        let mut block = AudioBlockSequential::<f32>::new(2, 5);
541
542        let mut channels_iter = block.channels_iter();
543        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
544        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
545        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
546        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
547        assert!(channels_iter.next().is_none());
548        drop(channels_iter);
549
550        let mut channels_iter = block.channels_iter_mut();
551        channels_iter
552            .next()
553            .unwrap()
554            .enumerate()
555            .for_each(|(i, v)| *v = i as f32);
556        channels_iter
557            .next()
558            .unwrap()
559            .enumerate()
560            .for_each(|(i, v)| *v = i as f32 + 10.0);
561        assert!(channels_iter.next().is_none());
562        drop(channels_iter);
563
564        let mut channels_iter = block.channels_iter();
565        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
566        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
567        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
568        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
569        assert!(channels_iter.next().is_none());
570        drop(channels_iter);
571    }
572
573    #[test]
574    fn test_frame_iter() {
575        let mut block = AudioBlockSequential::<f32>::new(2, 5);
576
577        for i in 0..block.num_frames() {
578            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
579            assert_eq!(frame, vec![0.0, 0.0]);
580        }
581
582        for i in 0..block.num_frames() {
583            let add = i as f32 * 10.0;
584            block
585                .frame_iter_mut(i)
586                .enumerate()
587                .for_each(|(i, v)| *v = i as f32 + add);
588        }
589
590        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
591        assert_eq!(channel, vec![0.0, 1.0]);
592        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
593        assert_eq!(channel, vec![10.0, 11.0]);
594        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
595        assert_eq!(channel, vec![20.0, 21.0]);
596        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
597        assert_eq!(channel, vec![30.0, 31.0]);
598        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
599        assert_eq!(channel, vec![40.0, 41.0]);
600    }
601
602    #[test]
603    fn test_frame_iters() {
604        let mut block = AudioBlockSequential::<f32>::new(3, 6);
605        block.set_active_size(2, 5);
606
607        let num_frames = block.num_frames;
608        let mut frames_iter = block.frame_iters();
609        for _ in 0..num_frames {
610            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
611            assert_eq!(frame, vec![0.0, 0.0]);
612        }
613        assert!(frames_iter.next().is_none());
614        drop(frames_iter);
615
616        let mut frames_iter = block.frames_iter_mut();
617        for i in 0..num_frames {
618            let add = i as f32 * 10.0;
619            frames_iter
620                .next()
621                .unwrap()
622                .enumerate()
623                .for_each(|(i, v)| *v = i as f32 + add);
624        }
625        assert!(frames_iter.next().is_none());
626        drop(frames_iter);
627
628        let mut frames_iter = block.frame_iters();
629        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
630        assert_eq!(frame, vec![0.0, 1.0]);
631        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
632        assert_eq!(frame, vec![10.0, 11.0]);
633        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
634        assert_eq!(frame, vec![20.0, 21.0]);
635        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
636        assert_eq!(frame, vec![30.0, 31.0]);
637        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
638        assert_eq!(frame, vec![40.0, 41.0]);
639        assert!(frames_iter.next().is_none());
640    }
641
642    #[test]
643    fn test_from_slice() {
644        let block =
645            AudioBlockSequential::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
646                &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
647                2,
648                5,
649            ));
650        assert_eq!(block.num_channels(), 2);
651        assert_eq!(block.num_channels_allocated(), 2);
652        assert_eq!(block.num_frames(), 5);
653        assert_eq!(block.num_frames_allocated(), 5);
654        assert_eq!(
655            block.channel_iter(0).copied().collect::<Vec<_>>(),
656            vec![0.0, 2.0, 4.0, 6.0, 8.0]
657        );
658        assert_eq!(
659            block.channel_iter(1).copied().collect::<Vec<_>>(),
660            vec![1.0, 3.0, 5.0, 7.0, 9.0]
661        );
662        assert_eq!(
663            block.frame_iter(0).copied().collect::<Vec<_>>(),
664            vec![0.0, 1.0]
665        );
666        assert_eq!(
667            block.frame_iter(1).copied().collect::<Vec<_>>(),
668            vec![2.0, 3.0]
669        );
670        assert_eq!(
671            block.frame_iter(2).copied().collect::<Vec<_>>(),
672            vec![4.0, 5.0]
673        );
674        assert_eq!(
675            block.frame_iter(3).copied().collect::<Vec<_>>(),
676            vec![6.0, 7.0]
677        );
678        assert_eq!(
679            block.frame_iter(4).copied().collect::<Vec<_>>(),
680            vec![8.0, 9.0]
681        );
682    }
683
684    #[test]
685    fn test_view() {
686        let block =
687            AudioBlockSequential::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
688                &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
689                2,
690                5,
691            ));
692        assert!(block.as_interleaved_view().is_none());
693        assert!(block.as_planar_view().is_none());
694        assert!(block.as_sequential_view().is_some());
695        let view = block.as_view();
696        assert_eq!(
697            view.channel_iter(0).copied().collect::<Vec<_>>(),
698            vec![0.0, 2.0, 4.0, 6.0, 8.0]
699        );
700        assert_eq!(
701            view.channel_iter(1).copied().collect::<Vec<_>>(),
702            vec![1.0, 3.0, 5.0, 7.0, 9.0]
703        );
704    }
705
706    #[test]
707    fn test_view_mut() {
708        let mut block = AudioBlockSequential::<f32>::new(2, 5);
709        assert!(block.as_interleaved_view().is_none());
710        assert!(block.as_planar_view().is_none());
711        assert!(block.as_sequential_view().is_some());
712        {
713            let mut view = block.as_view_mut();
714            view.channel_iter_mut(0)
715                .enumerate()
716                .for_each(|(i, v)| *v = i as f32);
717            view.channel_iter_mut(1)
718                .enumerate()
719                .for_each(|(i, v)| *v = i as f32 + 10.0);
720        }
721
722        assert_eq!(
723            block.channel_iter(0).copied().collect::<Vec<_>>(),
724            vec![0.0, 1.0, 2.0, 3.0, 4.0]
725        );
726        assert_eq!(
727            block.channel_iter(1).copied().collect::<Vec<_>>(),
728            vec![10.0, 11.0, 12.0, 13.0, 14.0]
729        );
730    }
731
732    #[test]
733    #[should_panic]
734    #[no_sanitize_realtime]
735    fn test_slice_out_of_bounds() {
736        let mut block = AudioBlockSequential::<f32>::new(3, 6);
737        block.set_active_size(2, 5);
738        block.channel(2);
739    }
740
741    #[test]
742    #[should_panic]
743    #[no_sanitize_realtime]
744    fn test_slice_out_of_bounds_mut() {
745        let mut block = AudioBlockSequential::<f32>::new(3, 6);
746        block.set_active_size(2, 5);
747        block.channel_mut(2);
748    }
749
750    #[test]
751    fn test_resize() {
752        let mut block = AudioBlockSequential::<f32>::new(3, 10);
753        assert_eq!(block.num_channels(), 3);
754        assert_eq!(block.num_frames(), 10);
755        assert_eq!(block.num_channels_allocated(), 3);
756        assert_eq!(block.num_frames_allocated(), 10);
757
758        for i in 0..block.num_channels() {
759            assert_eq!(block.channel_iter(i).count(), 10);
760            assert_eq!(block.channel_iter_mut(i).count(), 10);
761        }
762        for i in 0..block.num_frames() {
763            assert_eq!(block.frame_iter(i).count(), 3);
764            assert_eq!(block.frame_iter_mut(i).count(), 3);
765        }
766
767        block.set_active_size(3, 10);
768        block.set_active_size(2, 5);
769
770        assert_eq!(block.num_channels(), 2);
771        assert_eq!(block.num_frames(), 5);
772        assert_eq!(block.num_channels_allocated(), 3);
773        assert_eq!(block.num_frames_allocated(), 10);
774
775        for i in 0..block.num_channels() {
776            assert_eq!(block.channel_iter(i).count(), 5);
777            assert_eq!(block.channel_iter_mut(i).count(), 5);
778        }
779        for i in 0..block.num_frames() {
780            assert_eq!(block.frame_iter(i).count(), 2);
781            assert_eq!(block.frame_iter_mut(i).count(), 2);
782        }
783    }
784
785    #[test]
786    #[should_panic]
787    #[no_sanitize_realtime]
788    fn test_wrong_resize_channels() {
789        let mut block = AudioBlockSequential::<f32>::new(2, 10);
790        block.set_active_size(3, 10);
791    }
792
793    #[test]
794    #[should_panic]
795    #[no_sanitize_realtime]
796    fn test_wrong_resize_frames() {
797        let mut block = AudioBlockSequential::<f32>::new(2, 10);
798        block.set_active_size(2, 11);
799    }
800
801    #[test]
802    #[should_panic]
803    #[no_sanitize_realtime]
804    fn test_wrong_channel() {
805        let mut block = AudioBlockSequential::<f32>::new(2, 10);
806        block.set_active_size(1, 10);
807        let _ = block.channel_iter(1);
808    }
809
810    #[test]
811    #[should_panic]
812    #[no_sanitize_realtime]
813    fn test_wrong_frame() {
814        let mut block = AudioBlockSequential::<f32>::new(2, 10);
815        block.set_active_size(2, 5);
816        let _ = block.frame_iter(5);
817    }
818
819    #[test]
820    #[should_panic]
821    #[no_sanitize_realtime]
822    fn test_wrong_channel_mut() {
823        let mut block = AudioBlockSequential::<f32>::new(2, 10);
824        block.set_active_size(1, 10);
825        let _ = block.channel_iter_mut(1);
826    }
827}