use cpal::Sample as CpalSample;
pub trait SampleTransform:CpalSample{
fn into_f32(self)->f32;
fn to_u16(self,volume:f32)->u16;
fn to_i16(self,volume:f32)->i16;
fn to_f32(self,volume:f32)->f32;
fn from<S:SampleTransform>(sample:S,volume:f32)->Self;
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 SampleTransform for i16{
fn into_f32(self)->f32{
if self<0{
self as f32 / -(std::i16::MIN as f32)
}
else{
self as f32 / std::i16::MAX as f32
}
}
fn to_u16(self,volume:f32)->u16{
let s=(self as f32*volume) as i16;
if s < 0 {
(s - ::std::i16::MIN) as u16
} else {
(s as u16) + 32768
}
}
fn to_i16(self,volume:f32)->i16{
(self as f32 * volume) as i16
}
fn to_f32(self,volume:f32)->f32{
if self < 0 {
(self as f32)*volume / -(::std::i16::MIN as f32)
} else {
(self as f32)*volume / ::std::i16::MAX as f32
}
}
fn from<S:SampleTransform>(sample:S,volume:f32)->Self{
sample.to_i16(volume)
}
#[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 SampleTransform for u16{
fn into_f32(self)->f32{
if self >= 32768 {
(self - 32768) as f32 / std::i16::MAX as f32
}
else{
self as f32 - 32768f32 / -(std::i16::MIN as f32)
}
}
fn to_u16(self,volume:f32)->u16{
self
}
fn to_i16(self,volume:f32)->i16{
if self >= 32768 {
(self - 32768) as i16
} else {
(self as i16) - 32767 - 1
}
}
fn to_f32(self,volume:f32)->f32{
if self >= 32768 {
(self - 32768) as f32/ 32768f32
} else {
((self as i16) - 32767 - 1) as f32/ (32768f32)
}
}
fn from<S:SampleTransform>(sample:S,volume:f32)->Self{
sample.to_u16(volume)
}
#[inline]
fn lerp(first: u16, second: u16, numerator: u32, denominator: u32) -> u16 {
(first as u32 + (second as u32 - first as u32) * numerator / denominator) as u16
}
#[inline]
fn amplify(self, value: f32) -> u16 {
let s=CpalSample::to_i16(&self).amplify(value);
CpalSample::to_u16(&s)
}
#[inline]
fn saturating_add(self, other: u16) -> u16 {
self.saturating_add(other)
}
#[inline]
fn zero_value() -> u16 {
32768
}
}
impl SampleTransform for f32{
fn into_f32(self)->f32{
self
}
fn to_u16(self,volume:f32)->u16{
let s=(self as f32*volume) as i16;
if s < 0 {
(s - ::std::i16::MIN) as u16
} else {
(s as u16) + 32768
}
}
fn to_i16(self,volume:f32)->i16{
(self as f32 * volume) as i16
}
fn to_f32(self,volume:f32)->f32{
self*volume
}
fn from<S:SampleTransform>(sample:S,volume:f32)->Self{
sample.to_f32(volume)
}
#[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
}
}