rusty_daw_core/
block_buffer.rs

1use std::mem::MaybeUninit;
2use std::ops::Range;
3
4/// An audio buffer with a single channel.
5///
6/// This has a constant number of frames (`MAX_BLOCKSIZE`), so this can be allocated on
7/// the stack.
8#[derive(Debug)]
9pub struct MonoBlockBuffer<T: Default + Copy + Clone, const MAX_BLOCKSIZE: usize> {
10    pub buf: [T; MAX_BLOCKSIZE],
11}
12
13impl<T: Default + Copy + Clone, const MAX_BLOCKSIZE: usize> MonoBlockBuffer<T, MAX_BLOCKSIZE> {
14    /// Create a new buffer.
15    ///
16    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
17    ///
18    /// All samples will be cleared to 0.
19    pub fn new() -> Self {
20        Self {
21            buf: [T::default(); MAX_BLOCKSIZE],
22        }
23    }
24
25    /// Create a new buffer without initializing.
26    ///
27    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
28    ///
29    /// ## Undefined behavior
30    /// This data will be unitialized, so undefined behavior may occur if you try to read
31    /// any data without writing to it first.
32    pub unsafe fn new_uninit() -> Self {
33        Self {
34            buf: MaybeUninit::uninit().assume_init(),
35        }
36    }
37
38    /// Create a new buffer that only initializes the given number of frames to 0. Any samples
39    /// after `frames` will be uninitialized.
40    ///
41    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
42    ///
43    /// ## Undefined behavior
44    /// The portion of data not in the given range will be unitialized, so undefined behavior
45    /// may occur if you try to read any of that data without writing to it first.
46    pub unsafe fn new_uninit_after_frames(frames: usize) -> Self {
47        let frames = frames.min(MAX_BLOCKSIZE);
48        let mut buf: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
49
50        let buf_part = &mut buf[0..frames];
51        buf_part.fill(T::default());
52
53        Self { buf }
54    }
55
56    /// Create a new buffer that only initializes the given range of data to 0.
57    ///
58    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
59    ///
60    /// ## Undefined behavior
61    /// The portion of data not in the given range will be unitialized, so undefined behavior
62    /// may occur if you try to read any of that data without writing to it first.
63    ///
64    /// ## Panics
65    /// This will panic if the given range lies outside the valid range `[0, N)`.
66    pub unsafe fn new_partially_uninit(init_range: Range<usize>) -> Self {
67        let mut buf: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
68
69        let buf_part = &mut buf[init_range];
70        buf_part.fill(T::default());
71
72        Self { buf }
73    }
74
75    /// Clear all samples in the buffer to 0.
76    #[inline]
77    pub fn clear(&mut self) {
78        self.buf.fill(T::default());
79    }
80
81    /// Clear a number of frames in the buffer to 0.
82    #[inline]
83    pub fn clear_frames(&mut self, frames: usize) {
84        let frames = frames.min(MAX_BLOCKSIZE);
85        self.buf[0..frames].fill(T::default());
86    }
87
88    /// Clear a range in the buffer to 0.
89    ///
90    /// ## Panics
91    /// This will panic if the given range lies outside the valid range `[0, N)`.
92    pub fn clear_range(&mut self, range: Range<usize>) {
93        let buf_part = &mut self.buf[range];
94        buf_part.fill(T::default());
95    }
96
97    /// Copy all frames from `src` to this buffer.
98    #[inline]
99    pub fn copy_from(&mut self, src: &MonoBlockBuffer<T, MAX_BLOCKSIZE>) {
100        self.buf.copy_from_slice(&src.buf);
101    }
102
103    /// Copy the given number of `frames` from `src` to this buffer.
104    #[inline]
105    pub fn copy_frames_from(&mut self, src: &MonoBlockBuffer<T, MAX_BLOCKSIZE>, frames: usize) {
106        let frames = frames.min(MAX_BLOCKSIZE);
107        self.buf[0..frames].copy_from_slice(&src.buf[0..frames]);
108    }
109}
110
111impl<T, I, const MAX_BLOCKSIZE: usize> std::ops::Index<I> for MonoBlockBuffer<T, MAX_BLOCKSIZE>
112where
113    I: std::slice::SliceIndex<[T]>,
114    T: Default + Copy + Clone,
115{
116    type Output = I::Output;
117
118    #[inline]
119    fn index(&self, idx: I) -> &I::Output {
120        &self.buf[idx]
121    }
122}
123
124impl<T, I, const MAX_BLOCKSIZE: usize> std::ops::IndexMut<I> for MonoBlockBuffer<T, MAX_BLOCKSIZE>
125where
126    I: std::slice::SliceIndex<[T]>,
127    T: Default + Copy + Clone,
128{
129    #[inline]
130    fn index_mut(&mut self, idx: I) -> &mut I::Output {
131        &mut self.buf[idx]
132    }
133}
134
135/// An audio buffer with two channels.
136///
137/// This has a constant number of frames (`MAX_BLOCKSIZE`), so this can be allocated on
138/// the stack.
139#[derive(Debug)]
140pub struct StereoBlockBuffer<T: Default + Copy + Clone, const MAX_BLOCKSIZE: usize> {
141    pub left: [T; MAX_BLOCKSIZE],
142    pub right: [T; MAX_BLOCKSIZE],
143}
144
145impl<T: Default + Copy + Clone, const MAX_BLOCKSIZE: usize> StereoBlockBuffer<T, MAX_BLOCKSIZE> {
146    /// Create a new buffer.
147    ///
148    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
149    ///
150    /// All samples will be cleared to 0.
151    pub fn new() -> Self {
152        Self {
153            left: [T::default(); MAX_BLOCKSIZE],
154            right: [T::default(); MAX_BLOCKSIZE],
155        }
156    }
157
158    /// Create a new buffer without initializing.
159    ///
160    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
161    ///
162    /// ## Undefined behavior
163    /// This data will be unitialized, so undefined behavior may occur if you try to read
164    /// any data without writing to it first.
165    pub unsafe fn new_uninit() -> Self {
166        Self {
167            left: MaybeUninit::uninit().assume_init(),
168            right: MaybeUninit::uninit().assume_init(),
169        }
170    }
171
172    /// Create a new buffer that only initializes the given number of frames to 0. Any samples
173    /// after `frames` will be uninitialized.
174    ///
175    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
176    ///
177    /// ## Undefined behavior
178    /// The portion of data not in the given range will be unitialized, so undefined behavior
179    /// may occur if you try to read any of that data without writing to it first.
180    pub unsafe fn new_uninit_after_frames(frames: usize) -> Self {
181        let frames = frames.min(MAX_BLOCKSIZE);
182        let mut buf_left: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
183        let mut buf_right: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
184
185        let buf_left_part = &mut buf_left[0..frames];
186        let buf_right_part = &mut buf_right[0..frames];
187        buf_left_part.fill(T::default());
188        buf_right_part.fill(T::default());
189
190        Self {
191            left: buf_left,
192            right: buf_right,
193        }
194    }
195
196    /// Create a new buffer that only initializes the given range of data to 0.
197    ///
198    /// This is a constant size (`MAX_BLOCKSIZE`), so this can be allocated on the stack.
199    ///
200    /// ## Undefined behavior
201    /// The portion of data not in the given range will be unitialized, so undefined behavior
202    /// may occur if you try to read any of that data without writing to it first.
203    ///
204    /// ## Panics
205    /// This will panic if the given range lies outside the valid range `[0, N)`.
206    pub unsafe fn new_partially_uninit(init_range: Range<usize>) -> Self {
207        let mut buf_left: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
208        let mut buf_right: [T; MAX_BLOCKSIZE] = MaybeUninit::uninit().assume_init();
209
210        let buf_left_part = &mut buf_left[init_range.clone()];
211        let buf_right_part = &mut buf_right[init_range];
212        buf_left_part.fill(T::default());
213        buf_right_part.fill(T::default());
214
215        Self {
216            left: buf_left,
217            right: buf_right,
218        }
219    }
220
221    /// Clear all samples in the buffer to 0.
222    #[inline]
223    pub fn clear(&mut self) {
224        self.left.fill(T::default());
225        self.right.fill(T::default());
226    }
227
228    /// Clear a number of frames in the buffer to 0.
229    #[inline]
230    pub fn clear_frames(&mut self, frames: usize) {
231        let frames = frames.min(MAX_BLOCKSIZE);
232        self.left[0..frames].fill(T::default());
233        self.right[0..frames].fill(T::default());
234    }
235
236    /// Clear a range in the buffer to 0.
237    ///
238    /// ## Panics
239    /// This will panic if the given range lies outside the valid range `[0, N)`.
240    pub fn clear_range(&mut self, range: Range<usize>) {
241        let buf_left_part = &mut self.left[range.clone()];
242        let buf_right_part = &mut self.right[range];
243        buf_left_part.fill(T::default());
244        buf_right_part.fill(T::default());
245    }
246
247    /// Copy all frames from `src` to this buffer.
248    #[inline]
249    pub fn copy_from(&mut self, src: &StereoBlockBuffer<T, MAX_BLOCKSIZE>) {
250        self.left.copy_from_slice(&src.left);
251        self.right.copy_from_slice(&src.right);
252    }
253
254    /// Copy the given number of `frames` from `src` to this buffer.
255    #[inline]
256    pub fn copy_frames_from(&mut self, src: &StereoBlockBuffer<T, MAX_BLOCKSIZE>, frames: usize) {
257        let frames = frames.min(MAX_BLOCKSIZE);
258        self.left[0..frames].copy_from_slice(&src.left[0..frames]);
259        self.right[0..frames].copy_from_slice(&src.right[0..frames]);
260    }
261
262    /// Return a mutable reference to the left and right channels (in that order).
263    pub fn left_right_mut(&mut self) -> (&mut [T; MAX_BLOCKSIZE], &mut [T; MAX_BLOCKSIZE]) {
264        (&mut self.left, &mut self.right)
265    }
266}