Skip to main content

audio_blocks/mono/
view_mut.rs

1use rtsan_standalone::nonblocking;
2
3use super::view::MonoView;
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::MonoViewMut, AudioBlock};
18///
19/// let mut data = vec![0.0, 1.0, 2.0, 3.0, 4.0];
20/// let mut block = MonoViewMut::from_slice(&mut data);
21///
22/// *block.sample_mut(0) = 10.0;
23/// assert_eq!(block.sample(0), 10.0);
24/// ```
25pub struct MonoViewMut<'a, S: Sample> {
26    data: &'a mut [S],
27    num_frames: usize,
28    num_frames_allocated: usize,
29}
30
31impl<'a, S: Sample> MonoViewMut<'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::MonoViewMut, AudioBlock};
41    ///
42    /// let mut samples = [1.0, 2.0, 3.0, 4.0, 5.0];
43    /// let mut block = MonoViewMut::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::MonoViewMut, AudioBlock};
74    ///
75    /// let mut samples = [1.0, 2.0, 3.0, 4.0, 5.0];
76    /// let mut block = MonoViewMut::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::MonoViewMut, AudioBlock};
108    ///
109    /// let mut samples = [1.0, 2.0, 3.0, 4.0, 5.0];
110    /// let mut block = unsafe { MonoViewMut::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) -> MonoView<'_, S> {
197        MonoView::from_slice_limited(self.data, self.num_frames, self.num_frames_allocated)
198    }
199
200    #[nonblocking]
201    pub fn view_mut(&mut self) -> MonoViewMut<'_, S> {
202        MonoViewMut::from_slice_limited(self.data, self.num_frames, self.num_frames_allocated)
203    }
204}
205
206impl<S: Sample> AudioBlock<S> for MonoViewMut<'_, S> {
207    type PlanarView = [S; 0];
208
209    #[nonblocking]
210    fn num_channels(&self) -> u16 {
211        1
212    }
213
214    #[nonblocking]
215    fn num_frames(&self) -> usize {
216        self.num_frames
217    }
218
219    #[nonblocking]
220    fn num_channels_allocated(&self) -> u16 {
221        1
222    }
223
224    #[nonblocking]
225    fn num_frames_allocated(&self) -> usize {
226        self.num_frames_allocated
227    }
228
229    #[nonblocking]
230    fn layout(&self) -> crate::BlockLayout {
231        crate::BlockLayout::Sequential
232    }
233
234    #[nonblocking]
235    fn sample(&self, channel: u16, frame: usize) -> S {
236        assert_eq!(channel, 0, "MonoViewMut only has channel 0");
237        self.sample(frame)
238    }
239
240    #[nonblocking]
241    fn channel_iter(&self, channel: u16) -> impl ExactSizeIterator<Item = &S> {
242        assert_eq!(channel, 0, "MonoViewMut only has channel 0");
243        self.samples().iter()
244    }
245
246    #[nonblocking]
247    fn channels_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
248        core::iter::once(self.samples().iter())
249    }
250
251    #[nonblocking]
252    fn frame_iter(&self, frame: usize) -> impl ExactSizeIterator<Item = &S> {
253        assert!(frame < self.num_frames);
254        core::iter::once(&self.data[frame])
255    }
256
257    #[nonblocking]
258    fn frames_iter(&self) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &S>> {
259        self.data.iter().take(self.num_frames).map(core::iter::once)
260    }
261
262    #[nonblocking]
263    fn as_view(&self) -> impl AudioBlock<S> {
264        self.view()
265    }
266}
267
268impl<S: Sample> AudioBlockMut<S> for MonoViewMut<'_, S> {
269    type PlanarViewMut = [S; 0];
270
271    #[nonblocking]
272    fn set_num_channels_visible(&mut self, num_channels: u16) {
273        assert_eq!(
274            num_channels, 1,
275            "audio_blocks::MonoViewMut can only have 1 channel, got {}",
276            num_channels
277        );
278    }
279
280    #[nonblocking]
281    fn set_num_frames_visible(&mut self, num_frames: usize) {
282        assert!(num_frames <= self.num_frames_allocated);
283        self.num_frames = num_frames;
284    }
285
286    #[nonblocking]
287    fn sample_mut(&mut self, channel: u16, frame: usize) -> &mut S {
288        assert_eq!(channel, 0, "audio_blocks::MonoViewMut only has channel 0");
289        self.sample_mut(frame)
290    }
291
292    #[nonblocking]
293    fn channel_iter_mut(&mut self, channel: u16) -> impl ExactSizeIterator<Item = &mut S> {
294        assert_eq!(channel, 0, "audio_blocks::MonoViewMut only has channel 0");
295        self.samples_mut().iter_mut()
296    }
297
298    #[nonblocking]
299    fn channels_iter_mut(
300        &mut self,
301    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
302        core::iter::once(self.samples_mut().iter_mut())
303    }
304
305    #[nonblocking]
306    fn frame_iter_mut(&mut self, frame: usize) -> impl ExactSizeIterator<Item = &mut S> {
307        assert!(frame < self.num_frames);
308        let ptr = &mut self.data[frame] as *mut S;
309        core::iter::once(unsafe { &mut *ptr })
310    }
311
312    #[nonblocking]
313    fn frames_iter_mut(
314        &mut self,
315    ) -> impl ExactSizeIterator<Item = impl ExactSizeIterator<Item = &mut S>> {
316        let num_frames = self.num_frames;
317        self.data.iter_mut().take(num_frames).map(core::iter::once)
318    }
319
320    #[nonblocking]
321    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
322        self.view_mut()
323    }
324}
325
326impl<S: Sample + core::fmt::Debug> core::fmt::Debug for MonoViewMut<'_, S> {
327    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
328        writeln!(f, "audio_blocks::MonoViewMut {{")?;
329        writeln!(f, "  num_frames: {}", self.num_frames)?;
330        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
331        writeln!(f, "  samples: {:?}", self.samples())?;
332        writeln!(f, "}}")?;
333        Ok(())
334    }
335}
336
337#[cfg(test)]
338mod tests {
339    use super::*;
340    use rtsan_standalone::no_sanitize_realtime;
341
342    #[test]
343    fn test_from_slice() {
344        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
345        let block = MonoViewMut::from_slice(&mut data);
346        assert_eq!(block.num_frames(), 5);
347        assert_eq!(block.num_frames_allocated(), 5);
348        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
349    }
350
351    #[test]
352    fn test_from_slice_limited() {
353        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
354        let block = MonoViewMut::from_slice_limited(&mut data, 3, 5);
355        assert_eq!(block.num_frames(), 3);
356        assert_eq!(block.num_frames_allocated(), 5);
357        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
358        assert_eq!(block.raw_data(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
359    }
360
361    #[test]
362    fn test_from_ptr() {
363        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
364        let block = unsafe { MonoViewMut::from_ptr(data.as_mut_ptr(), 5) };
365        assert_eq!(block.num_frames(), 5);
366        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
367    }
368
369    #[test]
370    fn test_from_ptr_limited() {
371        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
372        let block = unsafe { MonoViewMut::from_ptr_limited(data.as_mut_ptr(), 3, 5) };
373        assert_eq!(block.num_frames(), 3);
374        assert_eq!(block.num_frames_allocated(), 5);
375        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
376    }
377
378    #[test]
379    fn test_sample_access() {
380        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
381        let mut block = MonoViewMut::from_slice(&mut data);
382        assert_eq!(block.sample(0), 1.0);
383        assert_eq!(block.sample(2), 3.0);
384        assert_eq!(block.sample(4), 5.0);
385
386        *block.sample_mut(2) = 10.0;
387        assert_eq!(block.sample(2), 10.0);
388    }
389
390    #[test]
391    fn test_samples_iter() {
392        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
393        let mut block = MonoViewMut::from_slice(&mut data);
394
395        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
396
397        for sample in block.samples_mut() {
398            *sample *= 2.0;
399        }
400
401        assert_eq!(block.samples(), &[2.0, 4.0, 6.0, 8.0, 10.0]);
402    }
403
404    #[test]
405    fn test_fill_and_clear() {
406        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
407        let mut block = MonoViewMut::from_slice(&mut data);
408
409        block.samples_mut().fill(0.5);
410        assert_eq!(block.samples(), &[0.5, 0.5, 0.5, 0.5, 0.5]);
411
412        for s in block.samples_mut() {
413            *s = 0.0;
414        }
415        assert_eq!(block.samples(), &[0.0, 0.0, 0.0, 0.0, 0.0]);
416    }
417
418    #[test]
419    fn test_audio_blocks_trait() {
420        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
421        let block = MonoViewMut::from_slice(&mut data);
422
423        assert_eq!(block.num_channels(), 1);
424        assert_eq!(block.num_frames(), 5);
425
426        // Test channel_iter
427        let channel: Vec<f32> = block.channel_iter(0).copied().collect();
428        assert_eq!(channel, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
429
430        // Test frame_iter
431        let frame: Vec<f32> = block.frame_iter(2).copied().collect();
432        assert_eq!(frame, vec![3.0]);
433    }
434
435    #[test]
436    fn test_audio_blocks_mut_trait() {
437        let mut data = [0.0, 0.0, 0.0, 0.0, 0.0];
438        let mut block = MonoViewMut::from_slice(&mut data);
439
440        for (i, sample) in block.channel_iter_mut(0).enumerate() {
441            *sample = i as f32;
442        }
443
444        assert_eq!(block.samples(), &[0.0, 1.0, 2.0, 3.0, 4.0]);
445    }
446
447    #[test]
448    fn test_set_num_frames_visible() {
449        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
450        let mut block = MonoViewMut::from_slice(&mut data);
451
452        block.set_num_frames_visible(3);
453        assert_eq!(block.num_frames(), 3);
454        assert_eq!(block.num_frames_allocated(), 5);
455        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
456    }
457
458    #[test]
459    fn test_views() {
460        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
461        let mut block = MonoViewMut::from_slice(&mut data);
462
463        // Test immutable view
464        {
465            let view = block.view();
466            assert_eq!(view.num_frames(), 5);
467            assert_eq!(view.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
468        }
469
470        // Test mutable view
471        {
472            let mut view_mut = block.view_mut();
473            *view_mut.sample_mut(2) = 10.0;
474        }
475
476        assert_eq!(block.sample(2), 10.0);
477    }
478
479    #[test]
480    #[should_panic]
481    #[no_sanitize_realtime]
482    fn test_sample_out_of_bounds() {
483        let mut data = [1.0, 2.0, 3.0];
484        let block = MonoViewMut::from_slice(&mut data);
485        let _ = block.sample(10);
486    }
487
488    #[test]
489    #[should_panic]
490    #[no_sanitize_realtime]
491    fn test_sample_mut_out_of_bounds() {
492        let mut data = [1.0, 2.0, 3.0];
493        let mut block = MonoViewMut::from_slice(&mut data);
494        let _ = block.sample_mut(10);
495    }
496
497    #[test]
498    #[should_panic]
499    #[no_sanitize_realtime]
500    fn test_wrong_channel() {
501        let mut data = [1.0, 2.0, 3.0];
502        let block = MonoViewMut::from_slice(&mut data);
503        let _ = block.channel_iter(1);
504    }
505
506    #[test]
507    #[should_panic]
508    #[no_sanitize_realtime]
509    fn test_set_num_frames_beyond_allocated() {
510        let mut data = [1.0, 2.0, 3.0];
511        let mut block = MonoViewMut::from_slice(&mut data);
512        block.set_num_frames_visible(10);
513    }
514}