mod sealed {
pub trait Sealed {}
impl Sealed for f32 {}
impl Sealed for i16 {}
}
pub trait PcmSample: Copy + Default + sealed::Sealed {
const CEILING: f32;
fn to_f32(self) -> f32;
fn from_f32(value: f32) -> Self;
}
impl PcmSample for f32 {
const CEILING: f32 = 1.0;
fn to_f32(self) -> f32 {
self
}
fn from_f32(value: f32) -> Self {
value
}
}
impl PcmSample for i16 {
const CEILING: f32 = i16::MAX as f32;
fn to_f32(self) -> f32 {
f32::from(self)
}
fn from_f32(value: f32) -> Self {
value as i16
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn i16_truncates_toward_zero_and_saturates() {
assert_eq!(i16::from_f32(12.9), 12);
assert_eq!(i16::from_f32(-12.9), -12);
assert_eq!(i16::from_f32(40_000.0), i16::MAX);
assert_eq!(i16::from_f32(-40_000.0), i16::MIN);
assert_eq!((-7i16).to_f32(), -7.0);
}
#[test]
fn f32_passes_through() {
assert_eq!(f32::from_f32(0.25), 0.25);
assert_eq!((-0.5f32).to_f32(), -0.5);
}
}