audio_channel_buffer/
instance_buffer.rs

1use core::pin::Pin;
2
3use crate::{ChannelBufferRef, ChannelBufferRefMut};
4
5/// A memory-efficient buffer of samples with a fixed compile-time number of instances each with a
6/// fixed compile-time number of `CHANNELS`. Each channel has a fixed runtime number of `frames`
7/// (samples in a single channel of audio).
8#[derive(Debug)]
9pub struct InstanceChannelBuffer<
10    T: Clone + Copy + Default + Sized + Unpin,
11    const INSTANCES: usize,
12    const CHANNELS: usize,
13> {
14    data: Pin<Vec<T>>,
15    offsets: [[*mut T; CHANNELS]; INSTANCES],
16    frames: usize,
17    instance_length: usize,
18}
19
20impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize>
21    InstanceChannelBuffer<T, INSTANCES, CHANNELS>
22{
23    const _COMPILE_TIME_ASSERTS: () = {
24        assert!(INSTANCES > 0);
25        assert!(CHANNELS > 0);
26    };
27
28    /// Create an empty [`InstanceBuffer`] with no allocated capacity.
29    pub fn empty() -> Self {
30        let _ = Self::_COMPILE_TIME_ASSERTS;
31
32        let mut data = Pin::new(Vec::<T>::new());
33
34        let offsets = core::array::from_fn(|_| core::array::from_fn(|_| data.as_mut_ptr()));
35
36        Self {
37            data,
38            offsets,
39            frames: 0,
40            instance_length: 0,
41        }
42    }
43
44    /// Create a new [`InstanceChannelBuffer`] allocated with the given number of
45    /// `instances`, each with the given number of `frames` (samples in a single channel
46    /// of audio).
47    ///
48    /// All data will be initialized with the default value.
49    pub fn new(num_instances: usize, frames: usize) -> Self {
50        let _ = Self::_COMPILE_TIME_ASSERTS;
51
52        let instance_length = frames * CHANNELS;
53        let buffer_len = instance_length * num_instances;
54
55        let mut data = Vec::<T>::new();
56        data.reserve_exact(buffer_len);
57        data.resize(buffer_len, Default::default());
58
59        let mut data = Pin::new(data);
60
61        // SAFETY: All of these pointers point to valid memory in the vec.
62        let offsets = unsafe {
63            core::array::from_fn(|inst_i| {
64                core::array::from_fn(|ch_i| {
65                    data.as_mut_ptr()
66                        .add((instance_length * inst_i) + (frames * ch_i))
67                })
68            })
69        };
70
71        Self {
72            data,
73            offsets,
74            frames,
75            instance_length,
76        }
77    }
78
79    /// Create a new [`InstanceChannelBuffer`] allocated with the given number of
80    /// `instances`, each with the given number of `frames` (samples in a single channel
81    /// of audio).
82    ///
83    /// No data will be initialized.
84    ///
85    /// # Safety
86    /// Any data must be initialized before reading.
87    pub unsafe fn new_uninit(num_instances: usize, frames: usize) -> Self {
88        let _ = Self::_COMPILE_TIME_ASSERTS;
89
90        let instance_length = frames * CHANNELS;
91        let buffer_len = instance_length * num_instances;
92
93        let mut data = Vec::<T>::new();
94        data.reserve_exact(buffer_len);
95        data.set_len(buffer_len);
96
97        let mut data = Pin::new(data);
98
99        // SAFETY: All of these pointers point to valid memory in the vec.
100        let offsets = unsafe {
101            core::array::from_fn(|inst_i| {
102                core::array::from_fn(|ch_i| {
103                    data.as_mut_ptr()
104                        .add((instance_length * inst_i) + (frames * ch_i))
105                })
106            })
107        };
108
109        Self {
110            data,
111            offsets,
112            frames,
113            instance_length,
114        }
115    }
116
117    /// The number of instances in this buffer.
118    pub fn num_instances(&self) -> usize {
119        self.offsets.len()
120    }
121
122    /// The number of channels in this buffer.
123    pub fn channels(&self) -> usize {
124        CHANNELS
125    }
126
127    /// The number of frames (samples in a single channel of audio) that are allocated
128    /// in this buffer.
129    pub fn frames(&self) -> usize {
130        self.frames
131    }
132
133    /// Get an immutable reference to the instance at the given index.
134    ///
135    /// Returns `None` if `index` is out of bounds.
136    #[inline(always)]
137    pub fn instance<'a>(&'a self, index: usize) -> Option<ChannelBufferRef<'a, T, CHANNELS>> {
138        if index < self.num_instances() {
139            // # SAFETY:
140            // We have checked that `index` is within bounds.
141            unsafe { Some(self.instance_unchecked(index)) }
142        } else {
143            None
144        }
145    }
146
147    /// Get an immutable reference to the instance at the given index.
148    ///
149    /// # Safety
150    /// `index` must be less than `self.num_instances()`.
151    #[inline(always)]
152    pub unsafe fn instance_unchecked<'a>(
153        &'a self,
154        index: usize,
155    ) -> ChannelBufferRef<'a, T, CHANNELS> {
156        // SAFETY:
157        //
158        // * The constructors ensure that the pointed-to data vec has a length of at
159        // least `num_instances * frames * CHANNELS`.
160        // * The caller upholds that `index` is within bounds.
161        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
162        // of the struct.
163        // * `[*const T; CHANNELS]` and `[*mut T; CHANNELS]` are interchangeable bit-for-bit.
164        // * We have asserted at compile-time that both `INSTANCES` and `CHANNELS` are non-zero.
165        ChannelBufferRef::from_raw(
166            core::slice::from_raw_parts(
167                *self.offsets.get_unchecked(index).get_unchecked(0),
168                self.instance_length,
169            ),
170            core::mem::transmute_copy(self.offsets.get_unchecked(index)),
171            self.frames,
172        )
173    }
174
175    /// Get a mutable reference to the instance at the given index.
176    ///
177    /// Returns `None` if `index` is out of bounds.
178    #[inline(always)]
179    pub fn instance_mut<'a>(
180        &'a mut self,
181        index: usize,
182    ) -> Option<ChannelBufferRefMut<'a, T, CHANNELS>> {
183        if index < self.num_instances() {
184            // # SAFETY:
185            // We have checked that `index` is within bounds.
186            unsafe { Some(self.instance_unchecked_mut(index)) }
187        } else {
188            None
189        }
190    }
191
192    /// Get a mutable reference to the instance at the given index.
193    ///
194    /// # Safety
195    /// `index` must be less than `self.num_instances()`.
196    #[inline(always)]
197    pub unsafe fn instance_unchecked_mut<'a>(
198        &'a mut self,
199        index: usize,
200    ) -> ChannelBufferRefMut<'a, T, CHANNELS> {
201        // SAFETY:
202        //
203        // * The constructors ensure that the pointed-to data vec has a length of at
204        // least `num_instances * frames * CHANNELS`.
205        // * The caller upholds that `index` is within bounds.
206        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
207        // of the struct.
208        // * `self` is borrowed as mutable, ensuring that no other references to the
209        // data Vec can exist.
210        // * We have asserted at compile-time that both `INSTANCES` and `CHANNELS` are non-zero.
211        ChannelBufferRefMut::from_raw(
212            core::slice::from_raw_parts_mut(
213                *self.offsets.get_unchecked(index).get_unchecked(0),
214                self.instance_length,
215            ),
216            self.offsets.get_unchecked(index).clone(),
217            self.frames,
218        )
219    }
220
221    /// Get an immutable reference to all instances.
222    pub fn all_instances<'a>(&'a self) -> [ChannelBufferRef<'a, T, CHANNELS>; INSTANCES] {
223        // SAFETY: `inst_i` is always within bounds.
224        unsafe { std::array::from_fn(|inst_i| self.instance_unchecked(inst_i)) }
225    }
226
227    /// Get a mutable reference to all instances.
228    pub fn all_instances_mut<'a>(
229        &'a mut self,
230    ) -> [ChannelBufferRefMut<'a, T, CHANNELS>; INSTANCES] {
231        // SAFETY:
232        // * The constructors ensure that the pointed-to data vec has a length of at
233        // least `num_instances * frames * CHANNELS`.
234        // * `inst_i` is always within bounds.
235        // * The Vec is pinned and cannot be moved, so the pointers are valid for the lifetime
236        // of the struct.
237        // * `self` is borrowed as mutable, and none of these slices overlap, so all
238        // mutability rules are being upheld.
239        // * We have asserted at compile-time that both `INSTANCES` and `CHANNELS` are non-zero.
240        unsafe {
241            std::array::from_fn(|inst_i| {
242                ChannelBufferRefMut::from_raw(
243                    core::slice::from_raw_parts_mut(
244                        *self.offsets.get_unchecked(inst_i).get_unchecked(0),
245                        self.instance_length,
246                    ),
247                    self.offsets.get_unchecked(inst_i).clone(),
248                    self.frames,
249                )
250            })
251        }
252    }
253
254    /// Get the entire contents of the buffer as a single immutable slice.
255    pub fn raw(&self) -> &[T] {
256        &self.data
257    }
258
259    /// Get the entire contents of the buffer as a single mutable slice.
260    pub fn raw_mut(&mut self) -> &mut [T] {
261        &mut self.data
262    }
263
264    /// Clear all data with the default value.
265    pub fn clear(&mut self) {
266        self.raw_mut().fill(T::default());
267    }
268}
269
270impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize>
271    Default for InstanceChannelBuffer<T, INSTANCES, CHANNELS>
272{
273    fn default() -> Self {
274        Self::empty()
275    }
276}
277
278impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize>
279    Into<Vec<T>> for InstanceChannelBuffer<T, INSTANCES, CHANNELS>
280{
281    fn into(self) -> Vec<T> {
282        Pin::<Vec<T>>::into_inner(self.data)
283    }
284}
285
286impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize> Clone
287    for InstanceChannelBuffer<T, INSTANCES, CHANNELS>
288{
289    fn clone(&self) -> Self {
290        // SAFETY: We initialize all the data below.
291        let mut new_self = unsafe { Self::new_uninit(self.num_instances(), self.frames) };
292
293        new_self.raw_mut().copy_from_slice(self.raw());
294
295        new_self
296    }
297}
298
299// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
300// the public API prevents misuse of the pointers.
301unsafe impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize>
302    Send for InstanceChannelBuffer<T, INSTANCES, CHANNELS>
303{
304}
305// # SAFETY: All the stored pointers are valid for the lifetime of the struct, and
306// the public API prevents misuse of the pointers.
307unsafe impl<T: Clone + Copy + Default + Sized + Unpin, const INSTANCES: usize, const CHANNELS: usize>
308    Sync for InstanceChannelBuffer<T, INSTANCES, CHANNELS>
309{
310}