geng_rodio/source/
uniform.rs1use std::cmp;
2use std::time::Duration;
3
4use cpal::FromSample;
5
6use crate::conversions::{ChannelCountConverter, DataConverter, SampleRateConverter};
7use crate::{Sample, Source};
8
9#[derive(Clone)]
15pub struct UniformSourceIterator<I, D>
16where
17 I: Source,
18 I::Item: Sample,
19 D: Sample,
20{
21 inner: Option<DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D>>,
22 target_channels: u16,
23 target_sample_rate: u32,
24 total_duration: Option<Duration>,
25}
26
27impl<I, D> UniformSourceIterator<I, D>
28where
29 I: Source,
30 I::Item: Sample,
31 D: Sample,
32{
33 #[inline]
34 pub fn new(
35 input: I,
36 target_channels: u16,
37 target_sample_rate: u32,
38 ) -> UniformSourceIterator<I, D> {
39 let total_duration = input.total_duration();
40 let input = UniformSourceIterator::bootstrap(input, target_channels, target_sample_rate);
41
42 UniformSourceIterator {
43 inner: Some(input),
44 target_channels,
45 target_sample_rate,
46 total_duration,
47 }
48 }
49
50 #[inline]
51 fn bootstrap(
52 input: I,
53 target_channels: u16,
54 target_sample_rate: u32,
55 ) -> DataConverter<ChannelCountConverter<SampleRateConverter<Take<I>>>, D> {
56 let frame_len = input.current_frame_len().map(|x| x.min(32768));
58
59 let from_channels = input.channels();
60 let from_sample_rate = input.sample_rate();
61
62 let input = Take {
63 iter: input,
64 n: frame_len,
65 };
66 let input = SampleRateConverter::new(
67 input,
68 cpal::SampleRate(from_sample_rate),
69 cpal::SampleRate(target_sample_rate),
70 from_channels,
71 );
72 let input = ChannelCountConverter::new(input, from_channels, target_channels);
73
74 DataConverter::new(input)
75 }
76}
77
78impl<I, D> Iterator for UniformSourceIterator<I, D>
79where
80 I: Source,
81 I::Item: Sample,
82 D: FromSample<I::Item> + Sample,
83{
84 type Item = D;
85
86 #[inline]
87 fn next(&mut self) -> Option<D> {
88 if let Some(value) = self.inner.as_mut().unwrap().next() {
89 return Some(value);
90 }
91
92 let input = self
93 .inner
94 .take()
95 .unwrap()
96 .into_inner()
97 .into_inner()
98 .into_inner()
99 .iter;
100
101 let mut input =
102 UniformSourceIterator::bootstrap(input, self.target_channels, self.target_sample_rate);
103
104 let value = input.next();
105 self.inner = Some(input);
106 value
107 }
108
109 #[inline]
110 fn size_hint(&self) -> (usize, Option<usize>) {
111 (self.inner.as_ref().unwrap().size_hint().0, None)
112 }
113}
114
115impl<I, D> Source for UniformSourceIterator<I, D>
116where
117 I: Iterator + Source,
118 I::Item: Sample,
119 D: FromSample<I::Item> + Sample,
120{
121 #[inline]
122 fn current_frame_len(&self) -> Option<usize> {
123 None
124 }
125
126 #[inline]
127 fn channels(&self) -> u16 {
128 self.target_channels
129 }
130
131 #[inline]
132 fn sample_rate(&self) -> u32 {
133 self.target_sample_rate
134 }
135
136 #[inline]
137 fn total_duration(&self) -> Option<Duration> {
138 self.total_duration
139 }
140}
141
142#[derive(Clone, Debug)]
143struct Take<I> {
144 iter: I,
145 n: Option<usize>,
146}
147
148impl<I> Iterator for Take<I>
149where
150 I: Iterator,
151{
152 type Item = <I as Iterator>::Item;
153
154 #[inline]
155 fn next(&mut self) -> Option<<I as Iterator>::Item> {
156 if let Some(n) = &mut self.n {
157 if *n != 0 {
158 *n -= 1;
159 self.iter.next()
160 } else {
161 None
162 }
163 } else {
164 self.iter.next()
165 }
166 }
167
168 #[inline]
169 fn size_hint(&self) -> (usize, Option<usize>) {
170 if let Some(n) = self.n {
171 let (lower, upper) = self.iter.size_hint();
172
173 let lower = cmp::min(lower, n);
174
175 let upper = match upper {
176 Some(x) if x < n => Some(x),
177 _ => Some(n),
178 };
179
180 (lower, upper)
181 } else {
182 self.iter.size_hint()
183 }
184 }
185}
186
187impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {}