rodio/source/
uniform.rs

1use std::cmp;
2use std::time::Duration;
3
4use cpal::FromSample;
5
6use crate::conversions::{ChannelCountConverter, DataConverter, SampleRateConverter};
7use crate::{Sample, Source};
8
9use super::SeekError;
10
11/// An iterator that reads from a `Source` and converts the samples to a
12/// specific type, sample-rate and channels count.
13///
14/// It implements `Source` as well, but all the data is guaranteed to be in a
15/// single frame whose channels and samples rate have been passed to `new`.
16#[derive(Clone)]
17pub struct UniformSourceIterator<I, D>
18where
19    I: Source,
20    I::Item: Sample,
21    D: Sample,
22{
23    inner: Option<DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D>>,
24    target_channels: u16,
25    target_sample_rate: u32,
26    total_duration: Option<Duration>,
27}
28
29impl<I, D> UniformSourceIterator<I, D>
30where
31    I: Source,
32    I::Item: Sample,
33    D: Sample,
34{
35    /// Wrap a `Source` and lazily convert its samples to a specific type,
36    /// sample-rate and channels count.
37    #[inline]
38    pub fn new(
39        input: I,
40        target_channels: u16,
41        target_sample_rate: u32,
42    ) -> UniformSourceIterator<I, D> {
43        let total_duration = input.total_duration();
44        let input = UniformSourceIterator::bootstrap(input, target_channels, target_sample_rate);
45
46        UniformSourceIterator {
47            inner: Some(input),
48            target_channels,
49            target_sample_rate,
50            total_duration,
51        }
52    }
53
54    #[inline]
55    fn bootstrap(
56        input: I,
57        target_channels: u16,
58        target_sample_rate: u32,
59    ) -> DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D> {
60        // Limit the frame length to something reasonable
61        let frame_len = input.current_frame_len().map(|x| x.min(32768));
62
63        let from_channels = input.channels();
64        let from_sample_rate = input.sample_rate();
65
66        let input = Take {
67            iter: input,
68            n: frame_len,
69        };
70        let input = SampleRateConverter::new(
71            input,
72            cpal::SampleRate(from_sample_rate),
73            cpal::SampleRate(target_sample_rate),
74            from_channels,
75        );
76        let input = ChannelCountConverter::new(input, from_channels, target_channels);
77
78        DataConverter::new(input)
79    }
80}
81
82impl<I, D> Iterator for UniformSourceIterator<I, D>
83where
84    I: Source,
85    I::Item: Sample,
86    D: FromSample<I::Item> + Sample,
87{
88    type Item = D;
89
90    #[inline]
91    fn next(&mut self) -> Option<D> {
92        if let Some(value) = self.inner.as_mut().unwrap().next() {
93            return Some(value);
94        }
95
96        let input = self
97            .inner
98            .take()
99            .unwrap()
100            .into_inner()
101            .into_inner()
102            .into_inner()
103            .iter;
104
105        let mut input =
106            UniformSourceIterator::bootstrap(input, self.target_channels, self.target_sample_rate);
107
108        let value = input.next();
109        self.inner = Some(input);
110        value
111    }
112
113    #[inline]
114    fn size_hint(&self) -> (usize, Option<usize>) {
115        (self.inner.as_ref().unwrap().size_hint().0, None)
116    }
117}
118
119impl<I, D> Source for UniformSourceIterator<I, D>
120where
121    I: Iterator + Source,
122    I::Item: Sample,
123    D: FromSample<I::Item> + Sample,
124{
125    #[inline]
126    fn current_frame_len(&self) -> Option<usize> {
127        None
128    }
129
130    #[inline]
131    fn channels(&self) -> u16 {
132        self.target_channels
133    }
134
135    #[inline]
136    fn sample_rate(&self) -> u32 {
137        self.target_sample_rate
138    }
139
140    #[inline]
141    fn total_duration(&self) -> Option<Duration> {
142        self.total_duration
143    }
144
145    #[inline]
146    fn try_seek(&mut self, pos: Duration) -> Result<(), SeekError> {
147        if let Some(input) = self.inner.as_mut() {
148            input
149                .inner_mut()
150                .inner_mut()
151                .inner_mut()
152                .inner_mut()
153                .try_seek(pos)
154        } else {
155            Ok(())
156        }
157    }
158}
159
160#[derive(Clone, Debug)]
161struct Take<I> {
162    iter: I,
163    n: Option<usize>,
164}
165
166impl<I> Take<I> {
167    #[inline]
168    pub fn inner_mut(&mut self) -> &mut I {
169        &mut self.iter
170    }
171}
172
173impl<I> Iterator for Take<I>
174where
175    I: Iterator,
176{
177    type Item = <I as Iterator>::Item;
178
179    #[inline]
180    fn next(&mut self) -> Option<<I as Iterator>::Item> {
181        if let Some(n) = &mut self.n {
182            if *n != 0 {
183                *n -= 1;
184                self.iter.next()
185            } else {
186                None
187            }
188        } else {
189            self.iter.next()
190        }
191    }
192
193    #[inline]
194    fn size_hint(&self) -> (usize, Option<usize>) {
195        if let Some(n) = self.n {
196            let (lower, upper) = self.iter.size_hint();
197
198            let lower = cmp::min(lower, n);
199
200            let upper = match upper {
201                Some(x) if x < n => Some(x),
202                _ => Some(n),
203            };
204
205            (lower, upper)
206        } else {
207            self.iter.size_hint()
208        }
209    }
210}
211
212impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}