firewheel_core/dsp/
buffer.rs

1use core::num::NonZeroUsize;
2
3use arrayvec::ArrayVec;
4
5#[cfg(not(feature = "std"))]
6use bevy_platform::prelude::Vec;
7
8/// A memory-efficient buffer of samples with `CHANNELS` channels. Each channel
9/// has a length of `frames`.
10pub struct ChannelBuffer<T: Clone + Copy + Default, const CHANNELS: usize> {
11    buffer: Vec<T>,
12    frames: usize,
13}
14
15impl<T: Clone + Copy + Default, const CHANNELS: usize> ChannelBuffer<T, CHANNELS> {
16    pub const fn empty() -> Self {
17        assert!(CHANNELS > 0);
18
19        Self {
20            buffer: Vec::new(),
21            frames: 0,
22        }
23    }
24
25    pub fn new(frames: usize) -> Self {
26        assert!(CHANNELS > 0);
27
28        let buffer_len = frames * CHANNELS;
29
30        let mut buffer = Vec::new();
31        buffer.reserve_exact(buffer_len);
32        buffer.resize(buffer_len, Default::default());
33
34        Self { buffer, frames }
35    }
36
37    pub fn frames(&self) -> usize {
38        self.frames
39    }
40
41    /// Get an immutable reference to the first channel.
42    #[inline]
43    pub fn first(&self) -> &[T] {
44        // SAFETY:
45        //
46        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`.
47        unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), self.frames) }
48    }
49
50    /// Get a mutable reference to the first channel.
51    #[inline]
52    pub fn first_mut(&mut self) -> &mut [T] {
53        // SAFETY:
54        //
55        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`.
56        // * `self` is borrowed mutably in this method, so all mutability rules are
57        // being upheld.
58        unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), self.frames) }
59    }
60
61    /// Get an immutable reference to the first channel with the given number of
62    /// frames.
63    ///
64    /// The length of the returned slice will be either `frames` or the number of
65    /// frames in this buffer, whichever is smaller.
66    #[inline]
67    pub fn first_with_frames(&self, frames: usize) -> &[T] {
68        let frames = frames.min(self.frames);
69
70        // SAFETY:
71        //
72        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
73        // and we have constrained `frames` above, so this is always within range.
74        unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), frames) }
75    }
76
77    /// Get a mutable reference to the first channel with the given number of
78    /// frames.
79    ///
80    /// The length of the returned slice will be either `frames` or the number of
81    /// frames in this buffer, whichever is smaller.
82    #[inline]
83    pub fn first_with_frames_mut(&mut self, frames: usize) -> &mut [T] {
84        let frames = frames.min(self.frames);
85
86        // SAFETY:
87        //
88        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
89        // and we have constrained `frames` above, so this is always within range.
90        // * `self` is borrowed mutably in this method, so all mutability rules are
91        // being upheld.
92        unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), frames) }
93    }
94
95    /// Get an immutable reference to all channels in this buffer.
96    pub fn all(&self) -> [&[T]; CHANNELS] {
97        // SAFETY:
98        //
99        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`.
100        unsafe {
101            core::array::from_fn(|ch_i| {
102                core::slice::from_raw_parts(
103                    self.buffer.as_ptr().add(ch_i * self.frames),
104                    self.frames,
105                )
106            })
107        }
108    }
109
110    /// Get a mutable reference to all channels in this buffer.
111    pub fn all_mut(&mut self) -> [&mut [T]; CHANNELS] {
112        // SAFETY:
113        //
114        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`.
115        // * None of these slices overlap, and `self` is borrowed mutably in this method,
116        // so all mutability rules are being upheld.
117        unsafe {
118            core::array::from_fn(|ch_i| {
119                core::slice::from_raw_parts_mut(
120                    self.buffer.as_mut_ptr().add(ch_i * self.frames),
121                    self.frames,
122                )
123            })
124        }
125    }
126
127    /// Get an immutable reference to all channels with the given number of frames.
128    ///
129    /// The length of the returned slices will be either `frames` or the number of
130    /// frames in this buffer, whichever is smaller.
131    pub fn all_with_frames(&self, frames: usize) -> [&[T]; CHANNELS] {
132        let frames = frames.min(self.frames);
133
134        // SAFETY:
135        //
136        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
137        // and we have constrained `frames` above, so this is always within range.
138        unsafe {
139            core::array::from_fn(|ch_i| {
140                core::slice::from_raw_parts(self.buffer.as_ptr().add(ch_i * self.frames), frames)
141            })
142        }
143    }
144
145    /// Get a mutable reference to all channels with the given number of frames.
146    ///
147    /// The length of the returned slices will be either `frames` or the number of
148    /// frames in this buffer, whichever is smaller.
149    pub fn all_with_frames_mut(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
150        let frames = frames.min(self.frames);
151
152        // SAFETY:
153        //
154        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
155        // and we have constrained `frames` above, so this is always within range.
156        // * None of these slices overlap, and `self` is borrowed mutably in this method,
157        // so all mutability rules are being upheld.
158        unsafe {
159            core::array::from_fn(|ch_i| {
160                core::slice::from_raw_parts_mut(
161                    self.buffer.as_mut_ptr().add(ch_i * self.frames),
162                    frames,
163                )
164            })
165        }
166    }
167}
168
169/// A memory-efficient buffer of samples with up to `MAX_CHANNELS` channels. Each
170/// channel has a length of `frames`.
171pub struct VarChannelBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
172    buffer: Vec<T>,
173    channels: NonZeroUsize,
174    frames: usize,
175}
176
177impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> VarChannelBuffer<T, MAX_CHANNELS> {
178    pub fn new(channels: NonZeroUsize, frames: usize) -> Self {
179        assert!(channels.get() <= MAX_CHANNELS);
180
181        let buffer_len = frames * channels.get();
182
183        let mut buffer = Vec::new();
184        buffer.reserve_exact(buffer_len);
185        buffer.resize(buffer_len, Default::default());
186
187        Self {
188            buffer,
189            channels,
190            frames,
191        }
192    }
193
194    pub fn frames(&self) -> usize {
195        self.frames
196    }
197
198    pub fn num_channels(&self) -> NonZeroUsize {
199        self.channels
200    }
201
202    pub fn channels(&self, num_channels: usize, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
203        let frames = frames.min(self.frames);
204        let channels = num_channels.min(self.channels.get());
205
206        let mut res = ArrayVec::new();
207
208        // SAFETY:
209        //
210        // * The constructor has set the size of the buffer to`self.frames * self.channels`,
211        // and we have constrained `channels` and `frames` above, so this is always
212        // within range.
213        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
214        unsafe {
215            for ch_i in 0..channels {
216                res.push_unchecked(core::slice::from_raw_parts(
217                    self.buffer.as_ptr().add(ch_i * self.frames),
218                    frames,
219                ));
220            }
221        }
222
223        res
224    }
225
226    pub fn channels_mut(
227        &mut self,
228        num_channels: usize,
229        frames: usize,
230    ) -> ArrayVec<&mut [T], MAX_CHANNELS> {
231        let frames = frames.min(self.frames);
232        let channels = num_channels.min(self.channels.get());
233
234        let mut res = ArrayVec::new();
235
236        // SAFETY:
237        //
238        // * The constructor has set the size of the buffer to`self.frames * self.channels`,
239        // and we have constrained `channels` and `frames` above, so this is always
240        // within range.
241        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
242        // * None of these slices overlap, and `self` is borrowed mutably in this method,
243        // so all mutability rules are being upheld.
244        unsafe {
245            for ch_i in 0..channels {
246                res.push_unchecked(core::slice::from_raw_parts_mut(
247                    self.buffer.as_mut_ptr().add(ch_i * self.frames),
248                    frames,
249                ));
250            }
251        }
252
253        res
254    }
255}
256
257/// A memory-efficient buffer of samples with variable number of instances each with up to
258/// `MAX_CHANNELS` channels. Each channel has a length of `frames`.
259pub struct InstanceBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
260    buffer: Vec<T>,
261    num_instances: usize,
262    channels: NonZeroUsize,
263    frames: usize,
264}
265
266impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> InstanceBuffer<T, MAX_CHANNELS> {
267    pub fn new(num_instances: usize, channels: NonZeroUsize, frames: usize) -> Self {
268        assert!(channels.get() <= MAX_CHANNELS);
269
270        let buffer_len = frames * channels.get() * num_instances;
271
272        let mut buffer = Vec::new();
273        buffer.reserve_exact(buffer_len);
274        buffer.resize(buffer_len, Default::default());
275
276        Self {
277            buffer,
278            num_instances,
279            channels,
280            frames,
281        }
282    }
283
284    pub fn frames(&self) -> usize {
285        self.frames
286    }
287
288    pub fn num_channels(&self) -> NonZeroUsize {
289        self.channels
290    }
291
292    pub fn num_instances(&self) -> usize {
293        self.num_instances
294    }
295
296    pub fn instance(
297        &self,
298        instance_index: usize,
299        channels: usize,
300        frames: usize,
301    ) -> Option<ArrayVec<&[T], MAX_CHANNELS>> {
302        if instance_index >= self.num_instances {
303            return None;
304        }
305
306        let frames = frames.min(self.frames);
307        let channels = channels.min(self.channels.get());
308
309        let start_frame = instance_index * self.frames * self.channels.get();
310
311        let mut res = ArrayVec::new();
312
313        // SAFETY:
314        //
315        // * The constructor has set the size of the buffer to
316        // `self.frames * self.channels * self.num_instances`, and we have constrained
317        // `instance_index`, `channels` and `frames` above, so this is always within range.
318        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
319        unsafe {
320            for ch_i in 0..channels {
321                res.push_unchecked(core::slice::from_raw_parts(
322                    self.buffer.as_ptr().add(start_frame + (ch_i * self.frames)),
323                    frames,
324                ));
325            }
326        }
327
328        Some(res)
329    }
330
331    pub fn instance_mut(
332        &mut self,
333        instance_index: usize,
334        channels: usize,
335        frames: usize,
336    ) -> Option<ArrayVec<&mut [T], MAX_CHANNELS>> {
337        if instance_index >= self.num_instances {
338            return None;
339        }
340
341        let frames = frames.min(self.frames);
342        let channels = channels.min(self.channels.get());
343
344        let start_frame = instance_index * self.frames * self.channels.get();
345
346        let mut res = ArrayVec::new();
347
348        // SAFETY:
349        //
350        // * The constructor has set the size of the buffer to
351        // `self.frames * self.channels * self.num_instances`, and we have constrained
352        // `instance_index`, `channels` and `frames` above, so this is always within range.
353        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
354        // * None of these slices overlap, and `self` is borrowed mutably in this method,
355        // so all mutability rules are being upheld.
356        unsafe {
357            for ch_i in 0..channels {
358                res.push_unchecked(core::slice::from_raw_parts_mut(
359                    self.buffer
360                        .as_mut_ptr()
361                        .add(start_frame + (ch_i * self.frames)),
362                    frames,
363                ));
364            }
365        }
366
367        Some(res)
368    }
369}