dasp_signal/
interpolate.rs

1//! The [**Converter**](./struct.Converter.html) type for interpolating the rate of a signal.
2
3use crate::Signal;
4use dasp_interpolate::Interpolator;
5
6/// A signal type that converts the rate at which frames are yielded from some source signal to
7/// some target rate.
8///
9/// Other names for `sample::interpolate::Converter` might include:
10///
11/// - Sample rate converter.
12/// - {Up/Down}sampler.
13/// - Sample interpolater.
14/// - Sample decimator.
15#[derive(Clone)]
16pub struct Converter<S, I>
17where
18    S: Signal,
19    I: Interpolator,
20{
21    source: S,
22    interpolator: I,
23    interpolation_value: f64,
24    source_to_target_ratio: f64,
25}
26
27impl<S, I> Converter<S, I>
28where
29    S: Signal,
30    I: Interpolator,
31{
32    /// Construct a new `Converter` from the source frames and the source and target sample rates
33    /// (in Hz).
34    #[inline]
35    pub fn from_hz_to_hz(source: S, interpolator: I, source_hz: f64, target_hz: f64) -> Self {
36        Self::scale_playback_hz(source, interpolator, source_hz / target_hz)
37    }
38
39    /// Construct a new `Converter` from the source frames and the amount by which the current
40    /// ***playback*** **rate** (not sample rate) should be multiplied to reach the new playback
41    /// rate.
42    ///
43    /// For example, if our `source_frames` is a sine wave oscillating at a frequency of 2hz and
44    /// we wanted to convert it to a frequency of 3hz, the given `scale` should be `1.5`.
45    #[inline]
46    pub fn scale_playback_hz(source: S, interpolator: I, scale: f64) -> Self {
47        assert!(
48            scale > 0.0,
49            "We can't yield any frames at 0 times a second!"
50        );
51        Converter {
52            source: source,
53            interpolator: interpolator,
54            interpolation_value: 0.0,
55            source_to_target_ratio: scale,
56        }
57    }
58
59    /// Construct a new `Converter` from the source frames and the amount by which the current
60    /// ***sample*** **rate** (not playback rate) should be multiplied to reach the new sample
61    /// rate.
62    ///
63    /// If our `source_frames` are being sampled at a rate of 44_100hz and we want to
64    /// convert to a sample rate of 96_000hz, the given `scale` should be `96_000.0 / 44_100.0`.
65    ///
66    /// This is the same as calling `Converter::scale_playback_hz(source_frames, 1.0 / scale)`.
67    #[inline]
68    pub fn scale_sample_hz(source: S, interpolator: I, scale: f64) -> Self {
69        Self::scale_playback_hz(source, interpolator, 1.0 / scale)
70    }
71
72    /// Update the `source_to_target_ratio` internally given the source and target hz.
73    ///
74    /// This method might be useful for changing the sample rate during playback.
75    #[inline]
76    pub fn set_hz_to_hz(&mut self, source_hz: f64, target_hz: f64) {
77        self.set_playback_hz_scale(source_hz / target_hz)
78    }
79
80    /// Update the `source_to_target_ratio` internally given a new **playback rate** multiplier.
81    ///
82    /// This method is useful for dynamically changing rates.
83    #[inline]
84    pub fn set_playback_hz_scale(&mut self, scale: f64) {
85        self.source_to_target_ratio = scale;
86    }
87
88    /// Update the `source_to_target_ratio` internally given a new **sample rate** multiplier.
89    ///
90    /// This method is useful for dynamically changing rates.
91    #[inline]
92    pub fn set_sample_hz_scale(&mut self, scale: f64) {
93        self.set_playback_hz_scale(1.0 / scale);
94    }
95
96    /// Borrow the `source_frames` Interpolator from the `Converter`.
97    #[inline]
98    pub fn source(&self) -> &S {
99        &self.source
100    }
101
102    /// Mutably borrow the `source_frames` Iterator from the `Converter`.
103    #[inline]
104    pub fn source_mut(&mut self) -> &mut S {
105        &mut self.source
106    }
107
108    /// Drop `self` and return the internal `source_frames` Iterator.
109    #[inline]
110    pub fn into_source(self) -> S {
111        self.source
112    }
113}
114
115impl<S, I> Signal for Converter<S, I>
116where
117    S: Signal,
118    I: Interpolator<Frame = S::Frame>,
119{
120    type Frame = S::Frame;
121
122    fn next(&mut self) -> Self::Frame {
123        let Converter {
124            ref mut source,
125            ref mut interpolator,
126            ref mut interpolation_value,
127            source_to_target_ratio,
128        } = *self;
129
130        // Advance frames
131        while *interpolation_value >= 1.0 {
132            interpolator.next_source_frame(source.next());
133            *interpolation_value -= 1.0;
134        }
135
136        let out = interpolator.interpolate(*interpolation_value);
137        *interpolation_value += source_to_target_ratio;
138        out
139    }
140
141    fn is_exhausted(&self) -> bool {
142        self.source.is_exhausted() && self.interpolation_value >= 1.0
143    }
144}