Skip to main content

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}