1use crate::common::{ChannelCount, SampleRate};
2use crate::{math, Sample};
3use num_rational::Ratio;
4use std::collections::VecDeque;
5use std::mem;
6
7#[derive(Clone, Debug)]
9pub struct SampleRateConverter<I>
10where
11 I: Iterator,
12{
13 input: I,
15 from: u32,
17 to: u32,
19 channels: ChannelCount,
21 current_span: Vec<I::Item>,
23 current_span_pos_in_chunk: u32,
25 next_frame: Vec<I::Item>,
27 next_output_span_pos_in_chunk: u32,
30 output_buffer: VecDeque<I::Item>,
32}
33
34impl<I> SampleRateConverter<I>
35where
36 I: Iterator,
37{
38 #[inline]
52 pub fn new(
53 mut input: I,
54 from: SampleRate,
55 to: SampleRate,
56 num_channels: ChannelCount,
57 ) -> SampleRateConverter<I> {
58 let (first_samples, next_samples) = if from == to {
59 (Vec::new(), Vec::new())
61 } else {
62 let first = input
63 .by_ref()
64 .take(num_channels.get() as usize)
65 .collect::<Vec<_>>();
66 let next = input
67 .by_ref()
68 .take(num_channels.get() as usize)
69 .collect::<Vec<_>>();
70 (first, next)
71 };
72
73 let (to, from) = Ratio::new(to.get(), from.get()).into_raw();
75
76 SampleRateConverter {
77 input,
78 from,
79 to,
80 channels: num_channels,
81 current_span_pos_in_chunk: 0,
82 next_output_span_pos_in_chunk: 0,
83 current_span: first_samples,
84 next_frame: next_samples,
85 output_buffer: VecDeque::with_capacity(
87 (to as f32 / from as f32).ceil() as usize * num_channels.get() as usize,
88 ),
89 }
90 }
91
92 #[inline]
94 pub fn into_inner(self) -> I {
95 self.input
96 }
97
98 #[inline]
100 pub fn inner_mut(&mut self) -> &mut I {
101 &mut self.input
102 }
103
104 #[inline]
106 pub fn inner(&self) -> &I {
107 &self.input
108 }
109
110 fn next_input_span(&mut self) {
111 self.current_span_pos_in_chunk += 1;
112
113 mem::swap(&mut self.current_span, &mut self.next_frame);
114 self.next_frame.clear();
115 for _ in 0..self.channels.get() {
116 if let Some(i) = self.input.next() {
117 self.next_frame.push(i);
118 } else {
119 break;
120 }
121 }
122 }
123}
124
125impl<I> Iterator for SampleRateConverter<I>
126where
127 I: Iterator<Item = Sample>,
128{
129 type Item = I::Item;
130
131 fn next(&mut self) -> Option<I::Item> {
132 if self.from == self.to {
134 debug_assert_eq!(self.from, 1);
135 return self.input.next();
136 }
137
138 if let Some(sample) = self.output_buffer.pop_front() {
140 return Some(sample);
141 }
142
143 if self.next_output_span_pos_in_chunk == self.to {
147 self.next_output_span_pos_in_chunk = 0;
149
150 self.next_input_span();
151 while self.current_span_pos_in_chunk != self.from {
152 self.next_input_span();
153 }
154 self.current_span_pos_in_chunk = 0;
155 } else {
156 let req_left_sample =
158 (self.from * self.next_output_span_pos_in_chunk / self.to) % self.from;
159
160 while self.current_span_pos_in_chunk != req_left_sample {
164 self.next_input_span();
165 debug_assert!(self.current_span_pos_in_chunk < self.from);
166 }
167 }
168
169 let mut result = None;
173 let numerator = (self.from * self.next_output_span_pos_in_chunk) % self.to;
174 for (off, (cur, next)) in self
175 .current_span
176 .iter()
177 .zip(self.next_frame.iter())
178 .enumerate()
179 {
180 let sample = math::lerp(*cur, *next, numerator, self.to);
181
182 if off == 0 {
183 result = Some(sample);
184 } else {
185 self.output_buffer.push_back(sample);
186 }
187 }
188
189 self.next_output_span_pos_in_chunk += 1;
191
192 if result.is_some() {
193 result
194 } else {
195 let mut current_span = self.current_span.drain(..);
197 let r = current_span.next()?;
198 self.output_buffer.extend(current_span);
199 Some(r)
200 }
201 }
202
203 #[inline]
204 fn size_hint(&self) -> (usize, Option<usize>) {
205 let apply = |samples: usize| {
206 let samples_after_chunk = samples;
209 let samples_after_chunk = if self.current_span_pos_in_chunk == self.from - 1 {
211 samples_after_chunk + self.next_frame.len()
212 } else {
213 samples_after_chunk
214 };
215 let samples_after_chunk = samples_after_chunk.saturating_sub(
217 self.from.saturating_sub(self.current_span_pos_in_chunk + 2) as usize
218 * usize::from(self.channels.get()),
219 );
220 let samples_after_chunk = samples_after_chunk * self.to as usize / self.from as usize;
223
224 let samples_current_chunk = (self.to - self.next_output_span_pos_in_chunk) as usize
227 * usize::from(self.channels.get());
228
229 samples_current_chunk + samples_after_chunk + self.output_buffer.len()
230 };
231
232 if self.from == self.to {
233 self.input.size_hint()
234 } else {
235 let (min, max) = self.input.size_hint();
236 (apply(min), max.map(apply))
237 }
238 }
239}
240
241impl<I> ExactSizeIterator for SampleRateConverter<I> where I: ExactSizeIterator<Item = Sample> {}
242
243#[cfg(test)]
244mod test {
245 use super::SampleRateConverter;
246 use crate::common::{ChannelCount, SampleRate};
247 use crate::math::nz;
248 use crate::Sample;
249 use core::time::Duration;
250 use quickcheck::{quickcheck, TestResult};
251
252 quickcheck! {
253 fn empty(from: SampleRate, to: SampleRate, channels: ChannelCount) -> TestResult {
255 if from.get() > 384_000*2 || to.get() > 384_000*2 || channels.get() > 128
256 {
257 return TestResult::discard();
258 }
259
260 let input: Vec<Sample> = Vec::new();
261 let output =
262 SampleRateConverter::new(input.into_iter(), from, to, channels)
263 .collect::<Vec<_>>();
264
265 assert_eq!(output, []);
266 TestResult::passed()
267 }
268
269 fn identity(from: SampleRate, channels: ChannelCount, input: Vec<i16>) -> TestResult {
271 if channels.get() > 128 { return TestResult::discard(); }
272 let input = Vec::from_iter(input.iter().map(|x| *x as Sample));
273
274 let output =
275 SampleRateConverter::new(input.clone().into_iter(), from, from, channels)
276 .collect::<Vec<_>>();
277
278 TestResult::from_bool(input == output)
279 }
280
281 fn divide_sample_rate(to: SampleRate, k: u16, input: Vec<i16>, channels: ChannelCount) -> TestResult {
284 if k == 0 || channels.get() > 128 || to.get() > 48000 {
285 return TestResult::discard();
286 }
287 let input = Vec::from_iter(input.iter().map(|x| *x as Sample));
288
289 let to = to as SampleRate;
290 let from = to.get() * k as u32;
291
292 let input = {
294 let ns = channels.get() as usize;
295 let mut i = input;
296 i.truncate(ns * (i.len() / ns));
297 i
298 };
299
300 let output =
301 SampleRateConverter::new(input.clone().into_iter(), SampleRate::new(from).expect("to is nonzero and k is nonzero"), to, channels)
302 .collect::<Vec<_>>();
303
304 TestResult::from_bool(input.chunks_exact(channels.get().into())
305 .step_by(k as usize).collect::<Vec<_>>().concat() == output)
306 }
307
308 fn multiply_sample_rate(from: SampleRate, k: u8, input: Vec<i16>, channels: ChannelCount) -> TestResult {
311 if k == 0 || from.get() > u16::MAX as u32 || channels.get() > 128 {
312 return TestResult::discard();
313 }
314 let input = Vec::from_iter(input.iter().map(|x| *x as Sample));
315
316 let from = from as SampleRate;
317 let to = from.get() * k as u32;
318
319 let input = {
321 let ns = channels.get() as usize;
322 let mut i = input;
323 i.truncate(ns * (i.len() / ns));
324 i
325 };
326
327 let output =
328 SampleRateConverter::new(input.clone().into_iter(), from, SampleRate::new(to).unwrap(), channels)
329 .collect::<Vec<_>>();
330
331 TestResult::from_bool(input ==
332 output.chunks_exact(channels.get().into())
333 .step_by(k as usize).collect::<Vec<_>>().concat())
334 }
335
336 #[ignore]
337 fn preserve_durations(d: Duration, freq: f32, to: SampleRate) -> TestResult {
341 use crate::source::{SineWave, Source};
342
343 let source = SineWave::new(freq).take_duration(d);
344 let from = source.sample_rate();
345
346 let resampled =
347 SampleRateConverter::new(source, from, to, nz!(1));
348 let duration =
349 Duration::from_secs_f32(resampled.count() as f32 / to.get() as f32);
350
351 let delta = duration.abs_diff(d);
352 TestResult::from_bool(delta < Duration::from_millis(1))
353 }
354 }
355
356 #[test]
357 fn upsample() {
358 let input = vec![2.0, 16.0, 4.0, 18.0, 6.0, 20.0, 8.0, 22.0];
359 let output = SampleRateConverter::new(input.into_iter(), nz!(2000), nz!(3000), nz!(2));
360 assert_eq!(output.len(), 12); let output = output.map(|x| x.trunc()).collect::<Vec<_>>();
363 assert_eq!(
364 output,
365 [2.0, 16.0, 3.0, 17.0, 4.0, 18.0, 6.0, 20.0, 7.0, 21.0, 8.0, 22.0]
366 );
367 }
368
369 #[test]
370 fn upsample2() {
371 let input = vec![1.0, 14.0];
372 let output = SampleRateConverter::new(input.into_iter(), nz!(1000), nz!(7000), nz!(1));
373 let size_estimation = output.len();
374 let output = output.map(|x| x.trunc()).collect::<Vec<_>>();
375 assert_eq!(output, [1.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0]);
376 assert!((size_estimation as f32 / output.len() as f32).abs() < 2.0);
377 }
378
379 #[test]
380 fn downsample() {
381 let input = Vec::from_iter((0..17).map(|x| x as Sample));
382 let output = SampleRateConverter::new(input.into_iter(), nz!(12000), nz!(2400), nz!(1));
383 let size_estimation = output.len();
384 let output = output.collect::<Vec<_>>();
385 assert_eq!(output, [0.0, 5.0, 10.0, 15.0]);
386 assert!((size_estimation as f32 / output.len() as f32).abs() < 2.0);
387 }
388}