Skip to main content

rtc_media/audio/
buffer.rs

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