webrtc_media/audio/
buffer.rs

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