use crate::Signal;
use dasp_interpolate::Interpolator;
#[derive(Clone)]
pub struct Converter<S, I>
where
S: Signal,
I: Interpolator,
{
source: S,
interpolator: I,
interpolation_value: f64,
source_to_target_ratio: f64,
}
impl<S, I> Converter<S, I>
where
S: Signal,
I: Interpolator,
{
#[inline]
pub fn from_hz_to_hz(source: S, interpolator: I, source_hz: f64, target_hz: f64) -> Self {
Self::scale_playback_hz(source, interpolator, source_hz / target_hz)
}
#[inline]
pub fn scale_playback_hz(source: S, interpolator: I, scale: f64) -> Self {
assert!(
scale > 0.0,
"We can't yield any frames at 0 times a second!"
);
Converter {
source: source,
interpolator: interpolator,
interpolation_value: 0.0,
source_to_target_ratio: scale,
}
}
#[inline]
pub fn scale_sample_hz(source: S, interpolator: I, scale: f64) -> Self {
Self::scale_playback_hz(source, interpolator, 1.0 / scale)
}
#[inline]
pub fn set_hz_to_hz(&mut self, source_hz: f64, target_hz: f64) {
self.set_playback_hz_scale(source_hz / target_hz)
}
#[inline]
pub fn set_playback_hz_scale(&mut self, scale: f64) {
self.source_to_target_ratio = scale;
}
#[inline]
pub fn set_sample_hz_scale(&mut self, scale: f64) {
self.set_playback_hz_scale(1.0 / scale);
}
#[inline]
pub fn source(&self) -> &S {
&self.source
}
#[inline]
pub fn source_mut(&mut self) -> &mut S {
&mut self.source
}
#[inline]
pub fn into_source(self) -> S {
self.source
}
}
impl<S, I> Signal for Converter<S, I>
where
S: Signal,
I: Interpolator<Frame = S::Frame>,
{
type Frame = S::Frame;
fn next(&mut self) -> Self::Frame {
let Converter {
ref mut source,
ref mut interpolator,
ref mut interpolation_value,
source_to_target_ratio,
} = *self;
while *interpolation_value >= 1.0 {
interpolator.next_source_frame(source.next());
*interpolation_value -= 1.0;
}
let out = interpolator.interpolate(*interpolation_value);
*interpolation_value += source_to_target_ratio;
out
}
fn is_exhausted(&self) -> bool {
self.source.is_exhausted() && self.interpolation_value >= 1.0
}
}