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#[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 #[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 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 {}