fixed_resample/
interleave.rs

1use std::{num::NonZeroUsize, ops::Range};
2
3use rubato::Sample;
4
5/// Interleave the given channels into the output buffer.
6///
7/// * `input` - The input channels.
8/// * `output` - The interleaved output buffer to write to.
9/// * `num_out_channels` - The number of interleaved channels in `output`.
10/// * `in_range` - The range in each channel in `input` to read from.
11pub fn interleave<T: Sample, Vin: AsRef<[T]>>(
12    input: &[Vin],
13    output: &mut [T],
14    num_out_channels: NonZeroUsize,
15    in_range: Range<usize>,
16) {
17    let in_frames = in_range.end - in_range.start;
18    let out_frames = output.len() / num_out_channels.get();
19
20    let frames = in_frames.min(out_frames);
21
22    let in_range = in_range.start..in_range.start + frames;
23
24    if num_out_channels.get() == 1 {
25        // Mono, no need to interleave.
26        output[..frames].copy_from_slice(&input[0].as_ref()[in_range.clone()]);
27
28        return;
29    }
30
31    if num_out_channels.get() == 2 && input.len() >= 2 {
32        // Provide an optimized loop for stereo.
33        let in_ch_1 = &input[0].as_ref()[in_range.clone()];
34        let in_ch_2 = &input[1].as_ref()[in_range.clone()];
35
36        for ((os, &s1), &s2) in output.chunks_exact_mut(2).zip(in_ch_1).zip(in_ch_2) {
37            os[0] = s1;
38            os[1] = s2
39        }
40
41        return;
42    }
43
44    for (ch_i, in_ch) in input.iter().enumerate() {
45        if ch_i >= num_out_channels.get() {
46            break;
47        }
48
49        for (os, &is) in output
50            .chunks_exact_mut(num_out_channels.get())
51            .zip(&in_ch.as_ref()[in_range.clone()])
52        {
53            os[ch_i] = is;
54        }
55    }
56}
57
58/// Deinterleave the given data into the output buffers.
59///
60/// * `input` - The interleaved input data.
61/// * `output` - The de-interleaved output buffer to write to.
62/// * `num_in_channels` - The number of interleaved channels in `input`.
63/// * `out_range` - The range in each channel in `output` to write to.
64pub fn deinterleave<T: Sample, Vout: AsMut<[T]>>(
65    input: &[T],
66    output: &mut [Vout],
67    num_in_channels: NonZeroUsize,
68    out_range: Range<usize>,
69) {
70    let out_frames = out_range.end - out_range.start;
71    let in_frames = input.len() / num_in_channels.get();
72
73    let frames = out_frames.min(in_frames);
74
75    let out_range = out_range.start..out_range.start + frames;
76
77    if num_in_channels.get() == 1 {
78        // Mono, no need to deinterleave.
79        output[0].as_mut()[out_range.clone()].copy_from_slice(&input[..frames]);
80
81        return;
82    }
83
84    if num_in_channels.get() == 2 && output.len() >= 2 {
85        // Provide an optimized loop for stereo.
86        let (out_ch_1, out_ch_2) = output.split_first_mut().unwrap();
87
88        for ((s, os1), os2) in input
89            .chunks_exact(2)
90            .zip(out_ch_1.as_mut()[out_range.clone()].iter_mut())
91            .zip(out_ch_2[0].as_mut()[out_range.clone()].iter_mut())
92        {
93            *os1 = s[0];
94            *os2 = s[1];
95        }
96
97        return;
98    }
99
100    for (ch_i, out_ch) in output.iter_mut().enumerate() {
101        if ch_i >= num_in_channels.get() {
102            break;
103        }
104
105        for (s, os) in input
106            .chunks_exact(num_in_channels.get())
107            .zip(&mut out_ch.as_mut()[out_range.clone()])
108        {
109            *os = s[ch_i];
110        }
111    }
112}