xref: /webrtc/media/src/audio/buffer.rs (revision ffe74184)
1 pub mod info;
2 pub mod layout;
3 
4 use std::{
5     mem::{ManuallyDrop, MaybeUninit},
6     ops::Range,
7 };
8 
9 use byteorder::ByteOrder;
10 use thiserror::Error;
11 
12 pub use info::BufferInfo;
13 pub use layout::BufferLayout;
14 
15 use layout::{Deinterleaved, Interleaved};
16 
17 pub trait FromBytes<L>: Sized {
18     type Error;
19 
from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>20     fn from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>;
21 }
22 
23 pub trait ToByteBufferRef<L>: Sized {
24     type Error;
25 
bytes_len(&self)26     fn bytes_len(&self);
to_bytes<B: ByteOrder>( &self, bytes: &mut [u8], channels: usize, ) -> Result<usize, Self::Error>27     fn to_bytes<B: ByteOrder>(
28         &self,
29         bytes: &mut [u8],
30         channels: usize,
31     ) -> Result<usize, Self::Error>;
32 }
33 
34 #[derive(Debug, Error, PartialEq, Eq)]
35 pub enum Error {
36     #[error("Unexpected end of buffer: (expected: {expected}, actual: {actual})")]
37     UnexpectedEndOfBuffer { expected: usize, actual: usize },
38 }
39 
40 #[derive(Eq, PartialEq, Clone, Debug)]
41 pub struct BufferRef<'a, T, L> {
42     samples: &'a [T],
43     info: BufferInfo<L>,
44 }
45 
46 impl<'a, T, L> BufferRef<'a, T, L> {
new(samples: &'a [T], channels: usize) -> Self47     pub fn new(samples: &'a [T], channels: usize) -> Self {
48         debug_assert_eq!(samples.len() % channels, 0);
49         let info = {
50             let frames = samples.len() / channels;
51             BufferInfo::new(channels, frames)
52         };
53         Self { samples, info }
54     }
55 }
56 
57 /// Buffer multi-channel interlaced Audio.
58 #[derive(Eq, PartialEq, Clone, Debug)]
59 pub struct Buffer<T, L> {
60     samples: Vec<T>,
61     info: BufferInfo<L>,
62 }
63 
64 impl<T, L> Buffer<T, L> {
new(samples: Vec<T>, channels: usize) -> Self65     pub fn new(samples: Vec<T>, channels: usize) -> Self {
66         debug_assert_eq!(samples.len() % channels, 0);
67         let info = {
68             let frames = samples.len() / channels;
69             BufferInfo::new(channels, frames)
70         };
71         Self { samples, info }
72     }
73 
as_ref(&'_ self) -> BufferRef<'_, T, L>74     pub fn as_ref(&'_ self) -> BufferRef<'_, T, L> {
75         BufferRef {
76             samples: &self.samples[..],
77             info: self.info,
78         }
79     }
80 
sub_range(&'_ self, range: Range<usize>) -> BufferRef<'_, T, L>81     pub fn sub_range(&'_ self, range: Range<usize>) -> BufferRef<'_, T, L> {
82         let samples_len = range.len();
83         let samples = &self.samples[range];
84         let info = {
85             let channels = self.info.channels();
86             assert_eq!(samples_len % channels, 0);
87             let frames = samples_len / channels;
88             BufferInfo::new(channels, frames)
89         };
90         BufferRef { samples, info }
91     }
92 }
93 
94 impl<T> From<Buffer<T, Deinterleaved>> for Buffer<T, Interleaved>
95 where
96     T: Default + Copy,
97 {
from(buffer: Buffer<T, Deinterleaved>) -> Self98     fn from(buffer: Buffer<T, Deinterleaved>) -> Self {
99         Self::from(buffer.as_ref())
100     }
101 }
102 
103 impl<'a, T> From<BufferRef<'a, T, Deinterleaved>> for Buffer<T, Interleaved>
104 where
105     T: Default + Copy,
106 {
from(buffer: BufferRef<'a, T, Deinterleaved>) -> Self107     fn from(buffer: BufferRef<'a, T, Deinterleaved>) -> Self {
108         // Writing into a vec of uninitialized `samples` is about 10% faster than
109         // cloning it or creating a default-initialized one and over-writing it.
110         //
111         // # Safety
112         //
113         // The performance boost comes with a cost though:
114         // At the end of the block each and every single item in
115         // `samples` needs to have been initialized, or else you get UB!
116         let samples = {
117             // Create a vec of uninitialized samples.
118             let mut samples: Vec<MaybeUninit<T>> =
119                 vec![MaybeUninit::uninit(); buffer.samples.len()];
120 
121             // Initialize all of its values:
122             layout::interleaved_by(
123                 buffer.samples,
124                 &mut samples[..],
125                 buffer.info.channels(),
126                 |sample| MaybeUninit::new(*sample),
127             );
128 
129             // Transmute the vec to the initialized type.
130             unsafe { std::mem::transmute::<_, Vec<T>>(samples) }
131         };
132 
133         let info = buffer.info.into();
134         Self { samples, info }
135     }
136 }
137 
138 impl<T> From<Buffer<T, Interleaved>> for Buffer<T, Deinterleaved>
139 where
140     T: Default + Copy,
141 {
from(buffer: Buffer<T, Interleaved>) -> Self142     fn from(buffer: Buffer<T, Interleaved>) -> Self {
143         Self::from(buffer.as_ref())
144     }
145 }
146 
147 impl<'a, T> From<BufferRef<'a, T, Interleaved>> for Buffer<T, Deinterleaved>
148 where
149     T: Default + Copy,
150 {
from(buffer: BufferRef<'a, T, Interleaved>) -> Self151     fn from(buffer: BufferRef<'a, T, Interleaved>) -> Self {
152         // Writing into a vec of uninitialized `samples` is about 10% faster than
153         // cloning it or creating a default-initialized one and over-writing it.
154         //
155         // # Safety
156         //
157         // The performance boost comes with a cost though:
158         // At the end of the block each and every single item in
159         // `samples` needs to have been initialized, or else you get UB!
160         let samples = {
161             // Create a vec of uninitialized samples.
162             let mut samples: Vec<MaybeUninit<T>> =
163                 vec![MaybeUninit::uninit(); buffer.samples.len()];
164 
165             // Initialize the vec's values:
166             layout::deinterleaved_by(
167                 buffer.samples,
168                 &mut samples[..],
169                 buffer.info.channels(),
170                 |sample| MaybeUninit::new(*sample),
171             );
172 
173             // Everything is initialized. Transmute the vec to the initialized type.
174             unsafe { std::mem::transmute::<_, Vec<T>>(samples) }
175         };
176 
177         let info = buffer.info.into();
178         Self { samples, info }
179     }
180 }
181 
182 impl FromBytes<Interleaved> for Buffer<i16, Interleaved> {
183     type Error = ();
184 
from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>185     fn from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error> {
186         const STRIDE: usize = std::mem::size_of::<i16>();
187         assert_eq!(bytes.len() % STRIDE, 0);
188 
189         let chunks = {
190             let chunks_ptr = bytes.as_ptr() as *const [u8; STRIDE];
191             let chunks_len = bytes.len() / STRIDE;
192             unsafe { std::slice::from_raw_parts(chunks_ptr, chunks_len) }
193         };
194 
195         let samples: Vec<_> = chunks.iter().map(|chunk| B::read_i16(&chunk[..])).collect();
196 
197         let info = {
198             let frames = samples.len() / channels;
199             BufferInfo::new(channels, frames)
200         };
201         Ok(Self { samples, info })
202     }
203 }
204 
205 impl FromBytes<Deinterleaved> for Buffer<i16, Interleaved> {
206     type Error = ();
207 
from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>208     fn from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error> {
209         const STRIDE: usize = std::mem::size_of::<i16>();
210         assert_eq!(bytes.len() % STRIDE, 0);
211 
212         let chunks = {
213             let chunks_ptr = bytes.as_ptr() as *const [u8; STRIDE];
214             let chunks_len = bytes.len() / STRIDE;
215             unsafe { std::slice::from_raw_parts(chunks_ptr, chunks_len) }
216         };
217 
218         // Writing into a vec of uninitialized `samples` is about 10% faster than
219         // cloning it or creating a default-initialized one and over-writing it.
220         //
221         // # Safety
222         //
223         // The performance boost comes with a cost though:
224         // At the end of the block each and every single item in
225         // `samples` needs to have been initialized, or else you get UB!
226         let samples = unsafe {
227             init_vec(chunks.len(), |samples| {
228                 layout::interleaved_by(chunks, samples, channels, |chunk| {
229                     MaybeUninit::new(B::read_i16(&chunk[..]))
230                 });
231             })
232         };
233 
234         let info = {
235             let frames = samples.len() / channels;
236             BufferInfo::new(channels, frames)
237         };
238         Ok(Self { samples, info })
239     }
240 }
241 
242 impl FromBytes<Deinterleaved> for Buffer<i16, Deinterleaved> {
243     type Error = ();
244 
from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>245     fn from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error> {
246         const STRIDE: usize = std::mem::size_of::<i16>();
247         assert_eq!(bytes.len() % STRIDE, 0);
248 
249         let chunks = {
250             let chunks_ptr = bytes.as_ptr() as *const [u8; STRIDE];
251             let chunks_len = bytes.len() / STRIDE;
252             unsafe { std::slice::from_raw_parts(chunks_ptr, chunks_len) }
253         };
254 
255         let samples: Vec<_> = chunks.iter().map(|chunk| B::read_i16(&chunk[..])).collect();
256 
257         let info = {
258             let frames = samples.len() / channels;
259             BufferInfo::new(channels, frames)
260         };
261         Ok(Self { samples, info })
262     }
263 }
264 
265 impl FromBytes<Interleaved> for Buffer<i16, Deinterleaved> {
266     type Error = ();
267 
from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error>268     fn from_bytes<B: ByteOrder>(bytes: &[u8], channels: usize) -> Result<Self, Self::Error> {
269         const STRIDE: usize = std::mem::size_of::<i16>();
270         assert_eq!(bytes.len() % STRIDE, 0);
271 
272         let chunks = {
273             let chunks_ptr = bytes.as_ptr() as *const [u8; STRIDE];
274             let chunks_len = bytes.len() / STRIDE;
275             unsafe { std::slice::from_raw_parts(chunks_ptr, chunks_len) }
276         };
277 
278         // Writing into a vec of uninitialized `samples` is about 10% faster than
279         // cloning it or creating a default-initialized one and over-writing it.
280         //
281         // # Safety
282         //
283         // The performance boost comes with a cost though:
284         // At the end of the block each and every single item in
285         // `samples` needs to have been initialized, or else you get UB!
286         let samples = unsafe {
287             init_vec(chunks.len(), |samples| {
288                 layout::deinterleaved_by(chunks, samples, channels, |chunk| {
289                     MaybeUninit::new(B::read_i16(&chunk[..]))
290                 });
291             })
292         };
293 
294         let info = {
295             let frames = samples.len() / channels;
296             BufferInfo::new(channels, frames)
297         };
298         Ok(Self { samples, info })
299     }
300 }
301 
302 /// Creates a vec with deferred initialization.
303 ///
304 /// # Safety
305 ///
306 /// The closure `f` MUST initialize every single item in the provided slice.
init_vec<T, F>(len: usize, f: F) -> Vec<T> where MaybeUninit<T>: Clone, F: FnOnce(&mut [MaybeUninit<T>]),307 unsafe fn init_vec<T, F>(len: usize, f: F) -> Vec<T>
308 where
309     MaybeUninit<T>: Clone,
310     F: FnOnce(&mut [MaybeUninit<T>]),
311 {
312     // Create a vec of uninitialized values.
313     let mut vec: Vec<MaybeUninit<T>> = vec![MaybeUninit::uninit(); len];
314 
315     // Initialize values:
316     f(&mut vec[..]);
317 
318     // Take owner-ship away from `vec`:
319     let mut manually_drop: ManuallyDrop<_> = ManuallyDrop::new(vec);
320 
321     // Create vec of proper type from `vec`'s raw parts.
322     let ptr = manually_drop.as_mut_ptr() as *mut T;
323     let len = manually_drop.len();
324     let cap = manually_drop.capacity();
325     Vec::from_raw_parts(ptr, len, cap)
326 }
327 
328 #[cfg(test)]
329 mod tests {
330     use byteorder::NativeEndian;
331 
332     use super::*;
333 
334     #[test]
deinterleaved_from_interleaved()335     fn deinterleaved_from_interleaved() {
336         let channels = 3;
337 
338         let input_samples: Vec<i32> = vec![0, 5, 10, 1, 6, 11, 2, 7, 12, 3, 8, 13, 4, 9, 14];
339         let input: Buffer<i32, Interleaved> = Buffer::new(input_samples, channels);
340 
341         let output = Buffer::<i32, Deinterleaved>::from(input);
342 
343         let actual = output.samples;
344         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
345 
346         assert_eq!(actual, expected);
347     }
348 
349     #[test]
interleaved_from_deinterleaved()350     fn interleaved_from_deinterleaved() {
351         let channels = 3;
352 
353         let input_samples: Vec<i32> = vec![0, 3, 6, 9, 12, 1, 4, 7, 10, 13, 2, 5, 8, 11, 14];
354         let input: Buffer<i32, Deinterleaved> = Buffer::new(input_samples, channels);
355 
356         let output = Buffer::<i32, Interleaved>::from(input);
357 
358         let actual = output.samples;
359         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
360 
361         assert_eq!(actual, expected);
362     }
363 
364     #[test]
deinterleaved_from_deinterleaved_bytes()365     fn deinterleaved_from_deinterleaved_bytes() {
366         let channels = 3;
367         let stride = 2;
368 
369         let input_samples: Vec<i16> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
370         let input_bytes: &[u8] = {
371             let bytes_ptr = input_samples.as_ptr() as *const u8;
372             let bytes_len = input_samples.len() * stride;
373             unsafe { std::slice::from_raw_parts(bytes_ptr, bytes_len) }
374         };
375 
376         let output: Buffer<i16, Deinterleaved> =
377             FromBytes::<Deinterleaved>::from_bytes::<NativeEndian>(input_bytes, channels).unwrap();
378 
379         let actual = output.samples;
380         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
381 
382         assert_eq!(actual, expected);
383     }
384 
385     #[test]
deinterleaved_from_interleaved_bytes()386     fn deinterleaved_from_interleaved_bytes() {
387         let channels = 3;
388         let stride = 2;
389 
390         let input_samples: Vec<i16> = vec![0, 5, 10, 1, 6, 11, 2, 7, 12, 3, 8, 13, 4, 9, 14];
391         let input_bytes: &[u8] = {
392             let bytes_ptr = input_samples.as_ptr() as *const u8;
393             let bytes_len = input_samples.len() * stride;
394             unsafe { std::slice::from_raw_parts(bytes_ptr, bytes_len) }
395         };
396 
397         let output: Buffer<i16, Deinterleaved> =
398             FromBytes::<Interleaved>::from_bytes::<NativeEndian>(input_bytes, channels).unwrap();
399 
400         let actual = output.samples;
401         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
402 
403         assert_eq!(actual, expected);
404     }
405 
406     #[test]
interleaved_from_interleaved_bytes()407     fn interleaved_from_interleaved_bytes() {
408         let channels = 3;
409         let stride = 2;
410 
411         let input_samples: Vec<i16> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
412         let input_bytes: &[u8] = {
413             let bytes_ptr = input_samples.as_ptr() as *const u8;
414             let bytes_len = input_samples.len() * stride;
415             unsafe { std::slice::from_raw_parts(bytes_ptr, bytes_len) }
416         };
417 
418         let output: Buffer<i16, Interleaved> =
419             FromBytes::<Interleaved>::from_bytes::<NativeEndian>(input_bytes, channels).unwrap();
420 
421         let actual = output.samples;
422         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
423 
424         assert_eq!(actual, expected);
425     }
426 
427     #[test]
interleaved_from_deinterleaved_bytes()428     fn interleaved_from_deinterleaved_bytes() {
429         let channels = 3;
430         let stride = 2;
431 
432         let input_samples: Vec<i16> = vec![0, 3, 6, 9, 12, 1, 4, 7, 10, 13, 2, 5, 8, 11, 14];
433         let input_bytes: &[u8] = {
434             let bytes_ptr = input_samples.as_ptr() as *const u8;
435             let bytes_len = input_samples.len() * stride;
436             unsafe { std::slice::from_raw_parts(bytes_ptr, bytes_len) }
437         };
438 
439         let output: Buffer<i16, Interleaved> =
440             FromBytes::<Deinterleaved>::from_bytes::<NativeEndian>(input_bytes, channels).unwrap();
441 
442         let actual = output.samples;
443         let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
444 
445         assert_eq!(actual, expected);
446     }
447 }
448