use crate::sample::{i24, u24, Sample};
pub mod dither {
use super::FromSample;
use crate::sample::Sample;
use crate::sample::{i24, u24};
use std::marker::PhantomData;
mod prng {
#[inline]
fn split_mix_64(x: &mut u64) -> u64 {
*x = x.wrapping_add(0x9e37_79b9_7f4a_7c15);
let mut z = *x;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
pub struct Xoshiro128pp {
s: [u32; 4],
}
impl Xoshiro128pp {
pub fn new(mut seed: u64) -> Self {
let a = split_mix_64(&mut seed);
let b = split_mix_64(&mut seed);
Xoshiro128pp {
s: [
(a & 0xffff_ffff) as u32,
(a >> 32) as u32,
(b & 0xffff_ffff) as u32,
(b >> 32) as u32,
],
}
}
#[inline(always)]
fn rotl(x: u32, k: u32) -> u32 {
(x << k) | (x >> (32 - k))
}
#[inline]
pub fn next(&mut self) -> u32 {
let x = self.s[0].wrapping_add(self.s[3]);
let result = Xoshiro128pp::rotl(x, 7).wrapping_add(self.s[0]);
let t = self.s[1] << 9;
self.s[2] ^= self.s[0];
self.s[3] ^= self.s[1];
self.s[1] ^= self.s[2];
self.s[0] ^= self.s[3];
self.s[2] ^= t;
self.s[3] = Xoshiro128pp::rotl(self.s[3], 11);
result
}
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct RandomNoise(pub i32);
impl RandomNoise {
pub fn from(random: i32, n_bits: u32) -> Self {
RandomNoise(random >> (32 - n_bits))
}
}
pub trait AddNoise<S: Sample> {
fn add_noise(self, sample: S) -> S;
}
macro_rules! add_noise_impl {
($sample_type:ty, $self:ident, $sample:ident, $conv:expr) => (
impl AddNoise<$sample_type> for RandomNoise {
#[inline]
fn add_noise($self, $sample: $sample_type) -> $sample_type { $conv }
}
)
}
add_noise_impl!(i8, self, s, {
i8::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(u8, self, s, {
u8::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(i16, self, s, {
i16::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(u16, self, s, {
u16::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(i24, self, s, {
i24::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(u24, self, s, {
u24::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
});
add_noise_impl!(i32, self, s, {
i32::from_sample(f64::from_sample(s) + f64::from_sample(self.0))
});
add_noise_impl!(u32, self, s, {
u32::from_sample(f64::from_sample(s) + f64::from_sample(self.0))
});
add_noise_impl!(f32, self, s, s + f32::from_sample(self.0));
add_noise_impl!(f64, self, s, s + f64::from_sample(self.0));
pub trait Dither<F: Sample, T: Sample> {
fn dither(&mut self, sample: F) -> F;
}
pub struct Identity<F: Sample, T: Sample> {
from_type: PhantomData<F>,
to_type: PhantomData<T>,
}
impl<F: Sample, T: Sample> Identity<F, T> {
pub fn new() -> Self {
Identity { from_type: PhantomData, to_type: PhantomData }
}
}
impl<F: Sample, T: Sample> Dither<F, T> for Identity<F, T> {
fn dither(&mut self, sample: F) -> F {
sample
}
}
impl<F: Sample, T: Sample> Default for Identity<F, T> {
fn default() -> Self {
Self::new()
}
}
pub struct Rectangular<F: Sample, T: Sample> {
prng: prng::Xoshiro128pp,
from_type: PhantomData<F>,
to_type: PhantomData<T>,
}
impl<F: Sample, T: Sample> Rectangular<F, T> {
pub fn new() -> Self {
Rectangular {
prng: prng::Xoshiro128pp::new(0xb2c1_01f4_425b_987e),
from_type: PhantomData,
to_type: PhantomData,
}
}
}
impl<F: Sample, T: Sample> Dither<F, T> for Rectangular<F, T>
where
RandomNoise: AddNoise<F>,
{
fn dither(&mut self, sample: F) -> F {
debug_assert!(F::EFF_BITS > T::EFF_BITS);
let dither_bits = 32 - T::EFF_BITS;
let noise = RandomNoise::from(self.prng.next() as i32, dither_bits);
noise.add_noise(sample)
}
}
impl<F: Sample, T: Sample> Default for Rectangular<F, T> {
fn default() -> Self {
Self::new()
}
}
pub struct Triangular<F: Sample, T: Sample> {
prng: prng::Xoshiro128pp,
from_type: PhantomData<F>,
to_type: PhantomData<T>,
}
impl<F: Sample, T: Sample> Triangular<F, T> {
pub fn new() -> Self {
Triangular {
prng: prng::Xoshiro128pp::new(0xb2c1_01f4_425b_987e),
from_type: PhantomData,
to_type: PhantomData,
}
}
}
impl<F: Sample, T: Sample> Dither<F, T> for Triangular<F, T>
where
RandomNoise: AddNoise<F>,
{
fn dither(&mut self, sample: F) -> F {
debug_assert!(F::EFF_BITS > T::EFF_BITS);
let dither_bits = 32 - T::EFF_BITS;
let tpdf = (self.prng.next() as i32 >> 1) + (self.prng.next() as i32 >> 1);
let noise = RandomNoise::from(tpdf, dither_bits);
noise.add_noise(sample)
}
}
impl<F: Sample, T: Sample> Default for Triangular<F, T> {
fn default() -> Self {
Self::new()
}
}
pub enum DitherType {
Identity,
Rectangular,
Triangular,
}
pub trait MaybeDither<T: Sample>: Sample {
const DITHERABLE: bool;
fn maybe_dither<D: Dither<Self, T>>(self, dither: &mut D) -> Self;
}
macro_rules! dither_never {
($to:ty, $from:ty) => {
impl MaybeDither<$to> for $from {
const DITHERABLE: bool = false;
#[inline(always)]
fn maybe_dither<D: Dither<$from, $to>>(self, _: &mut D) -> Self {
self
}
}
};
}
macro_rules! dither_maybe {
($to:ty, $from:ty) => {
impl MaybeDither<$to> for $from {
const DITHERABLE: bool = true;
#[inline(always)]
fn maybe_dither<D: Dither<$from, $to>>(self, dither: &mut D) -> Self {
dither.dither(self)
}
}
};
}
dither_never!(u8, u8);
dither_maybe!(u8, u16);
dither_maybe!(u8, u24);
dither_maybe!(u8, u32);
dither_never!(u8, i8);
dither_maybe!(u8, i16);
dither_maybe!(u8, i24);
dither_maybe!(u8, i32);
dither_never!(u8, f32);
dither_never!(u8, f64);
dither_never!(u16, u8);
dither_never!(u16, u16);
dither_maybe!(u16, u24);
dither_maybe!(u16, u32);
dither_never!(u16, i8);
dither_never!(u16, i16);
dither_maybe!(u16, i24);
dither_maybe!(u16, i32);
dither_never!(u16, f32);
dither_never!(u16, f64);
dither_never!(u24, u8);
dither_never!(u24, u16);
dither_never!(u24, u24);
dither_maybe!(u24, u32);
dither_never!(u24, i8);
dither_never!(u24, i16);
dither_never!(u24, i24);
dither_maybe!(u24, i32);
dither_never!(u24, f32);
dither_never!(u24, f64);
dither_never!(u32, u8);
dither_never!(u32, u16);
dither_never!(u32, u24);
dither_never!(u32, u32);
dither_never!(u32, i8);
dither_never!(u32, i16);
dither_never!(u32, i24);
dither_never!(u32, i32);
dither_never!(u32, f32);
dither_never!(u32, f64);
dither_never!(i8, u8);
dither_maybe!(i8, u16);
dither_maybe!(i8, u24);
dither_maybe!(i8, u32);
dither_never!(i8, i8);
dither_maybe!(i8, i16);
dither_maybe!(i8, i24);
dither_maybe!(i8, i32);
dither_never!(i8, f32);
dither_never!(i8, f64);
dither_never!(i16, u8);
dither_never!(i16, u16);
dither_maybe!(i16, u24);
dither_maybe!(i16, u32);
dither_never!(i16, i8);
dither_never!(i16, i16);
dither_maybe!(i16, i24);
dither_maybe!(i16, i32);
dither_never!(i16, f32);
dither_never!(i16, f64);
dither_never!(i24, u8);
dither_never!(i24, u16);
dither_never!(i24, u24);
dither_maybe!(i24, u32);
dither_never!(i24, i8);
dither_never!(i24, i16);
dither_never!(i24, i24);
dither_maybe!(i24, i32);
dither_never!(i24, f32);
dither_never!(i24, f64);
dither_never!(i32, u8);
dither_never!(i32, u16);
dither_never!(i32, u24);
dither_never!(i32, u32);
dither_never!(i32, i8);
dither_never!(i32, i16);
dither_never!(i32, i24);
dither_never!(i32, i32);
dither_never!(i32, f32);
dither_never!(i32, f64);
dither_never!(f32, u8);
dither_never!(f32, u16);
dither_never!(f32, u24);
dither_never!(f32, u32);
dither_never!(f32, i8);
dither_never!(f32, i16);
dither_never!(f32, i24);
dither_never!(f32, i32);
dither_never!(f32, f32);
dither_never!(f32, f64);
dither_never!(f64, u8);
dither_never!(f64, u16);
dither_never!(f64, u24);
dither_never!(f64, u32);
dither_never!(f64, i8);
dither_never!(f64, i16);
dither_never!(f64, i24);
dither_never!(f64, i32);
dither_never!(f64, f32);
dither_never!(f64, f64);
}
pub trait FromSample<F> {
fn from_sample(val: F) -> Self;
}
macro_rules! impl_convert {
($from:ty, $to:ty, $sample:ident, $func:expr) => {
impl FromSample<$from> for $to {
#[inline(always)]
fn from_sample($sample: $from) -> Self {
$func
}
}
};
}
#[inline(always)]
fn i8_to_u8(s: i8) -> u8 {
(s as u8).wrapping_add(0x80)
}
impl_convert!(i8, u8, s, i8_to_u8(s)); impl_convert!(i8, u16, s, (i8_to_u8(s) as u16) << 8); impl_convert!(i8, u24, s, u24::from((i8_to_u8(s) as u32) << 16)); impl_convert!(i8, u32, s, (i8_to_u8(s) as u32) << 24); impl_convert!(i8, i8, s, s); impl_convert!(i8, i16, s, (s as i16) << 8); impl_convert!(i8, i24, s, i24::from((s as i32) << 16)); impl_convert!(i8, i32, s, (s as i32) << 24); impl_convert!(i8, f32, s, s as f32 / 128.0); impl_convert!(i8, f64, s, s as f64 / 128.0); #[inline(always)]
fn i16_to_u16(s: i16) -> u16 {
(s as u16).wrapping_add(0x8000)
}
impl_convert!(i16, u8, s, (i16_to_u16(s) >> 8) as u8); impl_convert!(i16, u16, s, i16_to_u16(s)); impl_convert!(i16, u24, s, u24::from((i16_to_u16(s) as u32) << 8)); impl_convert!(i16, u32, s, (i16_to_u16(s) as u32) << 16); impl_convert!(i16, i8, s, (s >> 8) as i8); impl_convert!(i16, i16, s, s); impl_convert!(i16, i24, s, i24::from((s as i32) << 8)); impl_convert!(i16, i32, s, (s as i32) << 16); impl_convert!(i16, f32, s, s as f32 / 32_768.0); impl_convert!(i16, f64, s, s as f64 / 32_768.0); #[inline(always)]
fn i24_to_u32(s: i24) -> u32 {
((s.clamped().inner() << 8) as u32).wrapping_add(0x8000_0000)
}
impl_convert!(i24, u8, s, (i24_to_u32(s) >> 24) as u8); impl_convert!(i24, u16, s, (i24_to_u32(s) >> 16) as u16); impl_convert!(i24, u24, s, u24::from(i24_to_u32(s) >> 8)); impl_convert!(i24, u32, s, i24_to_u32(s)); impl_convert!(i24, i8, s, (s.clamped().inner() >> 16) as i8); impl_convert!(i24, i16, s, (s.clamped().inner() >> 8) as i16); impl_convert!(i24, i24, s, s); impl_convert!(i24, i32, s, (s.clamped().inner()) << 8); impl_convert!(i24, f32, s, s.clamped().inner() as f32 / 8_388_608.0); impl_convert!(i24, f64, s, s.clamped().inner() as f64 / 8_388_608.0); #[inline(always)]
fn i32_to_u32(s: i32) -> u32 {
(s as u32).wrapping_add(0x8000_0000)
}
impl_convert!(i32, u8, s, (i32_to_u32(s) >> 24) as u8); impl_convert!(i32, u16, s, (i32_to_u32(s) >> 16) as u16); impl_convert!(i32, u24, s, u24::from(i32_to_u32(s) >> 8)); impl_convert!(i32, u32, s, i32_to_u32(s)); impl_convert!(i32, i8, s, (s >> 24) as i8); impl_convert!(i32, i16, s, (s >> 16) as i16); impl_convert!(i32, i24, s, i24::from(s >> 8)); impl_convert!(i32, i32, s, s); impl_convert!(i32, f32, s, (s as f64 / 2_147_483_648.0) as f32); impl_convert!(i32, f64, s, s as f64 / 2_147_483_648.0); impl_convert!(u8, u8, s, s); impl_convert!(u8, u16, s, (s as u16) << 8); impl_convert!(u8, u24, s, u24::from((s as u32) << 16)); impl_convert!(u8, u32, s, (s as u32) << 24); impl_convert!(u8, i8, s, s.wrapping_sub(0x80) as i8); impl_convert!(u8, i16, s, ((s.wrapping_sub(0x80) as i8) as i16) << 8); impl_convert!(u8, i24, s, i24::from(((s.wrapping_sub(0x80) as i8) as i32) << 16)); impl_convert!(u8, i32, s, ((s.wrapping_sub(0x80) as i8) as i32) << 24); impl_convert!(u8, f32, s, ((s as f32) / 128.0) - 1.0); impl_convert!(u8, f64, s, ((s as f64) / 128.0) - 1.0); impl_convert!(u16, u8, s, (s >> 8) as u8); impl_convert!(u16, u16, s, s); impl_convert!(u16, u24, s, u24::from((s as u32) << 8)); impl_convert!(u16, u32, s, (s as u32) << 16); impl_convert!(u16, i8, s, (s.wrapping_sub(0x8000) >> 8) as i8); impl_convert!(u16, i16, s, s.wrapping_sub(0x8000) as i16); impl_convert!(u16, i24, s, i24::from(((s.wrapping_sub(0x8000) as i16) as i32) << 8)); impl_convert!(u16, i32, s, ((s.wrapping_sub(0x8000) as i16) as i32) << 16); impl_convert!(u16, f32, s, ((s as f32) / 32_768.0) - 1.0); impl_convert!(u16, f64, s, ((s as f64) / 32_768.0) - 1.0); impl_convert!(u24, u8, s, (s.clamped().inner() >> 16) as u8); impl_convert!(u24, u16, s, (s.clamped().inner() >> 8) as u16); impl_convert!(u24, u24, s, s); impl_convert!(u24, u32, s, s.clamped().inner() << 8); impl_convert!(u24, i8, s, (s.clamped().inner().wrapping_sub(0x80_0000) >> 16) as i8); impl_convert!(u24, i16, s, (s.clamped().inner().wrapping_sub(0x80_0000) >> 8) as i16); impl_convert!(u24, i24, s, i24::from(s.clamped().inner().wrapping_sub(0x80_0000) as i32)); impl_convert!(u24, i32, s, (s.clamped().inner().wrapping_sub(0x80_0000) << 8) as i32); impl_convert!(u24, f32, s, ((s.clamped().inner() as f32) / 8_388_608.0) - 1.0); impl_convert!(u24, f64, s, ((s.clamped().inner() as f64) / 8_388_608.0) - 1.0); impl_convert!(u32, u8, s, (s >> 24) as u8); impl_convert!(u32, u16, s, (s >> 16) as u16); impl_convert!(u32, u24, s, u24::from(s >> 8)); impl_convert!(u32, u32, s, s); impl_convert!(u32, i8, s, (s.wrapping_sub(0x8000_0000) >> 24) as i8); impl_convert!(u32, i16, s, (s.wrapping_sub(0x8000_0000) >> 16) as i16); impl_convert!(u32, i24, s, i24::from((s.wrapping_sub(0x8000_0000) as i32) >> 8)); impl_convert!(u32, i32, s, s.wrapping_sub(0x8000_0000) as i32); impl_convert!(u32, f32, s, (((s as f64) / 2_147_483_648.0) - 1.0) as f32); impl_convert!(u32, f64, s, ((s as f64) / 2_147_483_648.0) - 1.0); impl_convert!(f32, u8, s, ((s.clamped() + 1.0) * 128.0) as u8); impl_convert!(f32, u16, s, ((s.clamped() + 1.0) * 32_768.0) as u16); impl_convert!(f32, u24, s, u24::from(((s.clamped() + 1.0) * 8_388_608.0) as u32)); impl_convert!(f32, u32, s, ((s.clamped() + 1.0) as f64 * 2_147_483_648.0) as u32); impl_convert!(f32, i8, s, (s.clamped() * 128.0) as i8); impl_convert!(f32, i16, s, (s.clamped() * 32_768.0) as i16); impl_convert!(f32, i24, s, i24::from((s.clamped() * 8_388_608.0) as i32)); impl_convert!(f32, i32, s, (s.clamped() as f64 * 2_147_483_648.0) as i32); impl_convert!(f32, f32, s, s); impl_convert!(f32, f64, s, s as f64); impl_convert!(f64, u8, s, ((s.clamped() + 1.0) * 128.0) as u8); impl_convert!(f64, u16, s, ((s.clamped() + 1.0) * 32_768.0) as u16); impl_convert!(f64, u24, s, u24::from(((s.clamped() + 1.0) * 8_388_608.0) as u32)); impl_convert!(f64, u32, s, ((s.clamped() + 1.0) * 2_147_483_648.0) as u32); impl_convert!(f64, i8, s, (s.clamped() * 128.0) as i8); impl_convert!(f64, i16, s, (s.clamped() * 32_768.0) as i16); impl_convert!(f64, i24, s, i24::from((s.clamped() * 8_388_608.0) as i32)); impl_convert!(f64, i32, s, (s.clamped() * 2_147_483_648.0) as i32); impl_convert!(f64, f32, s, s as f32); impl_convert!(f64, f64, s, s); pub trait IntoSample<T> {
fn into_sample(self) -> T;
}
impl<F, T: FromSample<F>> IntoSample<T> for F {
#[inline]
fn into_sample(self) -> T {
T::from_sample(self)
}
}
pub trait ReversibleSample<S>: Sample + FromSample<S> + IntoSample<S> {}
impl<S, T> ReversibleSample<S> for T where T: Sample + FromSample<S> + IntoSample<S> {}
pub trait ConvertibleSample:
Sample
+ FromSample<i8>
+ FromSample<u8>
+ FromSample<i16>
+ FromSample<u16>
+ FromSample<i24>
+ FromSample<u24>
+ FromSample<i32>
+ FromSample<u32>
+ FromSample<f32>
+ FromSample<f64>
{
}
impl<S> ConvertibleSample for S where
S: Sample
+ FromSample<i8>
+ FromSample<u8>
+ FromSample<i16>
+ FromSample<u16>
+ FromSample<i24>
+ FromSample<u24>
+ FromSample<i32>
+ FromSample<u32>
+ FromSample<f32>
+ FromSample<f64>
{
}
#[cfg(test)]
mod tests {
use super::FromSample;
use crate::sample::{i24, u24, Sample};
use std::{i16, i32, i8, u16, u32, u8};
#[test]
fn verify_u8_from_sample() {
assert_eq!(u8::from_sample(u8::MAX), u8::MAX);
assert_eq!(u8::from_sample(u8::MID), u8::MID);
assert_eq!(u8::from_sample(u8::MIN), u8::MIN);
assert_eq!(u8::from_sample(u16::MAX), u8::MAX);
assert_eq!(u8::from_sample(u16::MID), u8::MID);
assert_eq!(u8::from_sample(u16::MIN), u8::MIN);
assert_eq!(u8::from_sample(u24::MAX), u8::MAX);
assert_eq!(u8::from_sample(u24::MID), u8::MID);
assert_eq!(u8::from_sample(u24::MIN), u8::MIN);
assert_eq!(u8::from_sample(u32::MAX), u8::MAX);
assert_eq!(u8::from_sample(u32::MID), u8::MID);
assert_eq!(u8::from_sample(u32::MIN), u8::MIN);
assert_eq!(u8::from_sample(i8::MAX), u8::MAX);
assert_eq!(u8::from_sample(i8::MID), u8::MID);
assert_eq!(u8::from_sample(i8::MIN), u8::MIN);
assert_eq!(u8::from_sample(i16::MAX), u8::MAX);
assert_eq!(u8::from_sample(i16::MID), u8::MID);
assert_eq!(u8::from_sample(i16::MIN), u8::MIN);
assert_eq!(u8::from_sample(i24::MAX), u8::MAX);
assert_eq!(u8::from_sample(i24::MID), u8::MID);
assert_eq!(u8::from_sample(i24::MIN), u8::MIN);
assert_eq!(u8::from_sample(i32::MAX), u8::MAX);
assert_eq!(u8::from_sample(i32::MID), u8::MID);
assert_eq!(u8::from_sample(i32::MIN), u8::MIN);
assert_eq!(u8::from_sample(1.0f32), u8::MAX);
assert_eq!(u8::from_sample(0f32), u8::MID);
assert_eq!(u8::from_sample(-1.0f32), u8::MIN);
assert_eq!(u8::from_sample(1.0f64), u8::MAX);
assert_eq!(u8::from_sample(0f64), u8::MID);
assert_eq!(u8::from_sample(-1.0f64), u8::MIN);
}
#[test]
fn verify_u16_from_sample() {
assert_eq!(u16::from_sample(u8::MAX), u16::MAX - 255);
assert_eq!(u16::from_sample(u8::MID), u16::MID);
assert_eq!(u16::from_sample(u8::MIN), u16::MIN);
assert_eq!(u16::from_sample(u16::MAX), u16::MAX);
assert_eq!(u16::from_sample(u16::MID), u16::MID);
assert_eq!(u16::from_sample(u16::MIN), u16::MIN);
assert_eq!(u16::from_sample(u24::MAX), u16::MAX);
assert_eq!(u16::from_sample(u24::MID), u16::MID);
assert_eq!(u16::from_sample(u24::MIN), u16::MIN);
assert_eq!(u16::from_sample(u32::MAX), u16::MAX);
assert_eq!(u16::from_sample(u32::MID), u16::MID);
assert_eq!(u16::from_sample(u32::MIN), u16::MIN);
assert_eq!(u16::from_sample(i8::MAX), u16::MAX - 255);
assert_eq!(u16::from_sample(i8::MID), u16::MID);
assert_eq!(u16::from_sample(i8::MIN), u16::MIN);
assert_eq!(u16::from_sample(i16::MAX), u16::MAX);
assert_eq!(u16::from_sample(i16::MID), u16::MID);
assert_eq!(u16::from_sample(i16::MIN), u16::MIN);
assert_eq!(u16::from_sample(i24::MAX), u16::MAX);
assert_eq!(u16::from_sample(i24::MID), u16::MID);
assert_eq!(u16::from_sample(i24::MIN), u16::MIN);
assert_eq!(u16::from_sample(i32::MAX), u16::MAX);
assert_eq!(u16::from_sample(i32::MID), u16::MID);
assert_eq!(u16::from_sample(i32::MIN), u16::MIN);
assert_eq!(u16::from_sample(1.0f32), u16::MAX);
assert_eq!(u16::from_sample(0f32), u16::MID);
assert_eq!(u16::from_sample(-1.0f32), u16::MIN);
assert_eq!(u16::from_sample(1.0f64), u16::MAX);
assert_eq!(u16::from_sample(0f64), u16::MID);
assert_eq!(u16::from_sample(-1.0f64), u16::MIN);
}
#[test]
fn verify_u24_from_sample() {
assert_eq!(u24::from_sample(u8::MAX), u24::MAX - u24::from(65_535u32));
assert_eq!(u24::from_sample(u8::MID), u24::MID);
assert_eq!(u24::from_sample(u8::MIN), u24::MIN);
assert_eq!(u24::from_sample(u16::MAX), u24::MAX - u24::from(255u32));
assert_eq!(u24::from_sample(u16::MID), u24::MID);
assert_eq!(u24::from_sample(u16::MIN), u24::MIN);
assert_eq!(u24::from_sample(u24::MAX), u24::MAX);
assert_eq!(u24::from_sample(u24::MID), u24::MID);
assert_eq!(u24::from_sample(u24::MIN), u24::MIN);
assert_eq!(u24::from_sample(u32::MAX), u24::MAX);
assert_eq!(u24::from_sample(u32::MID), u24::MID);
assert_eq!(u24::from_sample(u32::MIN), u24::MIN);
assert_eq!(u24::from_sample(i8::MAX), u24::MAX - u24::from(65_535u32));
assert_eq!(u24::from_sample(i8::MID), u24::MID);
assert_eq!(u24::from_sample(i8::MIN), u24::MIN);
assert_eq!(u24::from_sample(i16::MAX), u24::MAX - u24::from(255u32));
assert_eq!(u24::from_sample(i16::MID), u24::MID);
assert_eq!(u24::from_sample(i16::MIN), u24::MIN);
assert_eq!(u24::from_sample(i24::MAX), u24::MAX);
assert_eq!(u24::from_sample(i24::MID), u24::MID);
assert_eq!(u24::from_sample(i24::MIN), u24::MIN);
assert_eq!(u24::from_sample(i32::MAX), u24::MAX);
assert_eq!(u24::from_sample(i32::MID), u24::MID);
assert_eq!(u24::from_sample(i32::MIN), u24::MIN);
assert_eq!(u24::from_sample(1.0f32), u24::MAX);
assert_eq!(u24::from_sample(0f32), u24::MID);
assert_eq!(u24::from_sample(-1.0f32), u24::MIN);
assert_eq!(u24::from_sample(1.0f64), u24::MAX);
assert_eq!(u24::from_sample(0f64), u24::MID);
assert_eq!(u24::from_sample(-1.0f64), u24::MIN);
}
#[test]
fn verify_u32_from_sample() {
assert_eq!(u32::from_sample(u8::MAX), u32::MAX - 16_777_215);
assert_eq!(u32::from_sample(u8::MID), u32::MID);
assert_eq!(u32::from_sample(u8::MIN), u32::MIN);
assert_eq!(u32::from_sample(u16::MAX), u32::MAX - 65_535);
assert_eq!(u32::from_sample(u16::MID), u32::MID);
assert_eq!(u32::from_sample(u16::MIN), u32::MIN);
assert_eq!(u32::from_sample(u24::MAX), u32::MAX - 255);
assert_eq!(u32::from_sample(u24::MID), u32::MID);
assert_eq!(u32::from_sample(u24::MIN), u32::MIN);
assert_eq!(u32::from_sample(u32::MAX), u32::MAX);
assert_eq!(u32::from_sample(u32::MID), u32::MID);
assert_eq!(u32::from_sample(u32::MIN), u32::MIN);
assert_eq!(u32::from_sample(i8::MAX), u32::MAX - 16_777_215);
assert_eq!(u32::from_sample(i8::MID), u32::MID);
assert_eq!(u32::from_sample(i8::MIN), u32::MIN);
assert_eq!(u32::from_sample(i16::MAX), u32::MAX - 65_535);
assert_eq!(u32::from_sample(i16::MID), u32::MID);
assert_eq!(u32::from_sample(i16::MIN), u32::MIN);
assert_eq!(u32::from_sample(i24::MAX), u32::MAX - 255);
assert_eq!(u32::from_sample(i24::MID), u32::MID);
assert_eq!(u32::from_sample(i24::MIN), u32::MIN);
assert_eq!(u32::from_sample(i32::MAX), u32::MAX);
assert_eq!(u32::from_sample(i32::MID), u32::MID);
assert_eq!(u32::from_sample(i32::MIN), u32::MIN);
assert_eq!(u32::from_sample(1.0f32), u32::MAX);
assert_eq!(u32::from_sample(0f32), u32::MID);
assert_eq!(u32::from_sample(-1.0f32), u32::MIN);
assert_eq!(u32::from_sample(1.0f64), u32::MAX);
assert_eq!(u32::from_sample(0f64), u32::MID);
assert_eq!(u32::from_sample(-1.0f64), u32::MIN);
}
#[test]
fn verify_i8_from_sample() {
assert_eq!(i8::from_sample(u8::MAX), i8::MAX);
assert_eq!(i8::from_sample(u8::MID), i8::MID);
assert_eq!(i8::from_sample(u8::MIN), i8::MIN);
assert_eq!(i8::from_sample(u16::MAX), i8::MAX);
assert_eq!(i8::from_sample(u16::MID), i8::MID);
assert_eq!(i8::from_sample(u16::MIN), i8::MIN);
assert_eq!(i8::from_sample(u24::MAX), i8::MAX);
assert_eq!(i8::from_sample(u24::MID), i8::MID);
assert_eq!(i8::from_sample(u24::MIN), i8::MIN);
assert_eq!(i8::from_sample(u32::MAX), i8::MAX);
assert_eq!(i8::from_sample(u32::MID), i8::MID);
assert_eq!(i8::from_sample(u32::MIN), i8::MIN);
assert_eq!(i8::from_sample(i8::MAX), i8::MAX);
assert_eq!(i8::from_sample(i8::MID), i8::MID);
assert_eq!(i8::from_sample(i8::MIN), i8::MIN);
assert_eq!(i8::from_sample(i16::MAX), i8::MAX);
assert_eq!(i8::from_sample(i16::MID), i8::MID);
assert_eq!(i8::from_sample(i16::MIN), i8::MIN);
assert_eq!(i8::from_sample(i24::MAX), i8::MAX);
assert_eq!(i8::from_sample(i24::MID), i8::MID);
assert_eq!(i8::from_sample(i24::MIN), i8::MIN);
assert_eq!(i8::from_sample(i32::MAX), i8::MAX);
assert_eq!(i8::from_sample(i32::MID), i8::MID);
assert_eq!(i8::from_sample(i32::MIN), i8::MIN);
assert_eq!(i8::from_sample(1.0f32), i8::MAX);
assert_eq!(i8::from_sample(0f32), i8::MID);
assert_eq!(i8::from_sample(-1.0f32), i8::MIN);
assert_eq!(i8::from_sample(1.0f64), i8::MAX);
assert_eq!(i8::from_sample(0f64), i8::MID);
assert_eq!(i8::from_sample(-1.0f64), i8::MIN);
}
#[test]
fn verify_i16_from_sample() {
assert_eq!(i16::from_sample(u8::MAX), i16::MAX - 255);
assert_eq!(i16::from_sample(u8::MID), i16::MID);
assert_eq!(i16::from_sample(u8::MIN), i16::MIN);
assert_eq!(i16::from_sample(u16::MAX), i16::MAX);
assert_eq!(i16::from_sample(u16::MID), i16::MID);
assert_eq!(i16::from_sample(u16::MIN), i16::MIN);
assert_eq!(i16::from_sample(u24::MAX), i16::MAX);
assert_eq!(i16::from_sample(u24::MID), i16::MID);
assert_eq!(i16::from_sample(u24::MIN), i16::MIN);
assert_eq!(i16::from_sample(u32::MAX), i16::MAX);
assert_eq!(i16::from_sample(u32::MID), i16::MID);
assert_eq!(i16::from_sample(u32::MIN), i16::MIN);
assert_eq!(i16::from_sample(i8::MAX), i16::MAX - 255);
assert_eq!(i16::from_sample(i8::MID), i16::MID);
assert_eq!(i16::from_sample(i8::MIN), i16::MIN);
assert_eq!(i16::from_sample(i16::MAX), i16::MAX);
assert_eq!(i16::from_sample(i16::MID), i16::MID);
assert_eq!(i16::from_sample(i16::MIN), i16::MIN);
assert_eq!(i16::from_sample(i24::MAX), i16::MAX);
assert_eq!(i16::from_sample(i24::MID), i16::MID);
assert_eq!(i16::from_sample(i24::MIN), i16::MIN);
assert_eq!(i16::from_sample(i32::MAX), i16::MAX);
assert_eq!(i16::from_sample(i32::MID), i16::MID);
assert_eq!(i16::from_sample(i32::MIN), i16::MIN);
assert_eq!(i16::from_sample(1.0f32), i16::MAX);
assert_eq!(i16::from_sample(0f32), i16::MID);
assert_eq!(i16::from_sample(-1.0f32), i16::MIN);
assert_eq!(i16::from_sample(1.0f64), i16::MAX);
assert_eq!(i16::from_sample(0f64), i16::MID);
assert_eq!(i16::from_sample(-1.0f64), i16::MIN);
}
#[test]
fn verify_i24_from_sample() {
assert_eq!(i24::from_sample(u8::MAX), i24::MAX - i24::from(65_535));
assert_eq!(i24::from_sample(u8::MID), i24::MID);
assert_eq!(i24::from_sample(u8::MIN), i24::MIN);
assert_eq!(i24::from_sample(u16::MAX), i24::MAX - i24::from(255));
assert_eq!(i24::from_sample(u16::MID), i24::MID);
assert_eq!(i24::from_sample(u16::MIN), i24::MIN);
assert_eq!(i24::from_sample(u24::MAX), i24::MAX);
assert_eq!(i24::from_sample(u24::MID), i24::MID);
assert_eq!(i24::from_sample(u24::MIN), i24::MIN);
assert_eq!(i24::from_sample(u32::MAX), i24::MAX);
assert_eq!(i24::from_sample(u32::MID), i24::MID);
assert_eq!(i24::from_sample(u32::MIN), i24::MIN);
assert_eq!(i24::from_sample(i8::MAX), i24::MAX - i24::from(65_535));
assert_eq!(i24::from_sample(i8::MID), i24::MID);
assert_eq!(i24::from_sample(i8::MIN), i24::MIN);
assert_eq!(i24::from_sample(i16::MAX), i24::MAX - i24::from(255));
assert_eq!(i24::from_sample(i16::MID), i24::MID);
assert_eq!(i24::from_sample(i16::MIN), i24::MIN);
assert_eq!(i24::from_sample(i24::MAX), i24::MAX);
assert_eq!(i24::from_sample(i24::MID), i24::MID);
assert_eq!(i24::from_sample(i24::MIN), i24::MIN);
assert_eq!(i24::from_sample(i32::MAX), i24::MAX);
assert_eq!(i24::from_sample(i32::MID), i24::MID);
assert_eq!(i24::from_sample(i32::MIN), i24::MIN);
assert_eq!(i24::from_sample(1.0f32), i24::MAX);
assert_eq!(i24::from_sample(0f32), i24::MID);
assert_eq!(i24::from_sample(-1.0f32), i24::MIN);
assert_eq!(i24::from_sample(1.0f64), i24::MAX);
assert_eq!(i24::from_sample(0f64), i24::MID);
assert_eq!(i24::from_sample(-1.0f64), i24::MIN);
}
#[test]
fn verify_i32_from_sample() {
assert_eq!(i32::from_sample(u8::MAX), i32::MAX - 16_777_215);
assert_eq!(i32::from_sample(u8::MID), i32::MID);
assert_eq!(i32::from_sample(u8::MIN), i32::MIN);
assert_eq!(i32::from_sample(u16::MAX), i32::MAX - 65_535);
assert_eq!(i32::from_sample(u16::MID), i32::MID);
assert_eq!(i32::from_sample(u16::MIN), i32::MIN);
assert_eq!(i32::from_sample(u24::MAX), i32::MAX - 255);
assert_eq!(i32::from_sample(u24::MID), i32::MID);
assert_eq!(i32::from_sample(u24::MIN), i32::MIN);
assert_eq!(i32::from_sample(u32::MAX), i32::MAX);
assert_eq!(i32::from_sample(u32::MID), i32::MID);
assert_eq!(i32::from_sample(u32::MIN), i32::MIN);
assert_eq!(i32::from_sample(i8::MAX), i32::MAX - 16_777_215);
assert_eq!(i32::from_sample(i8::MID), i32::MID);
assert_eq!(i32::from_sample(i8::MIN), i32::MIN);
assert_eq!(i32::from_sample(i16::MAX), i32::MAX - 65_535);
assert_eq!(i32::from_sample(i16::MID), i32::MID);
assert_eq!(i32::from_sample(i16::MIN), i32::MIN);
assert_eq!(i32::from_sample(i24::MAX), i32::MAX - 255);
assert_eq!(i32::from_sample(i24::MID), i32::MID);
assert_eq!(i32::from_sample(i24::MIN), i32::MIN);
assert_eq!(i32::from_sample(i32::MAX), i32::MAX);
assert_eq!(i32::from_sample(i32::MID), i32::MID);
assert_eq!(i32::from_sample(i32::MIN), i32::MIN);
assert_eq!(i32::from_sample(1.0f32), i32::MAX);
assert_eq!(i32::from_sample(0f32), i32::MID);
assert_eq!(i32::from_sample(-1.0f32), i32::MIN);
assert_eq!(i32::from_sample(1.0f64), i32::MAX);
assert_eq!(i32::from_sample(0f64), i32::MID);
assert_eq!(i32::from_sample(-1.0f64), i32::MIN);
}
#[test]
fn verify_f64_from_sample() {
assert_eq!(f64::from_sample(u8::MAX), 127.0 / 128.0);
assert_eq!(f64::from_sample(u8::MID), 0.0);
assert_eq!(f64::from_sample(u8::MIN), -1.0);
assert_eq!(f64::from_sample(u16::MAX), 32_767.0 / 32_768.0);
assert_eq!(f64::from_sample(u16::MID), 0.0);
assert_eq!(f64::from_sample(u16::MIN), -1.0);
assert_eq!(f64::from_sample(u24::MAX), 8_388_607.0 / 8_388_608.0);
assert_eq!(f64::from_sample(u24::MID), 0.0);
assert_eq!(f64::from_sample(u24::MIN), -1.0);
assert_eq!(f64::from_sample(u32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
assert_eq!(f64::from_sample(u32::MID), 0.0);
assert_eq!(f64::from_sample(u32::MIN), -1.0);
assert_eq!(f64::from_sample(i8::MAX), 127.0 / 128.0);
assert_eq!(f64::from_sample(i8::MID), 0.0);
assert_eq!(f64::from_sample(i8::MIN), -1.0);
assert_eq!(f64::from_sample(i16::MAX), 32_767.0 / 32_768.0);
assert_eq!(f64::from_sample(i16::MID), 0.0);
assert_eq!(f64::from_sample(i16::MIN), -1.0);
assert_eq!(f64::from_sample(i24::MAX), 8_388_607.0 / 8_388_608.0);
assert_eq!(f64::from_sample(i24::MID), 0.0);
assert_eq!(f64::from_sample(i24::MIN), -1.0);
assert_eq!(f64::from_sample(i32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
assert_eq!(f64::from_sample(i32::MID), 0.0);
assert_eq!(f64::from_sample(i32::MIN), -1.0);
assert_eq!(f64::from_sample(1.0f32), 1.0);
assert_eq!(f64::from_sample(0f32), 0.0);
assert_eq!(f64::from_sample(-1.0f32), -1.0);
assert_eq!(f64::from_sample(1.0f64), 1.0);
assert_eq!(f64::from_sample(0f64), 0.0);
assert_eq!(f64::from_sample(-1.0f64), -1.0);
}
#[test]
fn verify_f32_from_sample() {
assert_eq!(f32::from_sample(u8::MAX), 127.0 / 128.0);
assert_eq!(f32::from_sample(u8::MID), 0.0);
assert_eq!(f32::from_sample(u8::MIN), -1.0);
assert_eq!(f32::from_sample(u16::MAX), 32_767.0 / 32_768.0);
assert_eq!(f32::from_sample(u16::MID), 0.0);
assert_eq!(f32::from_sample(u16::MIN), -1.0);
assert_eq!(f32::from_sample(u24::MAX), 8_388_607.0 / 8_388_608.0);
assert_eq!(f32::from_sample(u24::MID), 0.0);
assert_eq!(f32::from_sample(u24::MIN), -1.0);
assert_eq!(f32::from_sample(u32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
assert_eq!(f32::from_sample(u32::MID), 0.0);
assert_eq!(f32::from_sample(u32::MIN), -1.0);
assert_eq!(f32::from_sample(i8::MAX), 127.0 / 128.0);
assert_eq!(f32::from_sample(i8::MID), 0.0);
assert_eq!(f32::from_sample(i8::MIN), -1.0);
assert_eq!(f32::from_sample(i16::MAX), 32_767.0 / 32_768.0);
assert_eq!(f32::from_sample(i16::MID), 0.0);
assert_eq!(f32::from_sample(i16::MIN), -1.0);
assert_eq!(f32::from_sample(i24::MAX), 8_388_607.0 / 8_388_608.0);
assert_eq!(f32::from_sample(i24::MID), 0.0);
assert_eq!(f32::from_sample(i24::MIN), -1.0);
assert_eq!(f32::from_sample(i32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
assert_eq!(f32::from_sample(i32::MID), 0.0);
assert_eq!(f32::from_sample(i32::MIN), -1.0);
assert_eq!(f32::from_sample(1.0f32), 1.0);
assert_eq!(f32::from_sample(0f32), 0.0);
assert_eq!(f32::from_sample(-1.0f32), -1.0);
assert_eq!(f32::from_sample(1.0f64), 1.0);
assert_eq!(f32::from_sample(0f64), 0.0);
assert_eq!(f32::from_sample(-1.0f64), -1.0);
}
}