webrtc_media/audio/buffer/
layout.rs

1use crate::audio::buffer::BufferInfo;
2use crate::audio::sealed::Sealed;
3
4pub trait BufferLayout: Sized + Sealed {
5    fn index_of(info: &BufferInfo<Self>, channel: usize, frame: usize) -> usize;
6}
7
8#[derive(Eq, PartialEq, Copy, Clone, Debug)]
9pub enum Deinterleaved {}
10
11impl Sealed for Deinterleaved {}
12
13impl BufferLayout for Deinterleaved {
14    #[inline]
15    fn index_of(info: &BufferInfo<Self>, channel: usize, frame: usize) -> usize {
16        (channel * info.frames()) + frame
17    }
18}
19
20#[derive(Eq, PartialEq, Copy, Clone, Debug)]
21pub enum Interleaved {}
22
23impl Sealed for Interleaved {}
24
25impl BufferLayout for Interleaved {
26    #[inline]
27    fn index_of(info: &BufferInfo<Self>, channel: usize, frame: usize) -> usize {
28        (frame * info.channels()) + channel
29    }
30}
31
32#[cfg(test)]
33#[inline(always)]
34pub(crate) fn deinterleaved<T>(input: &[T], output: &mut [T], channels: usize)
35where
36    T: Copy,
37{
38    deinterleaved_by(input, output, channels, |sample| *sample)
39}
40
41/// De-interleaves an interleaved slice using a memory access pattern
42/// that's optimized for efficient cached (i.e. sequential) reads.
43pub(crate) fn deinterleaved_by<T, U, F>(input: &[T], output: &mut [U], channels: usize, f: F)
44where
45    F: Fn(&T) -> U,
46{
47    assert_eq!(input.len(), output.len());
48    assert_eq!(input.len() % channels, 0);
49
50    let frames = input.len() / channels;
51    let mut interleaved_index = 0;
52    for frame in 0..frames {
53        let mut deinterleaved_index = frame;
54        for _channel in 0..channels {
55            output[deinterleaved_index] = f(&input[interleaved_index]);
56            interleaved_index += 1;
57            deinterleaved_index += frames;
58        }
59    }
60}
61
62#[cfg(test)]
63#[inline(always)]
64pub(crate) fn interleaved<T>(input: &[T], output: &mut [T], channels: usize)
65where
66    T: Copy,
67{
68    interleaved_by(input, output, channels, |sample| *sample)
69}
70
71/// Interleaves an de-interleaved slice using a memory access pattern
72/// that's optimized for efficient cached (i.e. sequential) reads.
73pub(crate) fn interleaved_by<T, U, F>(input: &[T], output: &mut [U], channels: usize, f: F)
74where
75    F: Fn(&T) -> U,
76{
77    assert_eq!(input.len(), output.len());
78    assert_eq!(input.len() % channels, 0);
79
80    let frames = input.len() / channels;
81    let mut deinterleaved_index = 0;
82    for channel in 0..channels {
83        let mut interleaved_index = channel;
84        for _frame in 0..frames {
85            output[interleaved_index] = f(&input[deinterleaved_index]);
86            deinterleaved_index += 1;
87            interleaved_index += channels;
88        }
89    }
90}
91
92#[cfg(test)]
93mod tests {
94    use super::*;
95
96    #[test]
97    fn interleaved_1_channel() {
98        let input: Vec<_> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
99        let mut output = vec![0; input.len()];
100        let channels = 1;
101
102        interleaved(&input[..], &mut output[..], channels);
103
104        let actual = output;
105        let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
106
107        assert_eq!(actual, expected);
108    }
109
110    #[test]
111    fn deinterleaved_1_channel() {
112        let input: Vec<_> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
113        let mut output = vec![0; input.len()];
114        let channels = 1;
115
116        deinterleaved(&input[..], &mut output[..], channels);
117
118        let actual = output;
119        let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
120
121        assert_eq!(actual, expected);
122    }
123
124    #[test]
125    fn interleaved_2_channel() {
126        let input: Vec<_> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
127        let mut output = vec![0; input.len()];
128        let channels = 2;
129
130        interleaved(&input[..], &mut output[..], channels);
131
132        let actual = output;
133        let expected = vec![0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15];
134
135        assert_eq!(actual, expected);
136    }
137
138    #[test]
139    fn deinterleaved_2_channel() {
140        let input: Vec<_> = vec![0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15];
141        let mut output = vec![0; input.len()];
142        let channels = 2;
143
144        deinterleaved(&input[..], &mut output[..], channels);
145
146        let actual = output;
147        let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
148
149        assert_eq!(actual, expected);
150    }
151
152    #[test]
153    fn interleaved_3_channel() {
154        let input: Vec<_> = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
155        let mut output = vec![0; input.len()];
156        let channels = 3;
157
158        interleaved(&input[..], &mut output[..], channels);
159
160        let actual = output;
161        let expected = vec![0, 5, 10, 1, 6, 11, 2, 7, 12, 3, 8, 13, 4, 9, 14];
162
163        assert_eq!(actual, expected);
164    }
165
166    #[test]
167    fn deinterleaved_3_channel() {
168        let input: Vec<_> = vec![0, 5, 10, 1, 6, 11, 2, 7, 12, 3, 8, 13, 4, 9, 14];
169        let mut output = vec![0; input.len()];
170        let channels = 3;
171
172        deinterleaved(&input[..], &mut output[..], channels);
173
174        let actual = output;
175        let expected = vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];
176
177        assert_eq!(actual, expected);
178    }
179}