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///
11/// `T` is the backing type of the storage, typically f32.
12///
13/// This is like a [`SequentialBuffer`] but guarantees all `MAX_CHANNELS` are present.
14///
15/// The number of frames and number of channels cannot be changed once constructed.
16#[derive(Debug)]
17pub struct ConstSequentialBuffer<T: Clone + Copy + Default, const CHANNELS: usize> {
18 buffer: Vec<T>,
19 num_frames: usize,
20}
21
22impl<T: Clone + Copy + Default, const CHANNELS: usize> ConstSequentialBuffer<T, CHANNELS> {
23 pub const fn empty() -> Self {
24 assert!(CHANNELS > 0);
25
26 Self {
27 buffer: Vec::new(),
28 num_frames: 0,
29 }
30 }
31
32 pub fn new(frames: usize) -> Self {
33 assert!(CHANNELS > 0);
34
35 let buffer_len = frames * CHANNELS;
36
37 let mut buffer = Vec::new();
38 buffer.reserve_exact(buffer_len);
39 buffer.resize(buffer_len, Default::default());
40
41 Self {
42 buffer,
43 num_frames: frames,
44 }
45 }
46
47 pub fn frames(&self) -> usize {
48 self.num_frames
49 }
50
51 /// Get an immutable reference to the first channel.
52 #[inline]
53 pub fn first(&self) -> &[T] {
54 // SAFETY:
55 //
56 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
57 unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), self.num_frames) }
58 }
59
60 /// Get a mutable reference to the first channel.
61 #[inline]
62 pub fn first_mut(&mut self) -> &mut [T] {
63 // SAFETY:
64 //
65 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
66 // * `self` is borrowed mutably in this method, so all mutability rules are
67 // being upheld.
68 unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), self.num_frames) }
69 }
70
71 /// Get an immutable reference to the first channel with the given number of
72 /// frames.
73 ///
74 /// The length of the returned slice will be either `frames` or the number of
75 /// frames in this buffer, whichever is smaller.
76 #[inline]
77 pub fn first_with_frames(&self, frames: usize) -> &[T] {
78 let frames = frames.min(self.num_frames);
79
80 // SAFETY:
81 //
82 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
83 // and we have constrained `frames` above, so this is always within range.
84 unsafe { core::slice::from_raw_parts(self.buffer.as_ptr(), frames) }
85 }
86
87 /// Get a mutable reference to the first channel with the given number of
88 /// frames.
89 ///
90 /// The length of the returned slice will be either `frames` or the number of
91 /// frames in this buffer, whichever is smaller.
92 #[inline]
93 pub fn first_with_frames_mut(&mut self, frames: usize) -> &mut [T] {
94 let frames = frames.min(self.num_frames);
95
96 // SAFETY:
97 //
98 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
99 // and we have constrained `frames` above, so this is always within range.
100 // * `self` is borrowed mutably in this method, so all mutability rules are
101 // being upheld.
102 unsafe { core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), frames) }
103 }
104
105 /// Get an immutable reference to the first given number of channels in this buffer.
106 ///
107 /// # Panics
108 /// Panics if `NUM_CHANNELS > Self::CHANNELS`
109 pub fn channels<const NUM_CHANNELS: usize>(&self) -> [&[T]; NUM_CHANNELS] {
110 assert!(NUM_CHANNELS <= CHANNELS);
111
112 // SAFETY:
113 //
114 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
115 // and we have constrained NUM_CHANNELS above, so this is always within range.
116 unsafe {
117 core::array::from_fn(|ch_i| {
118 core::slice::from_raw_parts(
119 self.buffer.as_ptr().add(ch_i * self.num_frames),
120 self.num_frames,
121 )
122 })
123 }
124 }
125
126 /// Get a mutable reference to the first given number of channels in this buffer.
127 ///
128 /// # Panics
129 /// Panics if `NUM_CHANNELS > Self::CHANNELS`
130 pub fn channels_mut<const NUM_CHANNELS: usize>(&mut self) -> [&mut [T]; NUM_CHANNELS] {
131 assert!(NUM_CHANNELS <= CHANNELS);
132
133 // SAFETY:
134 //
135 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
136 // and we have constrained NUM_CHANNELS above, so this is always within range.
137 // * None of these slices overlap, and `self` is borrowed mutably in this method,
138 // so all mutability rules are being upheld.
139 unsafe {
140 core::array::from_fn(|ch_i| {
141 core::slice::from_raw_parts_mut(
142 self.buffer.as_mut_ptr().add(ch_i * self.num_frames),
143 self.num_frames,
144 )
145 })
146 }
147 }
148
149 /// Get an immutable reference to the first given number of channels with the
150 /// given number of frames.
151 ///
152 /// The length of the returned slices will be either `frames` or the number of
153 /// frames in this buffer, whichever is smaller.
154 ///
155 /// # Panics
156 /// Panics if `NUM_CHANNELS > Self::CHANNELS`
157 pub fn channels_with_frames<const NUM_CHANNELS: usize>(
158 &self,
159 frames: usize,
160 ) -> [&[T]; NUM_CHANNELS] {
161 assert!(NUM_CHANNELS <= CHANNELS);
162
163 let frames = frames.min(self.num_frames);
164
165 // SAFETY:
166 //
167 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
168 // and we have constrained NUM_CHANNELS and `frames` above, so this is always
169 // within range.
170 unsafe {
171 core::array::from_fn(|ch_i| {
172 core::slice::from_raw_parts(
173 self.buffer.as_ptr().add(ch_i * self.num_frames),
174 frames,
175 )
176 })
177 }
178 }
179
180 /// Get a mutable reference to the first given number of channels with the given
181 /// number of frames.
182 ///
183 /// The length of the returned slices will be either `frames` or the number of
184 /// frames in this buffer, whichever is smaller.
185 ///
186 /// # Panics
187 /// Panics if `NUM_CHANNELS > Self::CHANNELS`
188 pub fn channels_with_frames_mut<const NUM_CHANNELS: usize>(
189 &mut self,
190 frames: usize,
191 ) -> [&mut [T]; NUM_CHANNELS] {
192 assert!(NUM_CHANNELS <= CHANNELS);
193
194 let frames = frames.min(self.num_frames);
195
196 // SAFETY:
197 //
198 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
199 // and we have constrained NUM_CHANNELS and `frames` above, so this is always
200 // within range.
201 // * None of these slices overlap, and `self` is borrowed mutably in this method,
202 // so all mutability rules are being upheld.
203 unsafe {
204 core::array::from_fn(|ch_i| {
205 core::slice::from_raw_parts_mut(
206 self.buffer.as_mut_ptr().add(ch_i * self.num_frames),
207 frames,
208 )
209 })
210 }
211 }
212
213 /// Get an immutable reference to all channels in this buffer.
214 pub fn all(&self) -> [&[T]; CHANNELS] {
215 // SAFETY:
216 //
217 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
218 unsafe {
219 core::array::from_fn(|ch_i| {
220 core::slice::from_raw_parts(
221 self.buffer.as_ptr().add(ch_i * self.num_frames),
222 self.num_frames,
223 )
224 })
225 }
226 }
227
228 /// Get a mutable reference to all channels in this buffer.
229 pub fn all_mut(&mut self) -> [&mut [T]; CHANNELS] {
230 // SAFETY:
231 //
232 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`.
233 // * None of these slices overlap, and `self` is borrowed mutably in this method,
234 // so all mutability rules are being upheld.
235 unsafe {
236 core::array::from_fn(|ch_i| {
237 core::slice::from_raw_parts_mut(
238 self.buffer.as_mut_ptr().add(ch_i * self.num_frames),
239 self.num_frames,
240 )
241 })
242 }
243 }
244
245 /// Get an immutable reference to all channels with the given number of frames.
246 ///
247 /// The length of the returned slices will be either `frames` or the number of
248 /// frames in this buffer, whichever is smaller.
249 pub fn all_with_frames(&self, frames: usize) -> [&[T]; CHANNELS] {
250 let frames = frames.min(self.num_frames);
251
252 // SAFETY:
253 //
254 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
255 // and we have constrained `frames` above, so this is always within range.
256 unsafe {
257 core::array::from_fn(|ch_i| {
258 core::slice::from_raw_parts(
259 self.buffer.as_ptr().add(ch_i * self.num_frames),
260 frames,
261 )
262 })
263 }
264 }
265
266 /// Get a mutable reference to all channels with the given number of frames.
267 ///
268 /// The length of the returned slices will be either `frames` or the number of
269 /// frames in this buffer, whichever is smaller.
270 pub fn all_with_frames_mut(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
271 let frames = frames.min(self.num_frames);
272
273 // SAFETY:
274 //
275 // * The constructor has set the size of the buffer to `self.frames * CHANNELS`,
276 // and we have constrained `frames` above, so this is always within range.
277 // * None of these slices overlap, and `self` is borrowed mutably in this method,
278 // so all mutability rules are being upheld.
279 unsafe {
280 core::array::from_fn(|ch_i| {
281 core::slice::from_raw_parts_mut(
282 self.buffer.as_mut_ptr().add(ch_i * self.num_frames),
283 frames,
284 )
285 })
286 }
287 }
288
289 /// Iterate over all the channels immutably. Each channel slice will have a length
290 /// of `self.frames()`.
291 pub fn iter_channels(&self) -> impl Iterator<Item = &[T]> {
292 self.buffer.chunks_exact(self.num_frames)
293 }
294
295 /// Iterate over all the channels mutably. Each channel slice will have a length
296 /// of `self.frames()`.
297 pub fn iter_channels_mut(&mut self) -> impl Iterator<Item = &mut [T]> {
298 self.buffer.chunks_exact_mut(self.num_frames)
299 }
300}
301
302impl<T: Clone + Copy + Default, const CHANNELS: usize> Clone
303 for ConstSequentialBuffer<T, CHANNELS>
304{
305 fn clone(&self) -> Self {
306 // Ensure that `reserve_exact` is used when cloning.
307 let mut new_self = Self::new(self.num_frames);
308 new_self.buffer.copy_from_slice(&self.buffer);
309 new_self
310 }
311}
312
313/// A buffer of samples where each channel is stored sequentially in memory.
314///
315/// `T` is the backing type of the storage, typically f32.
316///
317/// The number of frames and number of channels cannot be changed once constructed.
318#[derive(Debug)]
319pub struct SequentialBuffer<T: Clone + Copy + Default> {
320 buffer: Vec<T>,
321 num_channels: NonZeroUsize,
322 num_frames: usize,
323}
324
325impl<T: Clone + Copy + Default> SequentialBuffer<T> {
326 pub fn new(channels: NonZeroUsize, frames: usize) -> Self {
327 let buffer_len = frames * channels.get();
328
329 let mut buffer = Vec::new();
330 buffer.reserve_exact(buffer_len);
331 buffer.resize(buffer_len, Default::default());
332
333 Self {
334 buffer,
335 num_channels: channels,
336 num_frames: frames,
337 }
338 }
339
340 pub fn frames(&self) -> usize {
341 self.num_frames
342 }
343
344 pub fn num_channels(&self) -> NonZeroUsize {
345 self.num_channels
346 }
347
348 /// Returns an immutable slice of the given channel. This slice will have a length of
349 /// `self.frames()`.
350 ///
351 /// Returns `None` if `channel >= self.num_channels()`.
352 pub fn channel_slice(&self, channel: usize) -> Option<&[T]> {
353 if channel < self.num_channels.get() {
354 // SAFETY:
355 //
356 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
357 // and we have checked the size of `channels` above, so this is always within range.
358 unsafe {
359 Some(core::slice::from_raw_parts(
360 self.buffer.as_ptr().add(channel * self.num_frames),
361 self.num_frames,
362 ))
363 }
364 } else {
365 None
366 }
367 }
368
369 /// Returns a mutable slice to the given channel. This slice will have a length of
370 /// `self.frames()`.
371 ///
372 /// Returns `None` if `channel >= self.num_channels()`.
373 pub fn channel_slice_mut(&mut self, channel: usize) -> Option<&mut [T]> {
374 if channel < self.num_channels.get() {
375 // SAFETY:
376 //
377 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
378 // and we have checked the size of `channels` above, so this is always within range.
379 // * None of these slices overlap, and `self` is borrowed mutably in this method,
380 // so all mutability rules are being upheld.
381 unsafe {
382 Some(core::slice::from_raw_parts_mut(
383 self.buffer.as_mut_ptr().add(channel * self.num_frames),
384 self.num_frames,
385 ))
386 }
387 } else {
388 None
389 }
390 }
391
392 /// Returns two immutable slices to the first two channels in this buffer with length
393 /// `frames`.
394 ///
395 /// Clamps `frames` to the available data.
396 ///
397 /// If the number of channels in this buffer is less than 2, then this will return
398 /// `None`.
399 pub fn stereo(&self, frames: usize) -> Option<(&[T], &[T])> {
400 if self.num_channels.get() < 2 {
401 return None;
402 }
403
404 let frames = frames.min(self.num_frames);
405
406 // SAFETY:
407 //
408 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
409 // we checked there is at least two channels above, and we have constrained `frames`
410 // above, so this is always within range.
411 unsafe {
412 Some((
413 core::slice::from_raw_parts(self.buffer.as_ptr(), frames),
414 core::slice::from_raw_parts(self.buffer.as_ptr().add(self.num_frames), frames),
415 ))
416 }
417 }
418
419 /// Returns two mutable slices to the first two channels in this buffer with length
420 /// `frames`.
421 ///
422 /// Clamps `frames` to the available data.
423 ///
424 /// If the number of channels in this buffer is less than 2, then this will return
425 /// `None`.
426 pub fn stereo_mut(&mut self, frames: usize) -> Option<(&mut [T], &mut [T])> {
427 if self.num_channels.get() < 2 {
428 return None;
429 }
430
431 let frames = frames.min(self.num_frames);
432
433 // SAFETY:
434 //
435 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
436 // we checked there is at least two channels above, and we have constrained `frames`
437 // above, so this is always within range.
438 // * None of these slices overlap, and `self` is borrowed mutably in this method,
439 // so all mutability rules are being upheld.
440 unsafe {
441 Some((
442 core::slice::from_raw_parts_mut(self.buffer.as_mut_ptr(), frames),
443 core::slice::from_raw_parts_mut(
444 self.buffer.as_mut_ptr().add(self.num_frames),
445 frames,
446 ),
447 ))
448 }
449 }
450
451 /// Returns a vec of slices to the first `frames` frames of the backing buffers
452 /// for the first `num_channels` channels present.
453 ///
454 /// Clamps `num_channels` and `frames` to the available data.
455 pub fn channels<const MAX_CHANNELS: usize>(
456 &self,
457 num_channels: usize,
458 frames: usize,
459 ) -> ArrayVec<&[T], MAX_CHANNELS> {
460 let frames = frames.min(self.num_frames);
461 let channels = num_channels.min(self.num_channels.get()).min(MAX_CHANNELS);
462
463 let mut res = ArrayVec::new();
464
465 // SAFETY:
466 //
467 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
468 // and we have constrained the size of `channels` and `frames` above, so this is always
469 // within range.
470 unsafe {
471 for ch_i in 0..channels {
472 res.push_unchecked(core::slice::from_raw_parts(
473 self.buffer.as_ptr().add(ch_i * self.num_frames),
474 frames,
475 ));
476 }
477 }
478
479 res
480 }
481
482 /// Returns a vec of mutable slices to the first `frames` frames of the backing buffers
483 /// for the first `num_channels` channels present.
484 ///
485 /// Clamps `num_channels` and `frames` to the available data.
486 pub fn channels_mut<const MAX_CHANNELS: usize>(
487 &mut self,
488 num_channels: usize,
489 frames: usize,
490 ) -> ArrayVec<&mut [T], MAX_CHANNELS> {
491 let frames = frames.min(self.num_frames);
492 let channels = num_channels.min(self.num_channels.get()).min(MAX_CHANNELS);
493
494 let mut res = ArrayVec::new();
495
496 // SAFETY:
497 //
498 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
499 // and we have constrained `channels` and `frames` above, so this is always
500 // within range.
501 // * None of these slices overlap, and `self` is borrowed mutably in this method,
502 // so all mutability rules are being upheld.
503 unsafe {
504 for ch_i in 0..channels {
505 res.push_unchecked(core::slice::from_raw_parts_mut(
506 self.buffer.as_mut_ptr().add(ch_i * self.num_frames),
507 frames,
508 ));
509 }
510 }
511
512 res
513 }
514
515 /// Iterate over all the channels immutably. Each channel slice will have a length
516 /// of `self.frames()`.
517 pub fn iter_channels(&self) -> impl Iterator<Item = &[T]> {
518 self.buffer.chunks_exact(self.num_frames)
519 }
520
521 /// Iterate over all the channels mutably. Each channel slice will have a length
522 /// of `self.frames()`.
523 pub fn iter_channels_mut(&mut self) -> impl Iterator<Item = &mut [T]> {
524 self.buffer.chunks_exact_mut(self.num_frames)
525 }
526}
527
528impl<T: Clone + Copy + Default> Clone for SequentialBuffer<T> {
529 fn clone(&self) -> Self {
530 // Ensure that `reserve_exact` is used when cloning.
531 let mut new_self = Self::new(self.num_channels, self.num_frames);
532 new_self.buffer.copy_from_slice(&self.buffer);
533 new_self
534 }
535}
536
537/// A memory-efficient buffer of samples with a given number of instances each with a given
538/// number of channels. Each channel has a length of `frames`.
539///
540/// `T` is the backing type of the storage, typically f32.
541///
542/// This is like a collection of `num_instances` [`SequentialBuffer`]s but contiguous in memory.
543///
544/// The number of instances, channels, and frames cannot be changed once constructed.
545#[derive(Debug)]
546pub struct InstanceBuffer<T: Clone + Copy + Default> {
547 buffer: Vec<T>,
548 num_instances: usize,
549 num_channels: NonZeroUsize,
550 num_frames: usize,
551}
552
553impl<T: Clone + Copy + Default> InstanceBuffer<T> {
554 pub fn new(instances: usize, channels: NonZeroUsize, frames: usize) -> Self {
555 let buffer_len = frames * channels.get() * instances;
556
557 let mut buffer = Vec::new();
558 buffer.reserve_exact(buffer_len);
559 buffer.resize(buffer_len, Default::default());
560
561 Self {
562 buffer,
563 num_instances: instances,
564 num_channels: channels,
565 num_frames: frames,
566 }
567 }
568
569 pub fn frames(&self) -> usize {
570 self.num_frames
571 }
572
573 pub fn num_channels(&self) -> NonZeroUsize {
574 self.num_channels
575 }
576
577 pub fn num_instances(&self) -> usize {
578 self.num_instances
579 }
580
581 /// Returns an array of slices to the first `frames` frames of the backing buffers
582 /// for the first `num_channels` channels present of the instance at `instance_index`.
583 ///
584 /// Clamps `num_channels` and `frames` to the available data.
585 ///
586 /// Returns `None` if there is no instance at `instance_index`.
587 pub fn instance<const MAX_CHANNELS: usize>(
588 &self,
589 instance_index: usize,
590 channels: usize,
591 frames: usize,
592 ) -> Option<ArrayVec<&[T], MAX_CHANNELS>> {
593 if instance_index >= self.num_instances {
594 return None;
595 }
596
597 let frames = frames.min(self.num_frames);
598 let channels = channels.min(self.num_channels.get()).min(MAX_CHANNELS);
599
600 let start_frame = instance_index * self.num_frames * self.num_channels.get();
601
602 let mut res = ArrayVec::new();
603
604 // SAFETY:
605 //
606 // * The constructor has set the size of the buffer to
607 // `self.frames * self.channels * self.num_instances`, and we have constrained
608 // `instance_index`, `channels` and `frames` above, so this is always within range.
609 unsafe {
610 for ch_i in 0..channels {
611 res.push_unchecked(core::slice::from_raw_parts(
612 self.buffer
613 .as_ptr()
614 .add(start_frame + (ch_i * self.num_frames)),
615 frames,
616 ));
617 }
618 }
619
620 Some(res)
621 }
622
623 /// Returns an array of mutable slices to the first `frames` frames of the backing buffers
624 /// for the first `num_channels` channels present of the instance at `instance_index`.
625 ///
626 /// Clamps `num_channels` and `frames` to the available data.
627 ///
628 /// Returns `None` if there is no instance at `instance_index`.
629 pub fn instance_mut<const MAX_CHANNELS: usize>(
630 &mut self,
631 instance_index: usize,
632 channels: usize,
633 frames: usize,
634 ) -> Option<ArrayVec<&mut [T], MAX_CHANNELS>> {
635 if instance_index >= self.num_instances {
636 return None;
637 }
638
639 let frames = frames.min(self.num_frames);
640 let channels = channels.min(self.num_channels.get()).min(MAX_CHANNELS);
641
642 let start_frame = instance_index * self.num_frames * self.num_channels.get();
643
644 let mut res = ArrayVec::new();
645
646 // SAFETY:
647 //
648 // * The constructor has set the size of the buffer to
649 // `self.frames * self.channels * self.num_instances`, and we have constrained
650 // `instance_index`, `channels` and `frames` above, so this is always within range.
651 // * None of these slices overlap, and `self` is borrowed mutably in this method,
652 // so all mutability rules are being upheld.
653 unsafe {
654 for ch_i in 0..channels {
655 res.push_unchecked(core::slice::from_raw_parts_mut(
656 self.buffer
657 .as_mut_ptr()
658 .add(start_frame + (ch_i * self.num_frames)),
659 frames,
660 ));
661 }
662 }
663
664 Some(res)
665 }
666}
667
668impl<T: Clone + Copy + Default> Clone for InstanceBuffer<T> {
669 fn clone(&self) -> Self {
670 // Ensure that `reserve_exact` is used when cloning.
671 let mut new_self = Self::new(self.num_instances, self.num_channels, self.num_frames);
672 new_self.buffer.copy_from_slice(&self.buffer);
673 new_self
674 }
675}