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