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`.
10#[derive(Debug)]
11pub struct ChannelBuffer<T: Clone + Copy + Default, const CHANNELS: usize> {
12 buffer: Vec<T>,
13 frames: usize,
14}
15
16impl<T: Clone + Copy + Default, const CHANNELS: usize> ChannelBuffer<T, CHANNELS> {
17 pub const fn empty() -> Self {
18 assert!(CHANNELS > 0);
19
20 Self {
21 buffer: Vec::new(),
22 frames: 0,
23 }
24 }
25
26 pub fn new(frames: usize) -> Self {
27 assert!(CHANNELS > 0);
28
29 let buffer_len = frames * CHANNELS;
30
31 let mut buffer = Vec::new();
32 buffer.reserve_exact(buffer_len);
33 buffer.resize(buffer_len, Default::default());
34
35 Self { buffer, frames }
36 }
37
38 pub fn frames(&self) -> usize {
39 self.frames
40 }
41
42 /// Get an immutable reference to the first channel.
43 #[inline]
44 pub fn first(&self) -> &[T] {
45 // SAFETY:
46 //
47 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
48 unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), self.frames) }
49 }
50
51 /// Get a mutable reference to the first channel.
52 #[inline]
53 pub fn first_mut(&mut self) -> &mut [T] {
54 // SAFETY:
55 //
56 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
57 // * `self` is borrowed mutably in this method, so all mutability rules are
58 // being upheld.
59 unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), self.frames) }
60 }
61
62 /// Get an immutable reference to the first channel with the given number of
63 /// frames.
64 ///
65 /// The length of the returned slice will be either `frames` or the number of
66 /// frames in this buffer, whichever is smaller.
67 #[inline]
68 pub fn first_with_frames(&self, frames: usize) -> &[T] {
69 let frames = frames.min(self.frames);
70
71 // SAFETY:
72 //
73 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
74 // and we have constrained `frames` above, so this is always within range.
75 unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), frames) }
76 }
77
78 /// Get a mutable reference to the first channel with the given number of
79 /// frames.
80 ///
81 /// The length of the returned slice will be either `frames` or the number of
82 /// frames in this buffer, whichever is smaller.
83 #[inline]
84 pub fn first_with_frames_mut(&mut self, frames: usize) -> &mut [T] {
85 let frames = frames.min(self.frames);
86
87 // SAFETY:
88 //
89 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
90 // and we have constrained `frames` above, so this is always within range.
91 // * `self` is borrowed mutably in this method, so all mutability rules are
92 // being upheld.
93 unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), frames) }
94 }
95
96 /// Get an immutable reference to the first given number of channels in this buffer.
97 pub fn channels<const NUM_CHANNELS: usize>(&self) -> [&[T]; NUM_CHANNELS] {
98 assert!(NUM_CHANNELS <= CHANNELS);
99
100 // SAFETY:
101 //
102 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
103 // and we have constrained NUM_CHANNELS above, so this is always within range.
104 unsafe {
105 core::array::from_fn(|ch_i| {
106 core::slice::from_raw_parts(
107 self.buffer.as_ptr().add(ch_i * self.frames),
108 self.frames,
109 )
110 })
111 }
112 }
113
114 /// Get a mutable reference to the first given number of channels in this buffer.
115 pub fn channels_mut<const NUM_CHANNELS: usize>(&mut self) -> [&mut [T]; NUM_CHANNELS] {
116 assert!(NUM_CHANNELS <= CHANNELS);
117
118 // SAFETY:
119 //
120 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
121 // and we have constrained NUM_CHANNELS above, so this is always within range.
122 // * None of these slices overlap, and `self` is borrowed mutably in this method,
123 // so all mutability rules are being upheld.
124 unsafe {
125 core::array::from_fn(|ch_i| {
126 core::slice::from_raw_parts_mut(
127 self.buffer.as_mut_ptr().add(ch_i * self.frames),
128 self.frames,
129 )
130 })
131 }
132 }
133
134 /// Get an immutable reference to the first given number of channels with the
135 /// given number of frames.
136 ///
137 /// The length of the returned slices will be either `frames` or the number of
138 /// frames in this buffer, whichever is smaller.
139 pub fn channels_with_frames<const NUM_CHANNELS: usize>(
140 &self,
141 frames: usize,
142 ) -> [&[T]; NUM_CHANNELS] {
143 assert!(NUM_CHANNELS <= CHANNELS);
144
145 let frames = frames.min(self.frames);
146
147 // SAFETY:
148 //
149 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
150 // and we have constrained NUM_CHANNELS and `frames` above, so this is always
151 // within range.
152 unsafe {
153 core::array::from_fn(|ch_i| {
154 core::slice::from_raw_parts(self.buffer.as_ptr().add(ch_i * self.frames), frames)
155 })
156 }
157 }
158
159 /// Get a mutable reference to the first given number of channels with the given
160 /// number of frames.
161 ///
162 /// The length of the returned slices will be either `frames` or the number of
163 /// frames in this buffer, whichever is smaller.
164 pub fn channels_with_frames_mut<const NUM_CHANNELS: usize>(
165 &mut self,
166 frames: usize,
167 ) -> [&mut [T]; NUM_CHANNELS] {
168 assert!(NUM_CHANNELS <= CHANNELS);
169
170 let frames = frames.min(self.frames);
171
172 // SAFETY:
173 //
174 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
175 // and we have constrained NUM_CHANNELS and `frames` above, so this is always
176 // within range.
177 // * None of these slices overlap, and `self` is borrowed mutably in this method,
178 // so all mutability rules are being upheld.
179 unsafe {
180 core::array::from_fn(|ch_i| {
181 core::slice::from_raw_parts_mut(
182 self.buffer.as_mut_ptr().add(ch_i * self.frames),
183 frames,
184 )
185 })
186 }
187 }
188
189 /// Get an immutable reference to all channels in this buffer.
190 pub fn all(&self) -> [&[T]; CHANNELS] {
191 // SAFETY:
192 //
193 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
194 unsafe {
195 core::array::from_fn(|ch_i| {
196 core::slice::from_raw_parts(
197 self.buffer.as_ptr().add(ch_i * self.frames),
198 self.frames,
199 )
200 })
201 }
202 }
203
204 /// Get a mutable reference to all channels in this buffer.
205 pub fn all_mut(&mut self) -> [&mut [T]; CHANNELS] {
206 // SAFETY:
207 //
208 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
209 // * None of these slices overlap, and `self` is borrowed mutably in this method,
210 // so all mutability rules are being upheld.
211 unsafe {
212 core::array::from_fn(|ch_i| {
213 core::slice::from_raw_parts_mut(
214 self.buffer.as_mut_ptr().add(ch_i * self.frames),
215 self.frames,
216 )
217 })
218 }
219 }
220
221 /// Get an immutable reference to all channels with the given number of frames.
222 ///
223 /// The length of the returned slices will be either `frames` or the number of
224 /// frames in this buffer, whichever is smaller.
225 pub fn all_with_frames(&self, frames: usize) -> [&[T]; CHANNELS] {
226 let frames = frames.min(self.frames);
227
228 // SAFETY:
229 //
230 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
231 // and we have constrained `frames` above, so this is always within range.
232 unsafe {
233 core::array::from_fn(|ch_i| {
234 core::slice::from_raw_parts(self.buffer.as_ptr().add(ch_i * self.frames), frames)
235 })
236 }
237 }
238
239 /// Get a mutable reference to all channels with the given number of frames.
240 ///
241 /// The length of the returned slices will be either `frames` or the number of
242 /// frames in this buffer, whichever is smaller.
243 pub fn all_with_frames_mut(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
244 let frames = frames.min(self.frames);
245
246 // SAFETY:
247 //
248 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
249 // and we have constrained `frames` above, so this is always within range.
250 // * None of these slices overlap, and `self` is borrowed mutably in this method,
251 // so all mutability rules are being upheld.
252 unsafe {
253 core::array::from_fn(|ch_i| {
254 core::slice::from_raw_parts_mut(
255 self.buffer.as_mut_ptr().add(ch_i * self.frames),
256 frames,
257 )
258 })
259 }
260 }
261}
262
263impl<T: Clone + Copy + Default, const CHANNELS: usize> Clone for ChannelBuffer<T, CHANNELS> {
264 fn clone(&self) -> Self {
265 // Ensure that `reserve_exact` is used when cloning.
266 let mut new_self = Self::new(self.frames);
267 new_self.buffer.copy_from_slice(&self.buffer);
268 new_self
269 }
270}
271
272/// A memory-efficient buffer of samples with up to `MAX_CHANNELS` channels. Each
273/// channel has a length of `frames`.
274#[derive(Debug)]
275pub struct VarChannelBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
276 buffer: Vec<T>,
277 channels: NonZeroUsize,
278 frames: usize,
279}
280
281impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> VarChannelBuffer<T, MAX_CHANNELS> {
282 pub fn new(channels: NonZeroUsize, frames: usize) -> Self {
283 assert!(channels.get() <= MAX_CHANNELS);
284
285 let buffer_len = frames * channels.get();
286
287 let mut buffer = Vec::new();
288 buffer.reserve_exact(buffer_len);
289 buffer.resize(buffer_len, Default::default());
290
291 Self {
292 buffer,
293 channels,
294 frames,
295 }
296 }
297
298 pub fn frames(&self) -> usize {
299 self.frames
300 }
301
302 pub fn num_channels(&self) -> NonZeroUsize {
303 self.channels
304 }
305
306 pub fn channels(&self, num_channels: usize, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
307 let frames = frames.min(self.frames);
308 let channels = num_channels.min(self.channels.get());
309
310 let mut res = ArrayVec::new();
311
312 // SAFETY:
313 //
314 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
315 // and we have constrained `channels` and `frames` above, so this is always
316 // within range.
317 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
318 unsafe {
319 for ch_i in 0..channels {
320 res.push_unchecked(core::slice::from_raw_parts(
321 self.buffer.as_ptr().add(ch_i * self.frames),
322 frames,
323 ));
324 }
325 }
326
327 res
328 }
329
330 pub fn channels_mut(
331 &mut self,
332 num_channels: usize,
333 frames: usize,
334 ) -> ArrayVec<&mut [T], MAX_CHANNELS> {
335 let frames = frames.min(self.frames);
336 let channels = num_channels.min(self.channels.get());
337
338 let mut res = ArrayVec::new();
339
340 // SAFETY:
341 //
342 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
343 // and we have constrained `channels` and `frames` above, so this is always
344 // within range.
345 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
346 // * None of these slices overlap, and `self` is borrowed mutably in this method,
347 // so all mutability rules are being upheld.
348 unsafe {
349 for ch_i in 0..channels {
350 res.push_unchecked(core::slice::from_raw_parts_mut(
351 self.buffer.as_mut_ptr().add(ch_i * self.frames),
352 frames,
353 ));
354 }
355 }
356
357 res
358 }
359}
360
361impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> Clone
362 for VarChannelBuffer<T, MAX_CHANNELS>
363{
364 fn clone(&self) -> Self {
365 // Ensure that `reserve_exact` is used when cloning.
366 let mut new_self = Self::new(self.channels, self.frames);
367 new_self.buffer.copy_from_slice(&self.buffer);
368 new_self
369 }
370}
371
372/// A memory-efficient buffer of samples with variable number of instances each with up to
373/// `MAX_CHANNELS` channels. Each channel has a length of `frames`.
374#[derive(Debug)]
375pub struct InstanceBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
376 buffer: Vec<T>,
377 num_instances: usize,
378 channels: NonZeroUsize,
379 frames: usize,
380}
381
382impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> InstanceBuffer<T, MAX_CHANNELS> {
383 pub fn new(num_instances: usize, channels: NonZeroUsize, frames: usize) -> Self {
384 assert!(channels.get() <= MAX_CHANNELS);
385
386 let buffer_len = frames * channels.get() * num_instances;
387
388 let mut buffer = Vec::new();
389 buffer.reserve_exact(buffer_len);
390 buffer.resize(buffer_len, Default::default());
391
392 Self {
393 buffer,
394 num_instances,
395 channels,
396 frames,
397 }
398 }
399
400 pub fn frames(&self) -> usize {
401 self.frames
402 }
403
404 pub fn num_channels(&self) -> NonZeroUsize {
405 self.channels
406 }
407
408 pub fn num_instances(&self) -> usize {
409 self.num_instances
410 }
411
412 pub fn instance(
413 &self,
414 instance_index: usize,
415 channels: usize,
416 frames: usize,
417 ) -> Option<ArrayVec<&[T], MAX_CHANNELS>> {
418 if instance_index >= self.num_instances {
419 return None;
420 }
421
422 let frames = frames.min(self.frames);
423 let channels = channels.min(self.channels.get());
424
425 let start_frame = instance_index * self.frames * self.channels.get();
426
427 let mut res = ArrayVec::new();
428
429 // SAFETY:
430 //
431 // * The constructor has set the size of the buffer to
432 // `self.frames * self.channels * self.num_instances`, and we have constrained
433 // `instance_index`, `channels` and `frames` above, so this is always within range.
434 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
435 unsafe {
436 for ch_i in 0..channels {
437 res.push_unchecked(core::slice::from_raw_parts(
438 self.buffer.as_ptr().add(start_frame + (ch_i * self.frames)),
439 frames,
440 ));
441 }
442 }
443
444 Some(res)
445 }
446
447 pub fn instance_mut(
448 &mut self,
449 instance_index: usize,
450 channels: usize,
451 frames: usize,
452 ) -> Option<ArrayVec<&mut [T], MAX_CHANNELS>> {
453 if instance_index >= self.num_instances {
454 return None;
455 }
456
457 let frames = frames.min(self.frames);
458 let channels = channels.min(self.channels.get());
459
460 let start_frame = instance_index * self.frames * self.channels.get();
461
462 let mut res = ArrayVec::new();
463
464 // SAFETY:
465 //
466 // * The constructor has set the size of the buffer to
467 // `self.frames * self.channels * self.num_instances`, and we have constrained
468 // `instance_index`, `channels` and `frames` above, so this is always within range.
469 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
470 // * None of these slices overlap, and `self` is borrowed mutably in this method,
471 // so all mutability rules are being upheld.
472 unsafe {
473 for ch_i in 0..channels {
474 res.push_unchecked(core::slice::from_raw_parts_mut(
475 self.buffer
476 .as_mut_ptr()
477 .add(start_frame + (ch_i * self.frames)),
478 frames,
479 ));
480 }
481 }
482
483 Some(res)
484 }
485}
486
487impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> Clone
488 for InstanceBuffer<T, MAX_CHANNELS>
489{
490 fn clone(&self) -> Self {
491 // Ensure that `reserve_exact` is used when cloning.
492 let mut new_self = Self::new(self.num_instances, self.channels, self.frames);
493 new_self.buffer.copy_from_slice(&self.buffer);
494 new_self
495 }
496}