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, Clone)]
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
263/// A memory-efficient buffer of samples with up to `MAX_CHANNELS` channels. Each
264/// channel has a length of `frames`.
265#[derive(Debug, Clone)]
266pub struct VarChannelBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
267 buffer: Vec<T>,
268 channels: NonZeroUsize,
269 frames: usize,
270}
271
272impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> VarChannelBuffer<T, MAX_CHANNELS> {
273 pub fn new(channels: NonZeroUsize, frames: usize) -> Self {
274 assert!(channels.get() <= MAX_CHANNELS);
275
276 let buffer_len = frames * channels.get();
277
278 let mut buffer = Vec::new();
279 buffer.reserve_exact(buffer_len);
280 buffer.resize(buffer_len, Default::default());
281
282 Self {
283 buffer,
284 channels,
285 frames,
286 }
287 }
288
289 pub fn frames(&self) -> usize {
290 self.frames
291 }
292
293 pub fn num_channels(&self) -> NonZeroUsize {
294 self.channels
295 }
296
297 pub fn channels(&self, num_channels: usize, frames: usize) -> ArrayVec<&[T], MAX_CHANNELS> {
298 let frames = frames.min(self.frames);
299 let channels = num_channels.min(self.channels.get());
300
301 let mut res = ArrayVec::new();
302
303 // SAFETY:
304 //
305 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
306 // and we have constrained `channels` and `frames` above, so this is always
307 // within range.
308 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
309 unsafe {
310 for ch_i in 0..channels {
311 res.push_unchecked(core::slice::from_raw_parts(
312 self.buffer.as_ptr().add(ch_i * self.frames),
313 frames,
314 ));
315 }
316 }
317
318 res
319 }
320
321 pub fn channels_mut(
322 &mut self,
323 num_channels: usize,
324 frames: usize,
325 ) -> ArrayVec<&mut [T], MAX_CHANNELS> {
326 let frames = frames.min(self.frames);
327 let channels = num_channels.min(self.channels.get());
328
329 let mut res = ArrayVec::new();
330
331 // SAFETY:
332 //
333 // * The constructor has set the size of the buffer to `self.frames * self.channels`,
334 // and we have constrained `channels` and `frames` above, so this is always
335 // within range.
336 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
337 // * None of these slices overlap, and `self` is borrowed mutably in this method,
338 // so all mutability rules are being upheld.
339 unsafe {
340 for ch_i in 0..channels {
341 res.push_unchecked(core::slice::from_raw_parts_mut(
342 self.buffer.as_mut_ptr().add(ch_i * self.frames),
343 frames,
344 ));
345 }
346 }
347
348 res
349 }
350}
351
352/// A memory-efficient buffer of samples with variable number of instances each with up to
353/// `MAX_CHANNELS` channels. Each channel has a length of `frames`.
354#[derive(Debug, Clone)]
355pub struct InstanceBuffer<T: Clone + Copy + Default, const MAX_CHANNELS: usize> {
356 buffer: Vec<T>,
357 num_instances: usize,
358 channels: NonZeroUsize,
359 frames: usize,
360}
361
362impl<T: Clone + Copy + Default, const MAX_CHANNELS: usize> InstanceBuffer<T, MAX_CHANNELS> {
363 pub fn new(num_instances: usize, channels: NonZeroUsize, frames: usize) -> Self {
364 assert!(channels.get() <= MAX_CHANNELS);
365
366 let buffer_len = frames * channels.get() * num_instances;
367
368 let mut buffer = Vec::new();
369 buffer.reserve_exact(buffer_len);
370 buffer.resize(buffer_len, Default::default());
371
372 Self {
373 buffer,
374 num_instances,
375 channels,
376 frames,
377 }
378 }
379
380 pub fn frames(&self) -> usize {
381 self.frames
382 }
383
384 pub fn num_channels(&self) -> NonZeroUsize {
385 self.channels
386 }
387
388 pub fn num_instances(&self) -> usize {
389 self.num_instances
390 }
391
392 pub fn instance(
393 &self,
394 instance_index: usize,
395 channels: usize,
396 frames: usize,
397 ) -> Option<ArrayVec<&[T], MAX_CHANNELS>> {
398 if instance_index >= self.num_instances {
399 return None;
400 }
401
402 let frames = frames.min(self.frames);
403 let channels = channels.min(self.channels.get());
404
405 let start_frame = instance_index * self.frames * self.channels.get();
406
407 let mut res = ArrayVec::new();
408
409 // SAFETY:
410 //
411 // * The constructor has set the size of the buffer to
412 // `self.frames * self.channels * self.num_instances`, and we have constrained
413 // `instance_index`, `channels` and `frames` above, so this is always within range.
414 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
415 unsafe {
416 for ch_i in 0..channels {
417 res.push_unchecked(core::slice::from_raw_parts(
418 self.buffer.as_ptr().add(start_frame + (ch_i * self.frames)),
419 frames,
420 ));
421 }
422 }
423
424 Some(res)
425 }
426
427 pub fn instance_mut(
428 &mut self,
429 instance_index: usize,
430 channels: usize,
431 frames: usize,
432 ) -> Option<ArrayVec<&mut [T], MAX_CHANNELS>> {
433 if instance_index >= self.num_instances {
434 return None;
435 }
436
437 let frames = frames.min(self.frames);
438 let channels = channels.min(self.channels.get());
439
440 let start_frame = instance_index * self.frames * self.channels.get();
441
442 let mut res = ArrayVec::new();
443
444 // SAFETY:
445 //
446 // * The constructor has set the size of the buffer to
447 // `self.frames * self.channels * self.num_instances`, and we have constrained
448 // `instance_index`, `channels` and `frames` above, so this is always within range.
449 // * The constructor has ensured that `self.channels <= MAX_CHANNELS`.
450 // * None of these slices overlap, and `self` is borrowed mutably in this method,
451 // so all mutability rules are being upheld.
452 unsafe {
453 for ch_i in 0..channels {
454 res.push_unchecked(core::slice::from_raw_parts_mut(
455 self.buffer
456 .as_mut_ptr()
457 .add(start_frame + (ch_i * self.frames)),
458 frames,
459 ));
460 }
461 }
462
463 Some(res)
464 }
465}