Skip to main content

audio_blocks/mono/
owned.rs

1use rtsan_standalone::{blocking, nonblocking};
2
3#[cfg(all(feature = "alloc", not(feature = "std")))]
4use alloc::{boxed::Box, vec, vec::Vec};
5#[cfg(all(feature = "std", not(feature = "alloc")))]
6use std::{boxed::Box, vec, vec::Vec};
7#[cfg(all(feature = "std", feature = "alloc"))]
8use std::{boxed::Box, vec, vec::Vec};
9
10use super::{view::MonoView, view_mut::MonoViewMut};
11use crate::{AudioBlock, AudioBlockMut, Sample};
12
13/// A mono (single-channel) audio block that owns its data.
14///
15/// This is a simplified version of the multi-channel audio blocks, optimized for
16/// mono audio processing with a streamlined API that doesn't require channel indexing.
17///
18/// * **Layout:** `[sample0, sample1, sample2, ...]`
19/// * **Interpretation:** A simple sequence of samples representing a single audio channel.
20/// * **Usage:** Ideal for mono audio processing, side-chain signals, or any single-channel audio data.
21///
22/// # Example
23///
24/// ```
25/// use audio_blocks::*;
26///
27/// let mut block = Mono::new(512);
28///
29/// // Fill with a simple ramp
30/// for (i, sample) in block.samples_mut().iter_mut().enumerate() {
31///     *sample = i as f32;
32/// }
33///
34/// assert_eq!(block.sample(0), 0.0);
35/// assert_eq!(block.sample(511), 511.0);
36/// ```
37#[derive(Default, Clone)]
38pub struct Mono<S: Sample> {
39    data: Box<[S]>,
40    num_frames: usize,
41    num_frames_allocated: usize,
42}
43
44impl<S: Sample + Default> Mono<S> {
45    /// Creates a new mono audio block with the specified number of frames.
46    ///
47    /// Allocates memory for a new mono audio block with exactly the specified
48    /// number of frames. The block is initialized with the default value (zero)
49    /// for the sample type.
50    ///
51    /// Do not use in real-time processes!
52    ///
53    /// # Arguments
54    ///
55    /// * `num_frames` - The number of frames (samples)
56    ///
57    /// # Example
58    ///
59    /// ```
60    /// use audio_blocks::{mono::Mono, AudioBlock};
61    ///
62    /// let block = Mono::<f32>::new(1024);
63    /// assert_eq!(block.num_frames(), 1024);
64    /// ```
65    #[blocking]
66    pub fn new(num_frames: usize) -> Self {
67        Self {
68            data: vec![S::default(); num_frames].into_boxed_slice(),
69            num_frames,
70            num_frames_allocated: num_frames,
71        }
72    }
73}
74
75impl<S: Sample> Mono<S> {
76    /// Creates a new mono audio block from a slice of samples.
77    ///
78    /// Copies the provided slice into a new owned mono block.
79    ///
80    /// # Warning
81    ///
82    /// This function allocates memory and should not be used in real-time audio processing contexts.
83    ///
84    /// # Arguments
85    ///
86    /// * `samples` - The slice of samples to copy
87    #[blocking]
88    pub fn from_slice(samples: &[S]) -> Self {
89        Self {
90            data: samples.to_vec().into_boxed_slice(),
91            num_frames: samples.len(),
92            num_frames_allocated: samples.len(),
93        }
94    }
95
96    /// Creates a new mono audio block from a slice of samples.
97    ///
98    /// Copies the provided slice into a new owned mono block.
99    ///
100    /// # Warning
101    ///
102    /// This function allocates memory and should not be used in real-time audio processing contexts.
103    ///
104    /// # Arguments
105    ///
106    /// * `samples` - The slice of samples to copy
107    /// * `num_frames_visible` - Number of audio frames to expose
108    #[blocking]
109    pub fn from_slice_limited(samples: &[S], num_frames_visible: usize) -> Self {
110        assert!(num_frames_visible <= samples.len());
111        Self {
112            data: samples.to_vec().into_boxed_slice(),
113            num_frames: num_frames_visible,
114            num_frames_allocated: samples.len(),
115        }
116    }
117
118    /// Creates a new mono audio block by copying data from another [`AudioBlock`].
119    ///
120    /// Extracts the first channel from any [`AudioBlock`] implementation.
121    /// If the source block has no channels, creates an empty mono block.
122    ///
123    /// # Warning
124    ///
125    /// This function allocates memory and should not be used in real-time audio processing contexts.
126    ///
127    /// # Arguments
128    ///
129    /// * `block` - The source audio block to copy data from (first channel will be used)
130    ///
131    /// # Panics
132    ///
133    /// Panics if the source block has zero channels.
134    #[blocking]
135    pub fn from_block(block: &impl AudioBlock<S>) -> Self {
136        assert!(
137            block.num_channels() > 0,
138            "Cannot create mono block from block with zero channels"
139        );
140
141        let mut data = Vec::with_capacity(block.num_frames());
142        block.channel_iter(0).for_each(|&v| data.push(v));
143
144        Self {
145            data: data.into_boxed_slice(),
146            num_frames: block.num_frames(),
147            num_frames_allocated: block.num_frames(),
148        }
149    }
150
151    /// Returns the sample at the specified frame index.
152    ///
153    /// # Panics
154    ///
155    /// Panics if frame index is out of bounds.
156    #[nonblocking]
157    pub fn sample(&self, frame: usize) -> S {
158        assert!(frame < self.num_frames);
159        unsafe { *self.data.get_unchecked(frame) }
160    }
161
162    /// Returns a mutable reference to the sample at the specified frame index.
163    ///
164    /// # Panics
165    ///
166    /// Panics if frame index is out of bounds.
167    #[nonblocking]
168    pub fn sample_mut(&mut self, frame: usize) -> &mut S {
169        assert!(frame < self.num_frames);
170        unsafe { self.data.get_unchecked_mut(frame) }
171    }
172
173    /// Provides direct access to the underlying samples as a slice.
174    ///
175    /// Returns only the visible samples (up to `num_frames`).
176    #[nonblocking]
177    pub fn samples(&self) -> &[S] {
178        &self.data[..self.num_frames]
179    }
180
181    /// Provides direct mutable access to the underlying samples as a slice.
182    ///
183    /// Returns only the visible samples (up to `num_frames`).
184    #[nonblocking]
185    pub fn samples_mut(&mut self) -> &mut [S] {
186        let num_frames = self.num_frames;
187        &mut self.data[..num_frames]
188    }
189
190    /// Provides direct access to all allocated memory, including reserved capacity.
191    ///
192    /// This gives access to the full allocated buffer, including any frames
193    /// beyond the visible range.
194    #[nonblocking]
195    pub fn raw_data(&self) -> &[S] {
196        &self.data
197    }
198
199    /// Provides direct mutable access to all allocated memory, including reserved capacity.
200    ///
201    /// This gives mutable access to the full allocated buffer, including any frames
202    /// beyond the visible range.
203    #[nonblocking]
204    pub fn raw_data_mut(&mut self) -> &mut [S] {
205        &mut self.data
206    }
207
208    /// Creates a view of this mono audio block.
209    #[nonblocking]
210    pub fn view(&self) -> MonoView<'_, S> {
211        MonoView::from_slice_limited(self.raw_data(), self.num_frames, self.num_frames_allocated)
212    }
213
214    /// Creates a mutable view of this mono audio block.
215    #[nonblocking]
216    pub fn view_mut(&mut self) -> MonoViewMut<'_, S> {
217        let num_frames = self.num_frames;
218        let num_frames_allocated = self.num_frames_allocated;
219        MonoViewMut::from_slice_limited(self.raw_data_mut(), num_frames, num_frames_allocated)
220    }
221}
222
223impl<S: Sample> AudioBlock<S> for Mono<S> {
224    type PlanarView = [S; 0];
225
226    #[nonblocking]
227    fn num_channels(&self) -> u16 {
228        1
229    }
230
231    #[nonblocking]
232    fn num_frames(&self) -> usize {
233        self.num_frames
234    }
235
236    #[nonblocking]
237    fn num_channels_allocated(&self) -> u16 {
238        1
239    }
240
241    #[nonblocking]
242    fn num_frames_allocated(&self) -> usize {
243        self.num_frames_allocated
244    }
245
246    #[nonblocking]
247    fn layout(&self) -> crate::BlockLayout {
248        crate::BlockLayout::Sequential
249    }
250
251    #[nonblocking]
252    fn sample(&self, channel: u16, frame: usize) -> S {
253        assert_eq!(channel, 0, "Mono only has channel 0");
254        self.sample(frame)
255    }
256
257    #[nonblocking]
258    fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
259        assert_eq!(channel, 0, "Mono only has channel 0");
260        self.samples().iter()
261    }
262
263    #[nonblocking]
264    fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
265        core::iter::once(self.samples().iter())
266    }
267
268    #[nonblocking]
269    fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
270        assert!(frame < self.num_frames);
271        core::iter::once(&self.data[frame])
272    }
273
274    #[nonblocking]
275    fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
276        self.data.iter().take(self.num_frames).map(core::iter::once)
277    }
278
279    #[nonblocking]
280    fn as_view(&self) -> impl AudioBlock<S> {
281        MonoView::from_slice_limited(self.raw_data(), self.num_frames, self.num_frames_allocated)
282    }
283}
284
285impl<S: Sample> AudioBlockMut<S> for Mono<S> {
286    type PlanarViewMut = [S; 0];
287
288    #[nonblocking]
289    fn set_num_channels_visible(&mut self, num_channels: u16) {
290        assert_eq!(
291            num_channels, 1,
292            "Mono can only have 1 channel, got {}",
293            num_channels
294        );
295    }
296
297    #[nonblocking]
298    fn set_num_frames_visible(&mut self, num_frames: usize) {
299        assert!(
300            num_frames <= self.num_frames_allocated,
301            "Cannot set visible frames ({}) beyond allocated frames ({})",
302            num_frames,
303            self.num_frames_allocated
304        );
305        self.num_frames = num_frames;
306    }
307
308    #[nonblocking]
309    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
310        assert_eq!(channel, 0, "audio_blocks::Mono only has channel 0");
311        self.sample_mut(frame)
312    }
313
314    #[nonblocking]
315    fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S> {
316        assert_eq!(channel, 0, "audio_blocks::Mono only has channel 0");
317        self.samples_mut().iter_mut()
318    }
319
320    #[nonblocking]
321    fn channels_iter_mut(
322        &mut self,
323    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
324        core::iter::once(self.samples_mut().iter_mut())
325    }
326
327    #[nonblocking]
328    fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S> {
329        assert!(frame < self.num_frames);
330        let ptr = &mut self.data[frame] as *mut S;
331        // Safety: We're creating a single-item iterator from a valid mutable reference
332        core::iter::once(unsafe { &mut *ptr })
333    }
334
335    #[nonblocking]
336    fn frames_iter_mut(
337        &mut self,
338    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
339        let num_frames = self.num_frames;
340        self.data.iter_mut().take(num_frames).map(core::iter::once)
341    }
342
343    #[nonblocking]
344    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
345        let num_frames = self.num_frames;
346        let num_frames_allocated = self.num_frames_allocated;
347        MonoViewMut::from_slice_limited(self.raw_data_mut(), num_frames, num_frames_allocated)
348    }
349}
350
351impl<S: Sample + core::fmt::Debug> core::fmt::Debug for Mono<S> {
352    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
353        writeln!(f, "audio_blocks::Mono {{")?;
354        writeln!(f, "  num_frames: {}", self.num_frames)?;
355        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
356        writeln!(f, "  samples: {:?}", self.samples())?;
357        writeln!(f, "}}")?;
358        Ok(())
359    }
360}
361
362#[cfg(test)]
363mod tests {
364    use super::*;
365    use rtsan_standalone::no_sanitize_realtime;
366
367    #[test]
368    fn test_new() {
369        let block = Mono::<f32>::new(1024);
370        assert_eq!(block.num_frames(), 1024);
371        assert_eq!(block.num_frames_allocated(), 1024);
372        assert!(block.samples().iter().all(|&s| s == 0.0));
373    }
374
375    #[test]
376    fn test_from_slice() {
377        let samples = [1.0, 2.0, 3.0, 4.0, 5.0];
378        let block = Mono::from_slice(&samples);
379        assert_eq!(block.num_frames(), 5);
380        assert_eq!(block.samples(), &samples);
381    }
382
383    #[test]
384    fn test_sample_access() {
385        let mut block = Mono::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);
386        assert_eq!(block.sample(0), 1.0);
387        assert_eq!(block.sample(2), 3.0);
388        assert_eq!(block.sample(4), 5.0);
389
390        *block.sample_mut(2) = 10.0;
391        assert_eq!(block.sample(2), 10.0);
392    }
393
394    #[test]
395    fn test_iterators() {
396        let mut block = Mono::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);
397
398        let sum: f32 = block.samples().iter().sum();
399        assert_eq!(sum, 15.0);
400
401        for sample in block.samples_mut() {
402            *sample *= 2.0;
403        }
404
405        assert_eq!(block.samples(), &[2.0, 4.0, 6.0, 8.0, 10.0]);
406    }
407
408    #[test]
409    #[should_panic]
410    #[no_sanitize_realtime]
411    fn test_resize_beyond_allocated() {
412        let mut block = Mono::<f32>::new(10);
413        block.set_num_frames_visible(11);
414    }
415
416    #[test]
417    fn test_audio_blocks_trait() {
418        let block = Mono::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);
419
420        assert_eq!(block.num_channels(), 1);
421        assert_eq!(block.num_frames(), 5);
422
423        // Test channel_iter
424        let channel: Vec<f32> = block.channel_iter(0).copied().collect();
425        assert_eq!(channel, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
426
427        // Test frame_iter
428        let frame: Vec<f32> = block.frame_iter(2).copied().collect();
429        assert_eq!(frame, vec![3.0]);
430    }
431
432    #[test]
433    fn test_audio_blocks_mut_trait() {
434        let mut block = Mono::<f32>::new(5);
435
436        for (i, sample) in block.channel_iter_mut(0).enumerate() {
437            *sample = i as f32;
438        }
439
440        assert_eq!(block.samples(), &[0.0, 1.0, 2.0, 3.0, 4.0]);
441    }
442
443    #[test]
444    #[should_panic]
445    #[no_sanitize_realtime]
446    fn test_wrong_channel() {
447        let block = Mono::<f32>::new(10);
448        let _ = block.channel_iter(1);
449    }
450
451    #[test]
452    #[should_panic]
453    #[no_sanitize_realtime]
454    fn test_sample_out_of_bounds() {
455        let block = Mono::<f32>::new(10);
456        let _ = block.sample(10);
457    }
458
459    #[test]
460    fn test_from_block() {
461        use crate::Interleaved;
462
463        let mut multi = Interleaved::<f32>::new(2, 5);
464        for (i, sample) in multi.channel_iter_mut(0).enumerate() {
465            *sample = i as f32;
466        }
467
468        let mono = Mono::from_block(&multi);
469        assert_eq!(mono.samples(), &[0.0, 1.0, 2.0, 3.0, 4.0]);
470    }
471
472    #[test]
473    fn test_views() {
474        let mut block = Mono::from_slice(&[1.0, 2.0, 3.0, 4.0, 5.0]);
475
476        // Test immutable view
477        {
478            let view = block.as_view();
479            assert_eq!(view.num_frames(), 5);
480            assert_eq!(view.sample(0, 2), 3.0);
481        }
482
483        // Test mutable view
484        {
485            let mut view_mut = block.as_view_mut();
486            *view_mut.sample_mut(0, 2) = 10.0;
487        }
488
489        assert_eq!(block.sample(2), 10.0);
490    }
491}