use cpal::{FromSample, Sample as CpalSample};
use std::marker::PhantomData;
#[derive(Clone, Debug)]
pub struct DataConverter<I, O> {
input: I,
marker: PhantomData<O>,
}
impl<I, O> DataConverter<I, O> {
#[inline]
pub fn new(input: I) -> DataConverter<I, O> {
DataConverter {
input,
marker: PhantomData,
}
}
#[inline]
pub fn into_inner(self) -> I {
self.input
}
}
impl<I, O> Iterator for DataConverter<I, O>
where
I: Iterator,
I::Item: Sample,
O: FromSample<I::Item> + Sample,
{
type Item = O;
#[inline]
fn next(&mut self) -> Option<O> {
self.input.next().map(|s| CpalSample::from_sample(s))
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
self.input.size_hint()
}
}
impl<I, O> ExactSizeIterator for DataConverter<I, O>
where
I: ExactSizeIterator,
I::Item: Sample,
O: FromSample<I::Item> + Sample,
{
}
pub trait Sample: CpalSample {
fn lerp(first: Self, second: Self, numerator: u32, denominator: u32) -> Self;
fn amplify(self, value: f32) -> Self;
fn saturating_add(self, other: Self) -> Self;
fn zero_value() -> Self;
}
impl Sample for u16 {
#[inline]
fn lerp(first: u16, second: u16, numerator: u32, denominator: u32) -> u16 {
let a = first as i32;
let b = second as i32;
let n = numerator as i32;
let d = denominator as i32;
(a + (b - a) * n / d) as u16
}
#[inline]
fn amplify(self, value: f32) -> u16 {
((self as f32) * value) as u16
}
#[inline]
fn saturating_add(self, other: u16) -> u16 {
self.saturating_add(other)
}
#[inline]
fn zero_value() -> u16 {
32768
}
}
impl Sample for i16 {
#[inline]
fn lerp(first: i16, second: i16, numerator: u32, denominator: u32) -> i16 {
(first as i32 + (second as i32 - first as i32) * numerator as i32 / denominator as i32)
as i16
}
#[inline]
fn amplify(self, value: f32) -> i16 {
((self as f32) * value) as i16
}
#[inline]
fn saturating_add(self, other: i16) -> i16 {
self.saturating_add(other)
}
#[inline]
fn zero_value() -> i16 {
0
}
}
impl Sample for f32 {
#[inline]
fn lerp(first: f32, second: f32, numerator: u32, denominator: u32) -> f32 {
first + (second - first) * numerator as f32 / denominator as f32
}
#[inline]
fn amplify(self, value: f32) -> f32 {
self * value
}
#[inline]
fn saturating_add(self, other: f32) -> f32 {
self + other
}
#[inline]
fn zero_value() -> f32 {
0.0
}
}