geng_rodio/source/
speed.rs

1use std::time::Duration;
2
3use crate::{Sample, Source};
4
5/// Internal function that builds a `Speed` object.
6pub fn speed<I>(input: I, factor: f32) -> Speed<I> {
7    Speed { input, factor }
8}
9
10/// Filter that modifies each sample by a given value.
11#[derive(Clone, Debug)]
12pub struct Speed<I> {
13    input: I,
14    factor: f32,
15}
16
17impl<I> Speed<I>
18where
19    I: Source,
20    I::Item: Sample,
21{
22    /// Modifies the speed factor.
23    #[inline]
24    pub fn set_factor(&mut self, factor: f32) {
25        self.factor = factor;
26    }
27
28    /// Returns a reference to the inner source.
29    #[inline]
30    pub fn inner(&self) -> &I {
31        &self.input
32    }
33
34    /// Returns a mutable reference to the inner source.
35    #[inline]
36    pub fn inner_mut(&mut self) -> &mut I {
37        &mut self.input
38    }
39
40    /// Returns the inner source.
41    #[inline]
42    pub fn into_inner(self) -> I {
43        self.input
44    }
45}
46
47impl<I> Iterator for Speed<I>
48where
49    I: Source,
50    I::Item: Sample,
51{
52    type Item = I::Item;
53
54    #[inline]
55    fn next(&mut self) -> Option<I::Item> {
56        self.input.next()
57    }
58
59    #[inline]
60    fn size_hint(&self) -> (usize, Option<usize>) {
61        self.input.size_hint()
62    }
63}
64
65impl<I> ExactSizeIterator for Speed<I>
66where
67    I: Source + ExactSizeIterator,
68    I::Item: Sample,
69{
70}
71
72impl<I> Source for Speed<I>
73where
74    I: Source,
75    I::Item: Sample,
76{
77    #[inline]
78    fn current_frame_len(&self) -> Option<usize> {
79        self.input.current_frame_len()
80    }
81
82    #[inline]
83    fn channels(&self) -> u16 {
84        self.input.channels()
85    }
86
87    #[inline]
88    fn sample_rate(&self) -> u32 {
89        (self.input.sample_rate() as f32 * self.factor) as u32
90    }
91
92    #[inline]
93    fn total_duration(&self) -> Option<Duration> {
94        // TODO: the crappy API of duration makes this code difficult to write
95        if let Some(duration) = self.input.total_duration() {
96            let as_ns = duration.as_secs() * 1000000000 + duration.subsec_nanos() as u64;
97            let new_val = (as_ns as f32 / self.factor) as u64;
98            Some(Duration::new(
99                new_val / 1000000000,
100                (new_val % 1000000000) as u32,
101            ))
102        } else {
103            None
104        }
105    }
106}