fundsp/
buffer.rs

1//! SIMD accelerated audio buffers for block processing.
2
3use super::audionode::*;
4use super::*;
5extern crate alloc;
6use alloc::vec::Vec;
7use numeric_array::ArrayLength;
8
9/// Mutably borrowed audio buffer with an arbitrary number of channels
10/// containing 64 (`MAX_BUFFER_SIZE`) samples per channel. Samples are stored
11/// non-interleaved. Intended as a temporary borrow to feed into
12/// `AudioNode::process` or `AudioUnit::process`.
13pub struct BufferMut<'a>(&'a mut [F32x]);
14
15impl<'a> BufferMut<'a> {
16    /// Create new buffer from a slice. The length of the slice must be divisible by 8.
17    #[inline]
18    pub fn new(buffer: &'a mut [F32x]) -> Self {
19        debug_assert!(buffer.len() & (SIMD_LEN - 1) == 0);
20        Self(buffer)
21    }
22
23    /// Create an empty buffer with 0 channels.
24    #[inline]
25    pub fn empty() -> Self {
26        Self(&mut [])
27    }
28
29    /// Create new buffer that is a subset of this buffer.
30    #[inline]
31    pub fn subset(&mut self, first_channel: usize, channels: usize) -> BufferMut {
32        debug_assert!(first_channel + channels <= self.channels());
33        BufferMut::new(
34            &mut self.0[(first_channel << SIMD_C)..((first_channel + channels) << SIMD_C)],
35        )
36    }
37
38    /// Convert this buffer into an immutable one.
39    #[inline]
40    pub fn buffer_ref(&mut self) -> BufferRef {
41        BufferRef::new(self.0)
42    }
43
44    /// Number of channels in this buffer.
45    #[inline]
46    pub fn channels(&self) -> usize {
47        self.0.len() >> SIMD_C
48    }
49
50    /// Get channel as a slice.
51    #[inline]
52    pub fn channel(&self, channel: usize) -> &[F32x] {
53        debug_assert!(channel < self.channels());
54        &(self.0)[(channel << SIMD_C)..(channel + 1) << SIMD_C]
55    }
56
57    /// Get channel as a mutable slice.
58    #[inline]
59    pub fn channel_mut(&mut self, channel: usize) -> &mut [F32x] {
60        debug_assert!(channel < self.channels());
61        &mut (self.0)[(channel << SIMD_C)..(channel + 1) << SIMD_C]
62    }
63
64    /// Get channel as a scalar slice.
65    #[inline]
66    pub fn channel_f32(&self, channel: usize) -> &'a [f32] {
67        debug_assert!(channel < self.channels());
68        let data = self.channel(channel).as_ptr() as *const f32;
69        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
70        unsafe { core::slice::from_raw_parts(data, MAX_BUFFER_SIZE) }
71    }
72
73    /// Get channel as a mutable scalar slice.
74    #[inline]
75    pub fn channel_f32_mut(&mut self, channel: usize) -> &'a mut [f32] {
76        debug_assert!(channel < self.channels());
77        let data = self.channel_mut(channel).as_mut_ptr() as *mut f32;
78        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
79        unsafe { core::slice::from_raw_parts_mut(data, MAX_BUFFER_SIZE) }
80    }
81
82    /// Set value at index `i` (0 <= `i` <= 7).
83    #[inline]
84    pub fn set(&mut self, channel: usize, i: usize, value: F32x) {
85        debug_assert!(channel < self.channels());
86        (self.0)[(channel << SIMD_C) + i] = value;
87    }
88
89    /// Set `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
90    #[inline]
91    pub fn set_f32(&mut self, channel: usize, i: usize, value: f32) {
92        debug_assert!(channel < self.channels());
93        (self.0)[(channel << SIMD_C) + (i >> SIMD_S)].as_array_mut()[i & SIMD_M] = value;
94        // Note. There is no difference in speed between the versions above and below.
95        //self.channel_f32_mut(channel)[i] = value;
96    }
97
98    /// Get value at index `i` (0 <= `i` <= 7) of `channel`.
99    #[inline]
100    pub fn at(&self, channel: usize, i: usize) -> F32x {
101        debug_assert!(channel < self.channels());
102        (self.0)[(channel << SIMD_C) + i]
103    }
104
105    /// Get value at index `i` (0 <= `i` <= 7) of `channel`.
106    #[inline]
107    pub fn at_mut(&mut self, channel: usize, i: usize) -> &mut F32x {
108        debug_assert!(channel < self.channels());
109        &mut (self.0)[(channel << SIMD_C) + i]
110    }
111
112    /// Get `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
113    #[inline]
114    pub fn at_f32(&self, channel: usize, i: usize) -> f32 {
115        debug_assert!(channel < self.channels());
116        (self.0)[(channel << SIMD_C) + (i >> SIMD_S)].as_array_ref()[i & SIMD_M]
117    }
118
119    /// Add to value at index `i` (0 <= `i` <= 7) of `channel`.
120    pub fn add(&mut self, channel: usize, i: usize, value: F32x) {
121        debug_assert!(channel < self.channels());
122        (self.0)[(channel << SIMD_C) + i] += value;
123    }
124}
125
126/// Immutably borrowed audio buffer with an arbitrary number of channels
127/// containing 64 (`MAX_BUFFER_SIZE`) samples per channel. Samples are stored non-interleaved.
128/// Intended as a temporary borrow to feed into `AudioNode::process` or `AudioUnit::process`.
129pub struct BufferRef<'a>(&'a [F32x]);
130
131impl<'a> BufferRef<'a> {
132    /// Create new buffer from a slice. The length of the slice must be divisible by 8.
133    #[inline]
134    pub fn new(buffer: &'a [F32x]) -> Self {
135        debug_assert!(buffer.len() & (SIMD_LEN - 1) == 0);
136        Self(buffer)
137    }
138
139    /// Create an empty buffer with 0 channels.
140    #[inline]
141    pub fn empty() -> Self {
142        Self(&[])
143    }
144
145    /// Create new buffer that is a subset of this buffer.
146    #[inline]
147    pub fn subset(&self, first_channel: usize, channels: usize) -> BufferRef {
148        debug_assert!(first_channel + channels <= self.channels());
149        BufferRef::new(&self.0[(first_channel << SIMD_C)..((first_channel + channels) << SIMD_C)])
150    }
151
152    /// Number of channels in this buffer.
153    #[inline]
154    pub fn channels(&self) -> usize {
155        self.0.len() >> SIMD_C
156    }
157
158    /// Get channel slice.
159    #[inline]
160    pub fn channel(&self, channel: usize) -> &[F32x] {
161        debug_assert!(channel < self.channels());
162        &(self.0)[(channel << SIMD_C)..(channel + 1) << SIMD_C]
163    }
164
165    /// Get channel as a scalar slice.
166    #[inline]
167    pub fn channel_f32(&self, channel: usize) -> &'a [f32] {
168        debug_assert!(channel < self.channels());
169        let data = self.channel(channel).as_ptr() as *const f32;
170        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
171        unsafe { core::slice::from_raw_parts(data, MAX_BUFFER_SIZE) }
172    }
173
174    /// Access value at index `i` (0 <= `i` <= 7).
175    #[inline]
176    pub fn at(&self, channel: usize, i: usize) -> F32x {
177        debug_assert!(channel < self.channels());
178        (self.0)[(channel << SIMD_C) + i]
179    }
180
181    /// Access `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
182    #[inline]
183    pub fn at_f32(&self, channel: usize, i: usize) -> f32 {
184        debug_assert!(channel < self.channels());
185        (self.0)[(channel << SIMD_C) + (i >> SIMD_S)].as_array_ref()[i & SIMD_M]
186    }
187}
188
189/// An owned buffer on the heap with an arbitrary number of channels
190/// containing 64 (`MAX_BUFFER_SIZE`) samples per channel. Samples are stored non-interleaved.
191#[derive(Clone, Default)]
192pub struct BufferVec {
193    buffer: Vec<F32x>,
194}
195
196impl BufferVec {
197    /// Create new owned buffer with the given number of `channels`.
198    pub fn new(channels: usize) -> Self {
199        let mut buffer = Vec::with_capacity(channels << SIMD_C);
200        buffer.resize(channels << SIMD_C, F32x::ZERO);
201        Self { buffer }
202    }
203
204    /// Number of channels in this buffer.
205    #[inline]
206    pub fn channels(&self) -> usize {
207        self.buffer.len() >> SIMD_C
208    }
209
210    /// Length of the buffer is 8 SIMD samples.
211    #[inline]
212    pub fn length(&self) -> usize {
213        SIMD_LEN
214    }
215
216    /// Length of the buffer is 8 SIMD samples.
217    #[inline]
218    #[allow(clippy::len_without_is_empty)]
219    pub fn len(&self) -> usize {
220        SIMD_LEN
221    }
222
223    /// Access value at index `i` (0 <= `i` <= 7) of `channel`.
224    #[inline]
225    pub fn at(&self, channel: usize, i: usize) -> F32x {
226        debug_assert!(channel < self.channels());
227        self.buffer[(channel << SIMD_C) + i]
228    }
229
230    /// Set `value` at index `i` (0 <= `i` <= 7) of `channel`.
231    #[inline]
232    pub fn set(&mut self, channel: usize, i: usize, value: F32x) {
233        debug_assert!(channel < self.channels());
234        self.buffer[(channel << SIMD_C) + i] = value;
235    }
236
237    /// Access `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
238    #[inline]
239    pub fn at_f32(&self, channel: usize, i: usize) -> f32 {
240        debug_assert!(channel < self.channels());
241        self.buffer[(channel << SIMD_C) + (i >> SIMD_S)].as_array_ref()[i & SIMD_M]
242    }
243
244    /// Set `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
245    #[inline]
246    pub fn set_f32(&mut self, channel: usize, i: usize, value: f32) {
247        debug_assert!(channel < self.channels());
248        self.buffer[(channel << SIMD_C) + (i >> SIMD_S)].as_array_mut()[i & SIMD_M] = value;
249    }
250
251    /// Get channel slice.
252    #[inline]
253    pub fn channel(&self, channel: usize) -> &[F32x] {
254        debug_assert!(channel < self.channels());
255        &self.buffer[(channel << SIMD_C)..(channel + 1) << SIMD_C]
256    }
257
258    /// Get mutable channel slice.
259    #[inline]
260    pub fn channel_mut(&mut self, channel: usize) -> &mut [F32x] {
261        debug_assert!(channel < self.channels());
262        &mut self.buffer[(channel << SIMD_C)..(channel + 1) << SIMD_C]
263    }
264
265    /// Get channel as a scalar slice.
266    #[inline]
267    pub fn channel_f32(&mut self, channel: usize) -> &[f32] {
268        debug_assert!(channel < self.channels());
269        let data = self.channel(channel).as_ptr() as *const f32;
270        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
271        unsafe { core::slice::from_raw_parts(data, MAX_BUFFER_SIZE) }
272    }
273
274    /// Get channel as a mutable scalar slice.
275    #[inline]
276    pub fn channel_f32_mut(&mut self, channel: usize) -> &mut [f32] {
277        debug_assert!(channel < self.channels());
278        let data = self.channel_mut(channel).as_mut_ptr() as *mut f32;
279        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
280        unsafe { core::slice::from_raw_parts_mut(data, MAX_BUFFER_SIZE) }
281    }
282
283    /// Fill all channels of buffer with zeros.
284    #[inline]
285    pub fn clear(&mut self) {
286        self.buffer.fill(F32x::ZERO);
287    }
288
289    /// Resize the buffer.
290    pub fn resize(&mut self, channels: usize) {
291        self.buffer.resize(channels << SIMD_C, F32x::ZERO);
292    }
293
294    /// Get an immutably borrowed buffer.
295    #[inline]
296    pub fn buffer_ref(&self) -> BufferRef {
297        BufferRef::new(&self.buffer)
298    }
299
300    /// Get a mutably borrowed buffer.
301    #[inline]
302    pub fn buffer_mut(&mut self) -> BufferMut {
303        BufferMut::new(&mut self.buffer)
304    }
305}
306
307/// An owned audio buffer stored inline as an array with an arbitrary number of channels
308/// containing 64 (`MAX_BUFFER_SIZE`) samples per channel.
309/// Samples are stored non-interleaved.
310/// The number of channels must be known at compile time:
311/// the size `N` is given as a type-level integer (`U0`, `U1`, ...).
312#[repr(C)]
313#[derive(Clone, Default)]
314pub struct BufferArray<N: ArrayLength> {
315    array: Frame<[F32x; SIMD_LEN], N>,
316}
317
318impl<N: ArrayLength> BufferArray<N> {
319    /// Create new buffer and initialize it with zeros.
320    #[inline]
321    pub fn new() -> Self {
322        Self::default()
323    }
324
325    /// Create new buffer.
326    #[inline]
327    pub(crate) fn uninitialized() -> Self {
328        // Safety: This is undefined behavior but it seems to work fine. Zero initialization is safe but slower in benchmarks.
329        #[allow(clippy::uninit_assumed_init)]
330        unsafe {
331            core::mem::MaybeUninit::uninit().assume_init()
332        }
333    }
334
335    /// Access value at index `i` (0 <= `i` <= 7) of `channel`.
336    #[inline]
337    pub fn at(&self, channel: usize, i: usize) -> F32x {
338        self.array[channel][i]
339    }
340
341    /// Get `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
342    #[inline]
343    pub fn at_f32(&self, channel: usize, i: usize) -> f32 {
344        debug_assert!(channel < self.channels());
345        self.array[channel][i >> SIMD_S].as_array_ref()[i & SIMD_M]
346    }
347
348    /// Set value at index `i` (0 <= `i` <= 7) of `channel`.
349    #[inline]
350    pub fn set(&mut self, channel: usize, i: usize, value: F32x) {
351        debug_assert!(channel < self.channels());
352        self.array[channel][i] = value;
353    }
354
355    /// Get `f32` value at index `i` (0 <= `i` <= 63) of `channel`.
356    #[inline]
357    pub fn set_f32(&mut self, channel: usize, i: usize, value: f32) {
358        debug_assert!(channel < self.channels());
359        self.array[channel][i >> SIMD_S].as_array_mut()[i & SIMD_M] = value;
360    }
361
362    /// Number of channels in this buffer.
363    #[inline]
364    pub fn channels(&self) -> usize {
365        N::USIZE
366    }
367
368    /// Length of the buffer is 8 SIMD samples.
369    #[inline]
370    pub fn length(&self) -> usize {
371        SIMD_LEN
372    }
373
374    /// Length of the buffer is 8 SIMD samples.
375    #[inline]
376    #[allow(clippy::len_without_is_empty)]
377    pub fn len(&self) -> usize {
378        SIMD_LEN
379    }
380
381    /// Fill all channels of buffer with zeros.
382    #[inline]
383    pub fn clear(&mut self) {
384        self.array.fill([F32x::ZERO; SIMD_LEN]);
385    }
386
387    /// Get channel slice.
388    #[inline]
389    pub fn channel(&self, channel: usize) -> &[F32x] {
390        // Safety: we know Frames are contiguous and we know the length statically.
391        unsafe {
392            &core::slice::from_raw_parts(self.array.as_ptr() as *const F32x, N::USIZE << SIMD_C)
393                [(channel << SIMD_C)..(channel + 1) << SIMD_C]
394        }
395    }
396
397    /// Get mutable channel slice.
398    #[inline]
399    pub fn channel_mut(&mut self, channel: usize) -> &mut [F32x] {
400        // Safety: we know Frames are contiguous and we know the length statically.
401        unsafe {
402            &mut core::slice::from_raw_parts_mut(
403                self.array.as_mut_ptr() as *mut F32x,
404                N::USIZE << SIMD_C,
405            )[(channel << SIMD_C)..(channel + 1) << SIMD_C]
406        }
407    }
408
409    /// Get channel as a scalar slice.
410    #[inline]
411    pub fn channel_f32(&mut self, channel: usize) -> &[f32] {
412        let data = self.channel(channel).as_ptr() as *const f32;
413        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
414        unsafe { core::slice::from_raw_parts(data, MAX_BUFFER_SIZE) }
415    }
416
417    /// Get channel as a mutable scalar slice.
418    #[inline]
419    pub fn channel_f32_mut(&mut self, channel: usize) -> &mut [f32] {
420        let data = self.channel_mut(channel).as_mut_ptr() as *mut f32;
421        // Safety: we know each channel contains exactly `MAX_BUFFER_SIZE` samples.
422        unsafe { core::slice::from_raw_parts_mut(data, MAX_BUFFER_SIZE) }
423    }
424
425    /// Get immutably borrowed buffer.
426    #[inline]
427    pub fn buffer_ref(&self) -> BufferRef {
428        // Safety: we know Frames are contiguous and we know the length statically.
429        let slice = unsafe {
430            core::slice::from_raw_parts(self.array.as_ptr() as *const F32x, N::USIZE << SIMD_C)
431        };
432        BufferRef::new(slice)
433    }
434
435    /// Get mutably borrowed buffer.
436    #[inline]
437    pub fn buffer_mut(&mut self) -> BufferMut {
438        // Safety: we know Frames are contiguous and we know the length statically.
439        let data = self.array.as_mut_ptr() as *mut F32x;
440        let slice = unsafe { core::slice::from_raw_parts_mut(data, N::USIZE << SIMD_C) };
441        BufferMut::new(slice)
442    }
443}