audio_engine/
converter.rs

1//! Structs for converting SoundSource parameters, like number of channels and sample rate.
2
3use super::SoundSource;
4use std::vec;
5
6#[cfg(test)]
7mod test {
8    use crate::SoundSource;
9
10    use super::{ChannelConverter, SampleRateConverter};
11
12    struct BufferSource {
13        sample_rate: u32,
14        channels: u16,
15        buffer: Vec<i16>,
16        i: usize,
17    }
18    impl SoundSource for BufferSource {
19        fn channels(&self) -> u16 {
20            self.channels
21        }
22
23        fn sample_rate(&self) -> u32 {
24            self.sample_rate
25        }
26
27        fn reset(&mut self) {
28            self.i = 0;
29        }
30
31        fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
32            let i = self.i;
33            let len = (self.buffer.len() - i).min(buffer.len());
34            buffer[0..len].copy_from_slice(&self.buffer[i..i + len]);
35            self.i += len;
36            len
37        }
38    }
39
40    #[test]
41    fn sample_rate_1_3() {
42        let inner = BufferSource {
43            sample_rate: 10,
44            channels: 1,
45            buffer: vec![0, 3, 6, 9, 12],
46            i: 0,
47        };
48        let mut outer = SampleRateConverter::new(inner, 30);
49
50        let mut output = [0; 3];
51        let len = outer.write_samples(&mut output[..]);
52
53        assert_eq!(len, output.len());
54        assert_eq!(output, [0, 1, 2]);
55
56        let mut output = [0; 4];
57
58        let len = outer.write_samples(&mut output[..]);
59        assert_eq!(len, output.len());
60        assert_eq!(output, [3, 4, 5, 6]);
61
62        let len = outer.write_samples(&mut output[..]);
63        assert_eq!(len, output.len());
64        assert_eq!(output, [7, 8, 9, 10]);
65
66        let len = outer.write_samples(&mut output[..]);
67        assert_eq!(len, 2);
68        assert_eq!(output[..len], [11, 12]);
69
70        let len = outer.write_samples(&mut output[..]);
71        assert_eq!(len, 0);
72    }
73
74    #[test]
75    fn sample_rate_2_3() {
76        let inner = BufferSource {
77            sample_rate: 20,
78            channels: 1,
79            buffer: vec![0, 3, 6, 9, 12, 15],
80            i: 0,
81        };
82        let mut outer = SampleRateConverter::new(inner, 30);
83
84        let mut output = [0; 3];
85        let len = outer.write_samples(&mut output[..]);
86
87        assert_eq!(len, output.len());
88        assert_eq!(output, [0, 2, 4]);
89
90        let mut output = [0; 4];
91
92        let len = outer.write_samples(&mut output[..]);
93        assert_eq!(len, output.len());
94        assert_eq!(output, [6, 8, 10, 12]);
95
96        let len = outer.write_samples(&mut output[..]);
97        assert_eq!(len, 1);
98        assert_eq!(output[..len], [14]);
99
100        let len = outer.write_samples(&mut output[..]);
101        assert_eq!(len, 0);
102    }
103
104    #[test]
105    fn sample_rate_3_2() {
106        let inner = BufferSource {
107            sample_rate: 30,
108            channels: 1,
109            buffer: vec![0, 2, 4, 6, 8, 10, 12, 14, 16, 18],
110            i: 0,
111        };
112        let mut outer = SampleRateConverter::new(inner, 20);
113
114        let mut output = [0; 2];
115        let len = outer.write_samples(&mut output[..]);
116
117        assert_eq!(len, output.len());
118        assert_eq!(output, [0, 3]);
119
120        let mut output = [0; 4];
121
122        let len = outer.write_samples(&mut output[..]);
123        assert_eq!(len, output.len());
124        assert_eq!(output, [6, 9, 12, 15]);
125
126        let len = outer.write_samples(&mut output[..]);
127        assert_eq!(len, 1);
128        assert_eq!(output[..len], [18]);
129
130        let len = outer.write_samples(&mut output[..]);
131        assert_eq!(len, 0);
132    }
133
134    #[test]
135    fn channels_1_3() {
136        let inner = BufferSource {
137            sample_rate: 30,
138            channels: 1,
139            buffer: vec![-2, -1, 0, 1, 2],
140            i: 0,
141        };
142
143        let out_channels = 3;
144
145        let mut output = vec![0; 3 * 5];
146        let mut outer = ChannelConverter::new(inner, out_channels);
147
148        outer.write_samples(&mut output);
149
150        assert_eq!(output, [-2, -2, -2, -1, -1, -1, 0, 0, 0, 1, 1, 1, 2, 2, 2]);
151    }
152
153    #[test]
154    fn channels_3_1() {
155        let inner = BufferSource {
156            sample_rate: 30,
157            channels: 3,
158            buffer: vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
159            i: 0,
160        };
161
162        let mut output = vec![0; 3];
163        let mut outer = ChannelConverter::new(inner, 1);
164
165        outer.write_samples(&mut output);
166
167        assert_eq!(output, [2, 5, 8]);
168    }
169
170    #[test]
171    fn channels_2_2() {
172        let inner = BufferSource {
173            sample_rate: 30,
174            channels: 2,
175            buffer: vec![1, 2, 3, 4, 5, 6, 7, 8, 9],
176            i: 0,
177        };
178
179        let input = inner.buffer.clone();
180        let mut output = vec![0; inner.buffer.len()];
181        let mut outer = ChannelConverter::new(inner, 2);
182        outer.write_samples(&mut output);
183        assert_eq!(output, input);
184    }
185
186    #[test]
187    fn channels_4_5() {
188        let inner = BufferSource {
189            sample_rate: 30,
190            channels: 4,
191            buffer: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
192            i: 0,
193        };
194        let mut output = vec![0; inner.buffer.len() / 4 * 5];
195        let mut outer = ChannelConverter::new(inner, 5);
196        outer.write_samples(&mut output);
197        assert_eq!(output, &[2, 2, 2, 2, 2, 6, 6, 6, 6, 6, 10, 10, 10, 10, 10,]);
198    }
199
200    #[test]
201    fn channels_5_3() {
202        let inner = BufferSource {
203            sample_rate: 30,
204            channels: 5,
205            buffer: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
206            i: 0,
207        };
208        let mut output = vec![0; inner.buffer.len() / 5 * 3];
209        let mut outer = ChannelConverter::new(inner, 3);
210        outer.write_samples(&mut output);
211        assert_eq!(output, &[3, 3, 3, 8, 8, 8, 13, 13, 13]);
212
213        let inner = BufferSource {
214            sample_rate: 30,
215            channels: 5,
216            buffer: vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
217            i: 0,
218        };
219        let mut output = vec![0; 3];
220        let mut outer = ChannelConverter::new(inner, 3);
221        let len = outer.write_samples(&mut output);
222        assert_eq!(output, &[3, 3, 3]);
223        assert_eq!(len, 3);
224        let len = outer.write_samples(&mut output);
225        assert_eq!(output, &[8, 8, 8]);
226        assert_eq!(len, 3);
227        let len = outer.write_samples(&mut output);
228        assert_eq!(output, &[13, 13, 13]);
229        assert_eq!(len, 3);
230        let len = outer.write_samples(&mut output);
231        assert_eq!(&output[..len], &[]);
232        assert_eq!(len, 0);
233    }
234}
235
236/// Convert a SoundSource to a diferent number of channels.
237///
238/// If the number of channels in the inner SoundSource is equal to the output number of channels,
239/// no conversion will be performed. Otherwise, each channel of the output will receive the average
240/// of all input channels.
241pub struct ChannelConverter<T: SoundSource> {
242    inner: T,
243    /// The number of channels to convert to.
244    channels: u16,
245    /// A buffer to temporary hold the input samples.
246    in_buffer: Vec<i16>,
247}
248impl<T: SoundSource> ChannelConverter<T> {
249    /// Create a new ChannelConverter.
250    ///
251    /// This will convert from the number of channels of `inner`, outputing the given number of
252    /// `channels`.
253    pub fn new(inner: T, channels: u16) -> Self {
254        Self {
255            inner,
256            channels,
257            in_buffer: Vec::new(),
258        }
259    }
260}
261impl<T: SoundSource> SoundSource for ChannelConverter<T> {
262    fn channels(&self) -> u16 {
263        self.channels
264    }
265    fn sample_rate(&self) -> u32 {
266        self.inner.sample_rate()
267    }
268    fn reset(&mut self) {
269        self.inner.reset()
270    }
271    fn write_samples(&mut self, out_buffer: &mut [i16]) -> usize {
272        let out_channels = self.channels as usize;
273        let in_channels = self.inner.channels() as usize;
274
275        use std::cmp::Ordering;
276        match in_channels.cmp(&out_channels) {
277            Ordering::Equal => self.inner.write_samples(out_buffer),
278            Ordering::Less => {
279                // To avoid a allocation, the input samples will be written to `out_buffer`, and
280                // then converted to output samples.
281                let in_len = out_buffer.len() / out_channels * in_channels;
282                let in_len = self.inner.write_samples(&mut out_buffer[0..in_len]);
283
284                let mut sum: i32 = 0;
285                for i in (0..in_len).rev() {
286                    sum += out_buffer[i] as i32;
287                    if i % in_channels == 0 {
288                        let frame_index = i / in_channels * out_channels;
289                        let mean = (sum / in_channels as i32) as i16;
290                        for c in 0..out_channels {
291                            out_buffer[frame_index + c] = mean;
292                        }
293                        sum = 0;
294                    }
295                }
296                in_len * out_channels / in_channels
297            }
298            Ordering::Greater => {
299                // There are more input samples than output samples, so the allocation avoidance of
300                // the previous arm does not work.
301                let in_buffer = {
302                    let len = out_buffer.len() / out_channels * in_channels;
303                    if len > self.in_buffer.len() {
304                        self.in_buffer.resize(len, 0);
305                    }
306                    &mut self.in_buffer[0..len]
307                };
308                let in_len = self.inner.write_samples(in_buffer);
309
310                let mut sum: i32 = 0;
311                for (i, &in_sample) in in_buffer[0..in_len].iter().enumerate() {
312                    sum += in_sample as i32;
313                    if (i + 1) % in_channels == 0 {
314                        let frame_index = i / in_channels * out_channels;
315                        let mean = (sum / in_channels as i32) as i16;
316                        for c in 0..out_channels {
317                            out_buffer[frame_index + c] = mean;
318                        }
319                        sum = 0;
320                    }
321                }
322                in_len * out_channels / in_channels
323            }
324        }
325    }
326}
327
328/// Do a sample rate convertion using linear interpolation.
329pub struct SampleRateConverter<T: SoundSource> {
330    inner: T,
331    /// The output sample_rate
332    output_sample_rate: u32,
333    /// a buffer contained a `in_len` of input samples, that will be completelly converted in
334    /// `out_len` of ouput samples.
335    in_buffer: Box<[i16]>,
336    out_len: usize,
337    /// The current length of valid samples in `in_buffer`.
338    len: usize,
339    /// The index of the next sample to be generated in the `out_buffer`. `out_buffer` don't exist
340    /// in fact, and it samples are directly outputed in `write_samples`.
341    iter: usize,
342}
343impl<T: SoundSource> SampleRateConverter<T> {
344    /// Create a new SampleRateConverter.
345    ///
346    /// This will convert from the sample rate of `inner`, outputing with the given `sample_rate`.
347    pub fn new(inner: T, output_sample_rate: u32) -> Self {
348        use gcd::Gcd;
349
350        // divide the input sample_rate and the ouput sample_rate by its gcd, to find to smallest
351        // pair of input/output buffers that can be fully converted between.
352        let gcd = inner.sample_rate().gcd(output_sample_rate) as usize;
353        let in_len = inner.sample_rate() as usize / gcd * inner.channels() as usize;
354        let out_len = output_sample_rate as usize / gcd * inner.channels() as usize;
355
356        let channels = inner.channels() as usize;
357
358        // in_buffer also contains the first sample of the next buffer.
359        let in_buffer = vec![0; in_len + channels].into_boxed_slice();
360
361        let mut this = Self {
362            len: in_buffer.len() - 1,
363            in_buffer,
364            iter: out_len,
365            out_len,
366            inner,
367            output_sample_rate,
368        };
369
370        this.reset();
371
372        this
373    }
374}
375impl<T: SoundSource> SoundSource for SampleRateConverter<T> {
376    fn channels(&self) -> u16 {
377        self.inner.channels()
378    }
379    fn sample_rate(&self) -> u32 {
380        self.output_sample_rate
381    }
382    fn reset(&mut self) {
383        self.inner.reset();
384
385        let channels = self.inner.channels() as usize;
386        self.len = self.inner.write_samples(&mut self.in_buffer[..]) - channels;
387        self.iter = 0;
388    }
389    fn write_samples(&mut self, buffer: &mut [i16]) -> usize {
390        let channels = self.inner.channels() as usize;
391
392        if self.output_sample_rate == self.inner.sample_rate() {
393            return self.inner.write_samples(buffer);
394        }
395
396        let mut i = 0;
397        while i < buffer.len() {
398            let in_len = self.in_buffer.len() - channels;
399            fn div_up(a: usize, b: usize) -> usize {
400                a / b + (a % b != 0) as usize
401            }
402            let curr_out_len = div_up(self.out_len * self.len, in_len) / channels * channels;
403
404            // if next sample is out of bounds, reset in_buffer
405            if self.iter >= curr_out_len {
406                // if self.len is smaller than in_len, the inner sound already finished.
407                if self.len < in_len {
408                    return i;
409                }
410
411                // the last sample of the last buffer is the start sample of this buffer.
412                self.in_buffer.copy_within(self.len.., 0);
413
414                self.len = self.inner.write_samples(&mut self.in_buffer[channels..]);
415                self.iter = 0;
416            }
417
418            // j is the float position in in_buffer.
419            let j = ((self.iter / channels) * in_len) as f32 / self.out_len as f32;
420
421            let t = j.fract();
422            let j = j as usize * channels;
423
424            for c in 0..channels {
425                // interpolate by t, curr and next sample
426                buffer[i + c] = (self.in_buffer[j + c] as f32 * (1.0 - t)
427                    + self.in_buffer[j + c + channels] as f32 * t)
428                    as i16;
429            }
430
431            self.iter += channels;
432            i += channels;
433        }
434
435        buffer.len()
436    }
437}