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