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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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 ExactSizeIterator<Item = impl ExactSizeIterator<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 ExactSizeIterator<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(
430        &mut self,
431    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
432        let num_channels = self.num_channels as usize;
433        let num_frames = self.num_frames;
434        let stride = self.num_frames_allocated;
435        let data_ptr = self.data.as_mut_ptr();
436
437        (0..num_frames).map(move |frame_idx| {
438            // Safety check: Ensure data isn't empty if we calculate a start_ptr.
439            // If num_frames or num_channels is 0, remaining will be 0, iterator is safe.
440            // If data is empty, ptr is dangling, but add(0) is okay. add(>0) is UB.
441            // But if data is empty, num_channels or num_frames must be 0.
442            let start_ptr = if self.data.is_empty() {
443                NonNull::dangling().as_ptr() // Use dangling pointer if slice is empty
444            } else {
445                // Safety: channel_idx is < num_channels <= num_channels_allocated.
446                // Adding it to a valid data_ptr is safe within slice bounds.
447                unsafe { data_ptr.add(frame_idx) }
448            };
449
450            StridedSampleIterMut::<'_, S> {
451                // Note: '_ lifetime from &self borrow
452                // Safety: Pointer is either dangling (if empty) or valid start pointer.
453                // NonNull::new is safe if start_ptr is non-null (i.e., data not empty).
454                ptr: NonNull::new(start_ptr).unwrap_or(NonNull::dangling()), // Use dangling on null/empty
455                stride,
456                remaining: num_channels, // If 0, iterator yields None immediately
457                _marker: PhantomData,
458            }
459        })
460    }
461
462    #[nonblocking]
463    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
464        self.view_mut()
465    }
466
467    #[nonblocking]
468    fn as_sequential_view_mut(&mut self) -> Option<AudioBlockSequentialViewMut<'_, S>> {
469        Some(self.view_mut())
470    }
471}
472
473impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockSequential<S> {
474    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
475        writeln!(f, "AudioBlockSequential {{")?;
476        writeln!(f, "  num_channels: {}", self.num_channels)?;
477        writeln!(f, "  num_frames: {}", self.num_frames)?;
478        writeln!(
479            f,
480            "  num_channels_allocated: {}",
481            self.num_channels_allocated
482        )?;
483        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
484        writeln!(f, "  channels:")?;
485
486        for (i, channel) in self.channels().enumerate() {
487            writeln!(f, "    {}: {:?}", i, channel)?;
488        }
489
490        writeln!(f, "  raw_data: {:?}", self.raw_data())?;
491        writeln!(f, "}}")?;
492
493        Ok(())
494    }
495}
496
497#[cfg(test)]
498mod tests {
499    use super::*;
500    use crate::interleaved::AudioBlockInterleavedView;
501    use rtsan_standalone::no_sanitize_realtime;
502
503    #[test]
504    fn test_member_functions() {
505        let mut block = AudioBlockSequential::<f32>::new(3, 4);
506        block.channel_mut(0).copy_from_slice(&[0.0, 1.0, 2.0, 3.0]);
507        block.channel_mut(1).copy_from_slice(&[4.0, 5.0, 6.0, 7.0]);
508        block.set_visible(2, 3);
509
510        // single frame
511        assert_eq!(block.channel(0), &[0.0, 1.0, 2.0]);
512        assert_eq!(block.channel(1), &[4.0, 5.0, 6.0]);
513
514        assert_eq!(block.channel_mut(0), &[0.0, 1.0, 2.0]);
515        assert_eq!(block.channel_mut(1), &[4.0, 5.0, 6.0]);
516
517        // all frames
518        let mut channels = block.channels();
519        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
520        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
521        assert_eq!(channels.next(), None);
522        drop(channels);
523
524        let mut channels = block.channels_mut();
525        assert_eq!(channels.next().unwrap(), &[0.0, 1.0, 2.0]);
526        assert_eq!(channels.next().unwrap(), &[4.0, 5.0, 6.0]);
527        assert_eq!(channels.next(), None);
528        drop(channels);
529
530        // raw data
531        assert_eq!(
532            block.raw_data(),
533            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 0.0, 0.0, 0.0, 0.0]
534        );
535
536        // views
537        let view = block.view();
538        assert_eq!(view.num_channels(), block.num_channels());
539        assert_eq!(view.num_frames(), block.num_frames());
540        assert_eq!(
541            view.num_channels_allocated(),
542            block.num_channels_allocated()
543        );
544        assert_eq!(view.num_frames_allocated(), block.num_frames_allocated());
545        assert_eq!(view.raw_data(), block.raw_data());
546
547        let num_channels = block.num_channels();
548        let num_frames = block.num_frames();
549        let num_channels_allocated = block.num_channels_allocated();
550        let num_frames_allocated = block.num_frames_allocated();
551        let data = block.raw_data().to_vec();
552        let view = block.view_mut();
553        assert_eq!(view.num_channels(), num_channels);
554        assert_eq!(view.num_frames(), num_frames);
555        assert_eq!(view.num_channels_allocated(), num_channels_allocated);
556        assert_eq!(view.num_frames_allocated(), num_frames_allocated);
557        assert_eq!(view.raw_data(), &data);
558    }
559
560    #[test]
561    fn test_samples() {
562        let mut block = AudioBlockSequential::<f32>::new(2, 5);
563
564        let num_frames = block.num_frames();
565        for ch in 0..block.num_channels() {
566            for f in 0..block.num_frames() {
567                *block.sample_mut(ch, f) = (ch as usize * num_frames + f) as f32;
568            }
569        }
570
571        for ch in 0..block.num_channels() {
572            for f in 0..block.num_frames() {
573                assert_eq!(block.sample(ch, f), (ch as usize * num_frames + f) as f32);
574            }
575        }
576
577        assert_eq!(
578            block.raw_data(),
579            &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]
580        );
581    }
582
583    #[test]
584    fn test_channel_iter() {
585        let mut block = AudioBlockSequential::<f32>::new(2, 5);
586
587        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
588        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
589        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
590        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
591
592        block
593            .channel_iter_mut(0)
594            .enumerate()
595            .for_each(|(i, v)| *v = i as f32);
596        block
597            .channel_iter_mut(1)
598            .enumerate()
599            .for_each(|(i, v)| *v = i as f32 + 10.0);
600
601        let channel = block.channel_iter(0).copied().collect::<Vec<_>>();
602        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
603        let channel = block.channel_iter(1).copied().collect::<Vec<_>>();
604        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
605    }
606
607    #[test]
608    fn test_channel_iters() {
609        let mut block = AudioBlockSequential::<f32>::new(2, 5);
610
611        let mut channels_iter = block.channels_iter();
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        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
615        assert_eq!(channel, vec![0.0, 0.0, 0.0, 0.0, 0.0]);
616        assert!(channels_iter.next().is_none());
617        drop(channels_iter);
618
619        let mut channels_iter = block.channels_iter_mut();
620        channels_iter
621            .next()
622            .unwrap()
623            .enumerate()
624            .for_each(|(i, v)| *v = i as f32);
625        channels_iter
626            .next()
627            .unwrap()
628            .enumerate()
629            .for_each(|(i, v)| *v = i as f32 + 10.0);
630        assert!(channels_iter.next().is_none());
631        drop(channels_iter);
632
633        let mut channels_iter = block.channels_iter();
634        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
635        assert_eq!(channel, vec![0.0, 1.0, 2.0, 3.0, 4.0]);
636        let channel = channels_iter.next().unwrap().copied().collect::<Vec<_>>();
637        assert_eq!(channel, vec![10.0, 11.0, 12.0, 13.0, 14.0]);
638        assert!(channels_iter.next().is_none());
639        drop(channels_iter);
640    }
641
642    #[test]
643    fn test_frame_iter() {
644        let mut block = AudioBlockSequential::<f32>::new(2, 5);
645
646        for i in 0..block.num_frames() {
647            let frame = block.frame_iter(i).copied().collect::<Vec<_>>();
648            assert_eq!(frame, vec![0.0, 0.0]);
649        }
650
651        for i in 0..block.num_frames() {
652            let add = i as f32 * 10.0;
653            block
654                .frame_iter_mut(i)
655                .enumerate()
656                .for_each(|(i, v)| *v = i as f32 + add);
657        }
658
659        let channel = block.frame_iter(0).copied().collect::<Vec<_>>();
660        assert_eq!(channel, vec![0.0, 1.0]);
661        let channel = block.frame_iter(1).copied().collect::<Vec<_>>();
662        assert_eq!(channel, vec![10.0, 11.0]);
663        let channel = block.frame_iter(2).copied().collect::<Vec<_>>();
664        assert_eq!(channel, vec![20.0, 21.0]);
665        let channel = block.frame_iter(3).copied().collect::<Vec<_>>();
666        assert_eq!(channel, vec![30.0, 31.0]);
667        let channel = block.frame_iter(4).copied().collect::<Vec<_>>();
668        assert_eq!(channel, vec![40.0, 41.0]);
669    }
670
671    #[test]
672    fn test_frame_iters() {
673        let mut block = AudioBlockSequential::<f32>::new(3, 6);
674        block.set_visible(2, 5);
675
676        let num_frames = block.num_frames;
677        let mut frames_iter = block.frames_iter();
678        for _ in 0..num_frames {
679            let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
680            assert_eq!(frame, vec![0.0, 0.0]);
681        }
682        assert!(frames_iter.next().is_none());
683        drop(frames_iter);
684
685        let mut frames_iter = block.frames_iter_mut();
686        for i in 0..num_frames {
687            let add = i as f32 * 10.0;
688            frames_iter
689                .next()
690                .unwrap()
691                .enumerate()
692                .for_each(|(i, v)| *v = i as f32 + add);
693        }
694        assert!(frames_iter.next().is_none());
695        drop(frames_iter);
696
697        let mut frames_iter = block.frames_iter();
698        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
699        assert_eq!(frame, vec![0.0, 1.0]);
700        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
701        assert_eq!(frame, vec![10.0, 11.0]);
702        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
703        assert_eq!(frame, vec![20.0, 21.0]);
704        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
705        assert_eq!(frame, vec![30.0, 31.0]);
706        let frame = frames_iter.next().unwrap().copied().collect::<Vec<_>>();
707        assert_eq!(frame, vec![40.0, 41.0]);
708        assert!(frames_iter.next().is_none());
709    }
710
711    #[test]
712    fn test_from_slice() {
713        let block =
714            AudioBlockSequential::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
715                &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
716                2,
717            ));
718        assert_eq!(block.num_channels(), 2);
719        assert_eq!(block.num_channels_allocated(), 2);
720        assert_eq!(block.num_frames(), 5);
721        assert_eq!(block.num_frames_allocated(), 5);
722        assert_eq!(
723            block.channel_iter(0).copied().collect::<Vec<_>>(),
724            vec![0.0, 2.0, 4.0, 6.0, 8.0]
725        );
726        assert_eq!(
727            block.channel_iter(1).copied().collect::<Vec<_>>(),
728            vec![1.0, 3.0, 5.0, 7.0, 9.0]
729        );
730        assert_eq!(
731            block.frame_iter(0).copied().collect::<Vec<_>>(),
732            vec![0.0, 1.0]
733        );
734        assert_eq!(
735            block.frame_iter(1).copied().collect::<Vec<_>>(),
736            vec![2.0, 3.0]
737        );
738        assert_eq!(
739            block.frame_iter(2).copied().collect::<Vec<_>>(),
740            vec![4.0, 5.0]
741        );
742        assert_eq!(
743            block.frame_iter(3).copied().collect::<Vec<_>>(),
744            vec![6.0, 7.0]
745        );
746        assert_eq!(
747            block.frame_iter(4).copied().collect::<Vec<_>>(),
748            vec![8.0, 9.0]
749        );
750    }
751
752    #[test]
753    fn test_view() {
754        let block =
755            AudioBlockSequential::<f32>::from_block(&AudioBlockInterleavedView::from_slice(
756                &[0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0],
757                2,
758            ));
759        assert!(block.as_interleaved_view().is_none());
760        assert!(block.as_planar_view().is_none());
761        assert!(block.as_sequential_view().is_some());
762        let view = block.as_view();
763        assert_eq!(
764            view.channel_iter(0).copied().collect::<Vec<_>>(),
765            vec![0.0, 2.0, 4.0, 6.0, 8.0]
766        );
767        assert_eq!(
768            view.channel_iter(1).copied().collect::<Vec<_>>(),
769            vec![1.0, 3.0, 5.0, 7.0, 9.0]
770        );
771    }
772
773    #[test]
774    fn test_view_mut() {
775        let mut block = AudioBlockSequential::<f32>::new(2, 5);
776        assert!(block.as_interleaved_view().is_none());
777        assert!(block.as_planar_view().is_none());
778        assert!(block.as_sequential_view().is_some());
779        {
780            let mut view = block.as_view_mut();
781            view.channel_iter_mut(0)
782                .enumerate()
783                .for_each(|(i, v)| *v = i as f32);
784            view.channel_iter_mut(1)
785                .enumerate()
786                .for_each(|(i, v)| *v = i as f32 + 10.0);
787        }
788
789        assert_eq!(
790            block.channel_iter(0).copied().collect::<Vec<_>>(),
791            vec![0.0, 1.0, 2.0, 3.0, 4.0]
792        );
793        assert_eq!(
794            block.channel_iter(1).copied().collect::<Vec<_>>(),
795            vec![10.0, 11.0, 12.0, 13.0, 14.0]
796        );
797    }
798
799    #[test]
800    #[should_panic]
801    #[no_sanitize_realtime]
802    fn test_slice_out_of_bounds() {
803        let mut block = AudioBlockSequential::<f32>::new(3, 6);
804        block.set_visible(2, 5);
805        block.channel(2);
806    }
807
808    #[test]
809    #[should_panic]
810    #[no_sanitize_realtime]
811    fn test_slice_out_of_bounds_mut() {
812        let mut block = AudioBlockSequential::<f32>::new(3, 6);
813        block.set_visible(2, 5);
814        block.channel_mut(2);
815    }
816
817    #[test]
818    fn test_resize() {
819        let mut block = AudioBlockSequential::<f32>::new(3, 10);
820        assert_eq!(block.num_channels(), 3);
821        assert_eq!(block.num_frames(), 10);
822        assert_eq!(block.num_channels_allocated(), 3);
823        assert_eq!(block.num_frames_allocated(), 10);
824
825        for i in 0..block.num_channels() {
826            assert_eq!(block.channel_iter(i).count(), 10);
827            assert_eq!(block.channel_iter_mut(i).count(), 10);
828        }
829        for i in 0..block.num_frames() {
830            assert_eq!(block.frame_iter(i).count(), 3);
831            assert_eq!(block.frame_iter_mut(i).count(), 3);
832        }
833
834        block.set_visible(3, 10);
835        block.set_visible(2, 5);
836
837        assert_eq!(block.num_channels(), 2);
838        assert_eq!(block.num_frames(), 5);
839        assert_eq!(block.num_channels_allocated(), 3);
840        assert_eq!(block.num_frames_allocated(), 10);
841
842        for i in 0..block.num_channels() {
843            assert_eq!(block.channel_iter(i).count(), 5);
844            assert_eq!(block.channel_iter_mut(i).count(), 5);
845        }
846        for i in 0..block.num_frames() {
847            assert_eq!(block.frame_iter(i).count(), 2);
848            assert_eq!(block.frame_iter_mut(i).count(), 2);
849        }
850    }
851
852    #[test]
853    #[should_panic]
854    #[no_sanitize_realtime]
855    fn test_wrong_resize_channels() {
856        let mut block = AudioBlockSequential::<f32>::new(2, 10);
857        block.set_visible(3, 10);
858    }
859
860    #[test]
861    #[should_panic]
862    #[no_sanitize_realtime]
863    fn test_wrong_resize_frames() {
864        let mut block = AudioBlockSequential::<f32>::new(2, 10);
865        block.set_visible(2, 11);
866    }
867
868    #[test]
869    #[should_panic]
870    #[no_sanitize_realtime]
871    fn test_wrong_channel() {
872        let mut block = AudioBlockSequential::<f32>::new(2, 10);
873        block.set_visible(1, 10);
874        let _ = block.channel_iter(1);
875    }
876
877    #[test]
878    #[should_panic]
879    #[no_sanitize_realtime]
880    fn test_wrong_frame() {
881        let mut block = AudioBlockSequential::<f32>::new(2, 10);
882        block.set_visible(2, 5);
883        let _ = block.frame_iter(5);
884    }
885
886    #[test]
887    #[should_panic]
888    #[no_sanitize_realtime]
889    fn test_wrong_channel_mut() {
890        let mut block = AudioBlockSequential::<f32>::new(2, 10);
891        block.set_visible(1, 10);
892        let _ = block.channel_iter_mut(1);
893    }
894}