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}