Skip to main content

audio_blocks/mono/
view_mut.rs

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