audio_blocks/sequential/
owned.rs

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