firewheel_core/dsp/
buffer.rs

1use core::num::NonZeroUsize;
2
3use arrayvec::ArrayVec;
4
5/// A memory-efficient buffer of samples with `CHANNELS` channels. Each channel
6/// has a length of `frames`.
7pub struct ChannelBuffer<T: Clone + Copy + Default, const CHANNELS: usize> {
8    buffer: Vec<T>,
9    frames: usize,
10}
11
12impl<T: Clone + Copy + Default, const CHANNELS: usize> ChannelBuffer<T, CHANNELS> {
13    pub const fn empty() -> Self {
14        Self {
15            buffer: Vec::new(),
16            frames: 0,
17        }
18    }
19
20    pub fn new(frames: usize) -> Self {
21        let buffer_len = frames * CHANNELS;
22
23        let mut buffer = Vec::new();
24        buffer.reserve_exact(buffer_len);
25        buffer.resize(buffer_len, Default::default());
26
27        Self { buffer, frames }
28    }
29
30    pub fn frames(&self) -> usize {
31        self.frames
32    }
33
34    pub fn get(&self, frames: usize) -> [&[T]; CHANNELS] {
35        let frames = frames.min(self.frames);
36
37        // SAFETY:
38        //
39        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
40        // and we have constrained `frames` above, so this is always within range.
41        unsafe {
42            core::array::from_fn(|ch_i| {
43                core::slice::from_raw_parts(self.buffer.as_ptr().add(ch_i * self.frames), frames)
44            })
45        }
46    }
47
48    pub fn get_mut(&mut self, frames: usize) -> [&mut [T]; CHANNELS] {
49        let frames = frames.min(self.frames);
50
51        // SAFETY:
52        //
53        // * The constructor has set the size of the buffer to`self.frames * CHANNELS`,
54        // and we have constrained `frames` above, so this is always within range.
55        // * None of these slices overlap, and `self` is borrowed mutably in this method,
56        // so all mutability rules are being upheld.
57        unsafe {
58            core::array::from_fn(|ch_i| {
59                core::slice::from_raw_parts_mut(
60                    self.buffer.as_mut_ptr().add(ch_i * self.frames),
61                    frames,
62                )
63            })
64        }
65    }
66}
67
68/// A memory-efficient buffer of samples with up to `MAX_CHANNELS` channels. Each
69/// channel has a length of `frames`.
70pub struct VarChannelBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
71    buffer: Vec<T>,
72    channels: NonZeroUsize,
73    frames: usize,
74}
75
76impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> VarChannelBuffer<T, MAX_CHANNELS> {
77    pub fn new(channels: NonZeroUsize, frames: usize) -> Self {
78        assert!(channels.get() <= MAX_CHANNELS);
79
80        let buffer_len = frames * channels.get();
81
82        let mut buffer = Vec::new();
83        buffer.reserve_exact(buffer_len);
84        buffer.resize(buffer_len, Default::default());
85
86        Self {
87            buffer,
88            channels,
89            frames,
90        }
91    }
92
93    pub fn frames(&self) -> usize {
94        self.frames
95    }
96
97    pub fn channels(&self) -> NonZeroUsize {
98        self.channels
99    }
100
101    pub fn get(&self, channels: usize, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
102        let frames = frames.min(self.frames);
103        let channels = channels.min(self.channels.get());
104
105        let mut res = ArrayVec::new();
106
107        // SAFETY:
108        //
109        // * The constructor has set the size of the buffer to`self.frames * self.channels`,
110        // and we have constrained `channels` and `frames` above, so this is always
111        // within range.
112        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
113        unsafe {
114            for ch_i in 0..channels {
115                res.push_unchecked(core::slice::from_raw_parts(
116                    self.buffer.as_ptr().add(ch_i * self.frames),
117                    frames,
118                ));
119            }
120        }
121
122        res
123    }
124
125    pub fn get_mut(&mut self, channels: usize, frames: usize) -> ArrayVec<&mut [T], MAX_CHANNELS> {
126        let frames = frames.min(self.frames);
127        let channels = channels.min(self.channels.get());
128
129        let mut res = ArrayVec::new();
130
131        // SAFETY:
132        //
133        // * The constructor has set the size of the buffer to`self.frames * self.channels`,
134        // and we have constrained `channels` and `frames` above, so this is always
135        // within range.
136        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
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            for ch_i in 0..channels {
141                res.push_unchecked(core::slice::from_raw_parts_mut(
142                    self.buffer.as_mut_ptr().add(ch_i * self.frames),
143                    frames,
144                ));
145            }
146        }
147
148        res
149    }
150}
151
152/// A memory-efficient buffer of samples with variable number of instances each with up to
153/// `MAX_CHANNELS` channels. Each channel has a length of `frames`.
154pub struct InstanceBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
155    buffer: Vec<T>,
156    num_instances: usize,
157    channels: NonZeroUsize,
158    frames: usize,
159}
160
161impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> InstanceBuffer<T, MAX_CHANNELS> {
162    pub fn new(num_instances: usize, channels: NonZeroUsize, frames: usize) -> Self {
163        assert!(channels.get() <= MAX_CHANNELS);
164
165        let buffer_len = frames * channels.get() * num_instances;
166
167        let mut buffer = Vec::new();
168        buffer.reserve_exact(buffer_len);
169        buffer.resize(buffer_len, Default::default());
170
171        Self {
172            buffer,
173            num_instances,
174            channels,
175            frames,
176        }
177    }
178
179    pub fn frames(&self) -> usize {
180        self.frames
181    }
182
183    pub fn channels(&self) -> NonZeroUsize {
184        self.channels
185    }
186
187    pub fn num_instances(&self) -> usize {
188        self.num_instances
189    }
190
191    pub fn get(
192        &self,
193        instance_index: usize,
194        channels: usize,
195        frames: usize,
196    ) -> Option<ArrayVec<&[T], MAX_CHANNELS>> {
197        if instance_index >= self.num_instances {
198            return None;
199        }
200
201        let frames = frames.min(self.frames);
202        let channels = channels.min(self.channels.get());
203
204        let start_frame = instance_index * self.frames * 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
211        // `self.frames * self.channels * self.num_instances`, and we have constrained
212        // `instance_index`, `channels` and `frames` above, so this is always 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(start_frame + (ch_i * self.frames)),
218                    frames,
219                ));
220            }
221        }
222
223        Some(res)
224    }
225
226    pub fn get_mut(
227        &mut self,
228        instance_index: usize,
229        channels: usize,
230        frames: usize,
231    ) -> Option<ArrayVec<&mut [T], MAX_CHANNELS>> {
232        if instance_index >= self.num_instances {
233            return None;
234        }
235
236        let frames = frames.min(self.frames);
237        let channels = channels.min(self.channels.get());
238
239        let start_frame = instance_index * self.frames * self.channels.get();
240
241        let mut res = ArrayVec::new();
242
243        // SAFETY:
244        //
245        // * The constructor has set the size of the buffer to
246        // `self.frames * self.channels * self.num_instances`, and we have constrained
247        // `instance_index`, `channels` and `frames` above, so this is always within range.
248        // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
249        // * None of these slices overlap, and `self` is borrowed mutably in this method,
250        // so all mutability rules are being upheld.
251        unsafe {
252            for ch_i in 0..channels {
253                res.push_unchecked(core::slice::from_raw_parts_mut(
254                    self.buffer
255                        .as_mut_ptr()
256                        .add(start_frame + (ch_i * self.frames)),
257                    frames,
258                ));
259            }
260        }
261
262        Some(res)
263    }
264}