Skip to main content

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