geng_rodio/conversions/
channels.rs

1/// Iterator that converts from a certain channel count to another.
2#[derive(Clone, Debug)]
3pub struct ChannelCountConverter<I>
4where
5    I: Iterator,
6{
7    input: I,
8    from: cpal::ChannelCount,
9    to: cpal::ChannelCount,
10    sample_repeat: Option<I::Item>,
11    next_output_sample_pos: cpal::ChannelCount,
12}
13
14impl<I> ChannelCountConverter<I>
15where
16    I: Iterator,
17{
18    /// Initializes the iterator.
19    ///
20    /// # Panic
21    ///
22    /// Panicks if `from` or `to` are equal to 0.
23    ///
24    #[inline]
25    pub fn new(
26        input: I,
27        from: cpal::ChannelCount,
28        to: cpal::ChannelCount,
29    ) -> ChannelCountConverter<I> {
30        assert!(from >= 1);
31        assert!(to >= 1);
32
33        ChannelCountConverter {
34            input,
35            from,
36            to,
37            sample_repeat: None,
38            next_output_sample_pos: 0,
39        }
40    }
41
42    /// Destroys this iterator and returns the underlying iterator.
43    #[inline]
44    pub fn into_inner(self) -> I {
45        self.input
46    }
47}
48
49impl<I> Iterator for ChannelCountConverter<I>
50where
51    I: Iterator,
52    I::Item: Clone,
53{
54    type Item = I::Item;
55
56    fn next(&mut self) -> Option<I::Item> {
57        let result = if self.next_output_sample_pos == self.from - 1 {
58            let value = self.input.next();
59            self.sample_repeat = value.clone();
60            value
61        } else if self.next_output_sample_pos < self.from {
62            self.input.next()
63        } else {
64            self.sample_repeat.clone()
65        };
66
67        self.next_output_sample_pos += 1;
68
69        if self.next_output_sample_pos == self.to {
70            self.next_output_sample_pos -= self.to;
71
72            if self.from > self.to {
73                for _ in self.to..self.from {
74                    self.input.next(); // discarding extra input
75                }
76            }
77        }
78
79        result
80    }
81
82    #[inline]
83    fn size_hint(&self) -> (usize, Option<usize>) {
84        let (min, max) = self.input.size_hint();
85
86        let min =
87            (min / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize;
88        let max = max.map(|max| {
89            (max / self.from as usize) * self.to as usize + self.next_output_sample_pos as usize
90        });
91
92        (min, max)
93    }
94}
95
96impl<I> ExactSizeIterator for ChannelCountConverter<I>
97where
98    I: ExactSizeIterator,
99    I::Item: Clone,
100{
101}
102
103#[cfg(test)]
104mod test {
105    use super::ChannelCountConverter;
106
107    #[test]
108    fn remove_channels() {
109        let input = vec![1u16, 2, 3, 1, 2, 3];
110        let output = ChannelCountConverter::new(input.into_iter(), 3, 2).collect::<Vec<_>>();
111        assert_eq!(output, [1, 2, 1, 2]);
112
113        let input = vec![1u16, 2, 3, 4, 1, 2, 3, 4];
114        let output = ChannelCountConverter::new(input.into_iter(), 4, 1).collect::<Vec<_>>();
115        assert_eq!(output, [1, 1]);
116    }
117
118    #[test]
119    fn add_channels() {
120        let input = vec![1u16, 2, 1, 2];
121        let output = ChannelCountConverter::new(input.into_iter(), 2, 3).collect::<Vec<_>>();
122        assert_eq!(output, [1, 2, 2, 1, 2, 2]);
123
124        let input = vec![1u16, 2, 1, 2];
125        let output = ChannelCountConverter::new(input.into_iter(), 2, 4).collect::<Vec<_>>();
126        assert_eq!(output, [1, 2, 2, 2, 1, 2, 2, 2]);
127    }
128
129    #[test]
130    fn len_more() {
131        let input = vec![1u16, 2, 1, 2];
132        let output = ChannelCountConverter::new(input.into_iter(), 2, 3);
133        assert_eq!(output.len(), 6);
134    }
135
136    #[test]
137    fn len_less() {
138        let input = vec![1u16, 2, 1, 2];
139        let output = ChannelCountConverter::new(input.into_iter(), 2, 1);
140        assert_eq!(output.len(), 2);
141    }
142}