rodio/source/
uniform.rs

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