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 Iterator<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 Iterator<Item = impl Iterator<Item = &S> + '_> + '_ {
256        core::iter::once(self.samples().iter())
257    }
258
259    #[nonblocking]
260    fn frame_iter(&self, frame: usize) -> impl Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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 Iterator<Item = impl Iterator<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 Iterator<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(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut S> + '_> + '_ {
322        let num_frames = self.num_frames;
323        self.data.iter_mut().take(num_frames).map(core::iter::once)
324    }
325
326    #[nonblocking]
327    fn as_view_mut(&mut self) -> impl AudioBlockMut<S> {
328        self.view_mut()
329    }
330}
331
332impl<S: Sample + core::fmt::Debug> core::fmt::Debug for AudioBlockMonoViewMut<'_, S> {
333    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
334        writeln!(f, "AudioBlockMonoViewMut {{")?;
335        writeln!(f, "  num_frames: {}", self.num_frames)?;
336        writeln!(f, "  num_frames_allocated: {}", self.num_frames_allocated)?;
337        writeln!(f, "  samples: {:?}", self.samples())?;
338        writeln!(f, "}}")?;
339        Ok(())
340    }
341}
342
343#[cfg(test)]
344mod tests {
345    use super::*;
346    use rtsan_standalone::no_sanitize_realtime;
347
348    #[test]
349    fn test_from_slice() {
350        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
351        let block = AudioBlockMonoViewMut::from_slice(&mut data);
352        assert_eq!(block.num_frames(), 5);
353        assert_eq!(block.num_frames_allocated(), 5);
354        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
355    }
356
357    #[test]
358    fn test_from_slice_limited() {
359        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
360        let block = AudioBlockMonoViewMut::from_slice_limited(&mut data, 3, 5);
361        assert_eq!(block.num_frames(), 3);
362        assert_eq!(block.num_frames_allocated(), 5);
363        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
364        assert_eq!(block.raw_data(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
365    }
366
367    #[test]
368    fn test_from_ptr() {
369        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
370        let block = unsafe { AudioBlockMonoViewMut::from_ptr(data.as_mut_ptr(), 5) };
371        assert_eq!(block.num_frames(), 5);
372        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
373    }
374
375    #[test]
376    fn test_from_ptr_limited() {
377        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
378        let block = unsafe { AudioBlockMonoViewMut::from_ptr_limited(data.as_mut_ptr(), 3, 5) };
379        assert_eq!(block.num_frames(), 3);
380        assert_eq!(block.num_frames_allocated(), 5);
381        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
382    }
383
384    #[test]
385    fn test_sample_access() {
386        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
387        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
388        assert_eq!(block.sample(0), 1.0);
389        assert_eq!(block.sample(2), 3.0);
390        assert_eq!(block.sample(4), 5.0);
391
392        *block.sample_mut(2) = 10.0;
393        assert_eq!(block.sample(2), 10.0);
394    }
395
396    #[test]
397    fn test_samples_iter() {
398        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
399        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
400
401        assert_eq!(block.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
402
403        for sample in block.samples_mut() {
404            *sample *= 2.0;
405        }
406
407        assert_eq!(block.samples(), &[2.0, 4.0, 6.0, 8.0, 10.0]);
408    }
409
410    #[test]
411    fn test_fill_and_clear() {
412        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
413        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
414
415        block.samples_mut().fill(0.5);
416        assert_eq!(block.samples(), &[0.5, 0.5, 0.5, 0.5, 0.5]);
417
418        for s in block.samples_mut() {
419            *s = 0.0;
420        }
421        assert_eq!(block.samples(), &[0.0, 0.0, 0.0, 0.0, 0.0]);
422    }
423
424    #[test]
425    fn test_audio_block_trait() {
426        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
427        let block = AudioBlockMonoViewMut::from_slice(&mut data);
428
429        assert_eq!(block.num_channels(), 1);
430        assert_eq!(block.num_frames(), 5);
431
432        // Test channel_iter
433        let channel: Vec<f32> = block.channel_iter(0).copied().collect();
434        assert_eq!(channel, vec![1.0, 2.0, 3.0, 4.0, 5.0]);
435
436        // Test frame_iter
437        let frame: Vec<f32> = block.frame_iter(2).copied().collect();
438        assert_eq!(frame, vec![3.0]);
439    }
440
441    #[test]
442    fn test_audio_block_mut_trait() {
443        let mut data = [0.0, 0.0, 0.0, 0.0, 0.0];
444        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
445
446        for (i, sample) in block.channel_iter_mut(0).enumerate() {
447            *sample = i as f32;
448        }
449
450        assert_eq!(block.samples(), &[0.0, 1.0, 2.0, 3.0, 4.0]);
451    }
452
453    #[test]
454    fn test_set_num_frames_visible() {
455        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
456        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
457
458        block.set_num_frames_visible(3);
459        assert_eq!(block.num_frames(), 3);
460        assert_eq!(block.num_frames_allocated(), 5);
461        assert_eq!(block.samples(), &[1.0, 2.0, 3.0]);
462    }
463
464    #[test]
465    fn test_views() {
466        let mut data = [1.0, 2.0, 3.0, 4.0, 5.0];
467        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
468
469        // Test immutable view
470        {
471            let view = block.view();
472            assert_eq!(view.num_frames(), 5);
473            assert_eq!(view.samples(), &[1.0, 2.0, 3.0, 4.0, 5.0]);
474        }
475
476        // Test mutable view
477        {
478            let mut view_mut = block.view_mut();
479            *view_mut.sample_mut(2) = 10.0;
480        }
481
482        assert_eq!(block.sample(2), 10.0);
483    }
484
485    #[test]
486    #[should_panic]
487    #[no_sanitize_realtime]
488    fn test_sample_out_of_bounds() {
489        let mut data = [1.0, 2.0, 3.0];
490        let block = AudioBlockMonoViewMut::from_slice(&mut data);
491        let _ = block.sample(10);
492    }
493
494    #[test]
495    #[should_panic]
496    #[no_sanitize_realtime]
497    fn test_sample_mut_out_of_bounds() {
498        let mut data = [1.0, 2.0, 3.0];
499        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
500        let _ = block.sample_mut(10);
501    }
502
503    #[test]
504    #[should_panic]
505    #[no_sanitize_realtime]
506    fn test_wrong_channel() {
507        let mut data = [1.0, 2.0, 3.0];
508        let block = AudioBlockMonoViewMut::from_slice(&mut data);
509        let _ = block.channel_iter(1);
510    }
511
512    #[test]
513    #[should_panic]
514    #[no_sanitize_realtime]
515    fn test_set_num_frames_beyond_allocated() {
516        let mut data = [1.0, 2.0, 3.0];
517        let mut block = AudioBlockMonoViewMut::from_slice(&mut data);
518        block.set_num_frames_visible(10);
519    }
520}