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}