Vendor dependencies for 0.3.0 release

This commit is contained in:
2025-09-27 10:29:08 -05:00
parent 0c8d39d483
commit 82ab7f317b
26803 changed files with 16134934 additions and 0 deletions

699
vendor/dasp_sample/src/conv.rs vendored Normal file
View File

@@ -0,0 +1,699 @@
//! Pure functions and traits for converting between i8, i16, I24, i32, I48, i64, u8, u16, U24,
//! u32, U48, u64, f32 and f64.
//!
//! Each conversion function is performance focused, memory-sensitive and expects that the user has
//! validated their input prior to the function call.
//!
//! No conversion function will ever cast to a type with a size in bytes larger than the largest
//! between the source and target sample types.
//!
//! The conversion functions do *not* check the range of incoming values for floating point values
//! or any of the custom `I24`, `U24`, `I48` and `U48` types.
//!
//! Note that floating point conversions use the range -1.0 <= v < 1.0:
//! `(1.0 as f64).to_sample::<i16>()` will overflow!
use crate::types::{I24, I48, U24, U48};
macro_rules! conversion_fn {
($Rep:ty, $s:ident to_i8 { $body:expr }) => {
#[inline]
pub fn to_i8($s: $Rep) -> i8 {
$body
}
};
($Rep:ty, $s:ident to_i16 { $body:expr }) => {
#[inline]
pub fn to_i16($s: $Rep) -> i16 {
$body
}
};
($Rep:ty, $s:ident to_i24 { $body:expr }) => {
#[inline]
pub fn to_i24($s: $Rep) -> I24 {
$body
}
};
($Rep:ty, $s:ident to_i32 { $body:expr }) => {
#[inline]
pub fn to_i32($s: $Rep) -> i32 {
$body
}
};
($Rep:ty, $s:ident to_i48 { $body:expr }) => {
#[inline]
pub fn to_i48($s: $Rep) -> I48 {
$body
}
};
($Rep:ty, $s:ident to_i64 { $body:expr }) => {
#[inline]
pub fn to_i64($s: $Rep) -> i64 {
$body
}
};
($Rep:ty, $s:ident to_u8 { $body:expr }) => {
#[inline]
pub fn to_u8($s: $Rep) -> u8 {
$body
}
};
($Rep:ty, $s:ident to_u16 { $body:expr }) => {
#[inline]
pub fn to_u16($s: $Rep) -> u16 {
$body
}
};
($Rep:ty, $s:ident to_u24 { $body:expr }) => {
#[inline]
pub fn to_u24($s: $Rep) -> U24 {
$body
}
};
($Rep:ty, $s:ident to_u32 { $body:expr }) => {
#[inline]
pub fn to_u32($s: $Rep) -> u32 {
$body
}
};
($Rep:ty, $s:ident to_u48 { $body:expr }) => {
#[inline]
pub fn to_u48($s: $Rep) -> U48 {
$body
}
};
($Rep:ty, $s:ident to_u64 { $body:expr }) => {
#[inline]
pub fn to_u64($s: $Rep) -> u64 {
$body
}
};
($Rep:ty, $s:ident to_f32 { $body:expr }) => {
#[inline]
pub fn to_f32($s: $Rep) -> f32 {
$body
}
};
($Rep:ty, $s:ident to_f64 { $body:expr }) => {
#[inline]
pub fn to_f64($s: $Rep) -> f64 {
$body
}
};
}
macro_rules! conversion_fns {
($Rep:ty, $s:ident $fn_name:tt { $body:expr } $($rest:tt)*) => {
conversion_fn!($Rep, $s $fn_name { $body });
conversion_fns!($Rep, $($rest)*);
};
($Rep:ty, ) => {};
}
macro_rules! conversions {
($T:ident, $mod_name:ident { $($rest:tt)* }) => {
pub mod $mod_name {
use $crate::types::{I24, U24, I48, U48};
conversion_fns!($T, $($rest)*);
}
};
}
conversions!(i8, i8 {
s to_i16 { (s as i16) << 8 }
s to_i24 { I24::new_unchecked((s as i32) << 16) }
s to_i32 { (s as i32) << 24 }
s to_i48 { I48::new_unchecked((s as i64) << 40) }
s to_i64 { (s as i64) << 56 }
s to_u8 {
if s < 0 {
// 128i8 overflows, so we must use 127 + 1 instead.
(s + 127 + 1) as u8
} else {
(s as u8) + 128
}
}
s to_u16 {
if s < 0 {
((s + 127 + 1) as u16) << 8
} else {
(s as u16 + 128) << 8
}
}
s to_u24 {
U24::new_unchecked((s as i32 + 128) << 16)
}
s to_u32 {
if s < 0 {
((s + 127 + 1) as u32) << 24
} else {
(s as u32 + 128) << 24
}
}
s to_u48 {
U48::new_unchecked((s as i64 + 128) << 40)
}
s to_u64 {
if s < 0 {
((s + 127 + 1) as u64) << 56
} else {
(s as u64 + 128) << 56
}
}
s to_f32 {
s as f32 / 128.0
}
s to_f64 {
s as f64 / 128.0
}
});
conversions!(i16, i16 {
s to_i8 { (s >> 8) as i8 }
s to_i24 { I24::new_unchecked((s as i32) << 8) }
s to_i32 { (s as i32) << 16 }
s to_i48 { I48::new_unchecked((s as i64) << 32) }
s to_i64 { (s as i64) << 48 }
s to_u8 {
super::i8::to_u8(to_i8(s))
}
s to_u16 {
if s < 0 {
// 32_768i16 overflows, so we must use + 1 instead.
(s + 32_767 + 1) as u16
} else {
s as u16 + 32_768
}
}
s to_u24 {
if s < 0 {
U24::new_unchecked(((s + 32_767 + 1) as i32) << 8)
} else {
U24::new_unchecked((s as i32 + 32_768) << 8)
}
}
s to_u32 {
if s < 0 {
((s + 32_767 + 1) as u32) << 16
} else {
((s as u32) + 32_768) << 16
}
}
s to_u48 {
if s < 0 {
U48::new_unchecked(((s + 32_767 + 1) as i64) << 32)
} else {
U48::new_unchecked((s as i64 + 32_768) << 32)
}
}
s to_u64 {
if s < 0 {
((s + 32_767 + 1) as u64) << 48
} else {
((s as u64) + 32_768) << 48
}
}
s to_f32 {
s as f32 / 32_768.0
}
s to_f64 {
s as f64 / 32_768.0
}
});
conversions!(I24, i24 {
s to_i8 { (s.inner() >> 16) as i8 }
s to_i16 { (s.inner() >> 8) as i16 }
s to_i32 { s.inner() << 8 }
s to_i48 { I48::new_unchecked((s.inner() as i64) << 24) }
s to_i64 { (s.inner() as i64) << 40 }
s to_u8 {
super::i8::to_u8(to_i8(s))
}
s to_u16 {
super::i16::to_u16(to_i16(s))
}
s to_u24 {
U24::new_unchecked(s.inner() + 8_388_608)
}
s to_u32 {
((s.inner() + 8_388_608) as u32) << 8
}
s to_u48 {
U48::new_unchecked((s.inner() as i64 + 8_388_608) << 24)
}
s to_u64 {
((s.inner() + 8_388_608) as u64) << 40
}
s to_f32 {
s.inner() as f32 / 8_388_608.0
}
s to_f64 {
s.inner() as f64 / 8_388_608.0
}
});
conversions!(i32, i32 {
s to_i8 { (s >> 24) as i8 }
s to_i16 { (s >> 16) as i16 }
s to_i24 { I24::new_unchecked(s >> 8) }
s to_i48 { I48::new_unchecked((s as i64) << 16) }
s to_i64 { (s as i64) << 32 }
s to_u8 {
super::i8::to_u8(to_i8(s))
}
s to_u16 {
super::i16::to_u16(to_i16(s))
}
s to_u24 {
super::i24::to_u24(to_i24(s))
}
s to_u32 {
if s < 0 {
(s + 2_147_483_647 + 1) as u32
} else {
s as u32 + 2_147_483_648
}
}
s to_u48 {
U48::new_unchecked((s as i64 + 2_147_483_648) << 16)
}
s to_u64 {
if s < 0 {
((s + 2_147_483_647 + 1) as u64) << 32
} else {
(s as u64) + 2_147_483_648 << 32
}
}
s to_f32 {
s as f32 / 2_147_483_648.0
}
s to_f64 {
s as f64 / 2_147_483_648.0
}
});
conversions!(I48, i48 {
s to_i8 { (s.inner() >> 40) as i8 }
s to_i16 { (s.inner() >> 32) as i16 }
s to_i24 { I24::new_unchecked((s.inner() >> 24) as i32) }
s to_i32 { (s.inner() >> 16) as i32 }
s to_i64 { s.inner() << 16 }
s to_u8 {
super::i8::to_u8(to_i8(s))
}
s to_u16 {
super::i16::to_u16(to_i16(s))
}
s to_u24 {
super::i24::to_u24(to_i24(s))
}
s to_u32 {
super::i32::to_u32(to_i32(s))
}
s to_u48 {
U48::new_unchecked(s.inner() + 140_737_488_355_328)
}
s to_u64 {
((s.inner() + 140_737_488_355_328) as u64) << 16
}
s to_f32 {
s.inner() as f32 / 140_737_488_355_328.0
}
s to_f64 {
s.inner() as f64 / 140_737_488_355_328.0
}
});
conversions!(i64, i64 {
s to_i8 { (s >> 56) as i8 }
s to_i16 { (s >> 48) as i16 }
s to_i24 { I24::new_unchecked((s >> 40) as i32) }
s to_i32 { (s >> 32) as i32 }
s to_i48 { I48::new_unchecked(s >> 16) }
s to_u8 {
super::i8::to_u8(to_i8(s))
}
s to_u16 {
super::i16::to_u16(to_i16(s))
}
s to_u24 {
super::i24::to_u24(to_i24(s))
}
s to_u32 {
super::i32::to_u32(to_i32(s))
}
s to_u48 {
super::i48::to_u48(to_i48(s))
}
s to_u64 {
if s < 0 {
(s + 9_223_372_036_854_775_807 + 1) as u64
} else {
s as u64 + 9_223_372_036_854_775_808
}
}
s to_f32 {
s as f32 / 9_223_372_036_854_775_808.0
}
s to_f64 {
s as f64 / 9_223_372_036_854_775_808.0
}
});
conversions!(u8, u8 {
s to_i8 {
if s < 128 {
s as i8 - 127 - 1
} else {
(s - 128) as i8
}
}
s to_i16 {
(s as i16 - 128) << 8
}
s to_i24 {
I24::new_unchecked((s as i32 - 128) << 16)
}
s to_i32 {
(s as i32 - 128) << 24
}
s to_i48 {
I48::new_unchecked((s as i64 - 128) << 40)
}
s to_i64 {
(s as i64 - 128) << 56
}
s to_u16 { (s as u16) << 8 }
s to_u24 { U24::new_unchecked((s as i32) << 16) }
s to_u32 { (s as u32) << 24 }
s to_u48 { U48::new_unchecked((s as i64) << 40) }
s to_u64 { (s as u64) << 56 }
s to_f32 { super::i8::to_f32(to_i8(s)) }
s to_f64 { super::i8::to_f64(to_i8(s)) }
});
conversions!(u16, u16 {
s to_i8 { super::u8::to_i8(to_u8(s)) }
s to_i16 {
if s < 32_768 {
s as i16 - 32_767 - 1
} else {
(s - 32_768) as i16
}
}
s to_i24 {
I24::new_unchecked((s as i32 - 32_768) << 8)
}
s to_i32 {
(s as i32 - 32_768) << 16
}
s to_i48 {
I48::new_unchecked((s as i64 - 32_768) << 32)
}
s to_i64 {
(s as i64 - 32_768) << 48
}
s to_u8 { (s >> 8) as u8 }
s to_u24 { U24::new_unchecked((s as i32) << 8) }
s to_u32 { (s as u32) << 16 }
s to_u48 { U48::new_unchecked((s as i64) << 32) }
s to_u64 { (s as u64) << 48 }
s to_f32 { super::i16::to_f32(to_i16(s)) }
s to_f64 { super::i16::to_f64(to_i16(s)) }
});
conversions!(U24, u24 {
s to_i8 { super::u8::to_i8(to_u8(s)) }
s to_i16 { super::u16::to_i16(to_u16(s)) }
s to_i24 {
I24::new_unchecked(s.inner() - 8_388_608)
}
s to_i32 {
(s.inner() - 8_388_608) << 8
}
s to_i48 {
I48::new_unchecked(((s.inner() as i64) - 8_388_608) << 24)
}
s to_i64 {
(s.inner() as i64 - 8_388_608) << 40
}
s to_u8 { (s.inner() >> 16) as u8 }
s to_u16 { (s.inner() >> 8) as u16 }
s to_u32 { (s.inner() as u32) << 8 }
s to_u48 { U48::new_unchecked((s.inner() as i64) << 24) }
s to_u64 { (s.inner() as u64) << 40 }
s to_f32 { super::i24::to_f32(to_i24(s)) }
s to_f64 { super::i24::to_f64(to_i24(s)) }
});
conversions!(u32, u32 {
s to_i8 { super::u8::to_i8(to_u8(s)) }
s to_i16 { super::u16::to_i16(to_u16(s)) }
s to_i24 { super::u24::to_i24(to_u24(s)) }
s to_i32 {
if s < 2_147_483_648 {
s as i32 - 2_147_483_647 - 1
} else {
(s - 2_147_483_648) as i32
}
}
s to_i48 {
I48::new_unchecked((s as i64 - 2_147_483_648) << 16)
}
s to_i64 {
(s as i64 - 2_147_483_648) << 32
}
s to_u8 { (s >> 24) as u8 }
s to_u16 { (s >> 16) as u16 }
s to_u24 { U24::new_unchecked((s >> 8) as i32) }
s to_u48 { U48::new_unchecked((s as i64) << 16) }
s to_u64 { (s as u64) << 32 }
s to_f32 { super::i32::to_f32(to_i32(s)) }
s to_f64 { super::i32::to_f64(to_i32(s)) }
});
conversions!(U48, u48 {
s to_i8 { super::u8::to_i8(to_u8(s)) }
s to_i16 { super::u16::to_i16(to_u16(s)) }
s to_i24 { super::u24::to_i24(to_u24(s)) }
s to_i32 { super::u32::to_i32(to_u32(s)) }
s to_i48 {
I48::new_unchecked(s.inner() - 140_737_488_355_328)
}
s to_i64 {
(s.inner() - 140_737_488_355_328) << 16
}
s to_u8 { (s.inner() >> 40) as u8 }
s to_u16 { (s.inner() >> 32) as u16 }
s to_u24 { U24::new_unchecked((s.inner() >> 24) as i32) }
s to_u32 { (s.inner() >> 16) as u32 }
s to_u64 { (s.inner() as u64) << 16 }
s to_f32 { super::i48::to_f32(to_i48(s)) }
s to_f64 { super::i48::to_f64(to_i48(s)) }
});
conversions!(u64, u64 {
s to_i8 { super::u8::to_i8(to_u8(s)) }
s to_i16 { super::u16::to_i16(to_u16(s)) }
s to_i24 { super::u24::to_i24(to_u24(s)) }
s to_i32 { super::u32::to_i32(to_u32(s)) }
s to_i48 { super::u48::to_i48(to_u48(s)) }
s to_i64 {
if s < 9_223_372_036_854_775_808 {
s as i64 - 9_223_372_036_854_775_807 - 1
} else {
(s - 9_223_372_036_854_775_808) as i64
}
}
s to_u8 { (s >> 56) as u8 }
s to_u16 { (s >> 48) as u16 }
s to_u24 { U24::new_unchecked((s >> 40) as i32) }
s to_u32 { (s >> 32) as u32 }
s to_u48 { U48::new_unchecked((s >> 16) as i64) }
s to_f32 { super::i64::to_f32(to_i64(s)) }
s to_f64 { super::i64::to_f64(to_i64(s)) }
});
// The following conversions assume `-1.0 <= s < 1.0` (note that +1.0 is excluded) and will
// overflow otherwise.
conversions!(f32, f32 {
s to_i8 { (s * 128.0) as i8 }
s to_i16 { (s * 32_768.0) as i16 }
s to_i24 { I24::new_unchecked((s * 8_388_608.0) as i32) }
s to_i32 { (s * 2_147_483_648.0) as i32 }
s to_i48 { I48::new_unchecked((s * 140_737_488_355_328.0) as i64) }
s to_i64 { (s * 9_223_372_036_854_775_808.0) as i64 }
s to_u8 { super::i8::to_u8(to_i8(s)) }
s to_u16 { super::i16::to_u16(to_i16(s)) }
s to_u24 { super::i24::to_u24(to_i24(s)) }
s to_u32 { super::i32::to_u32(to_i32(s)) }
s to_u48 { super::i48::to_u48(to_i48(s)) }
s to_u64 { super::i64::to_u64(to_i64(s)) }
s to_f64 { s as f64 }
});
// The following conversions assume `-1.0 <= s < 1.0` (note that +1.0 is excluded) and will
// overflow otherwise.
conversions!(f64, f64 {
s to_i8 { (s * 128.0) as i8 }
s to_i16 { (s * 32_768.0) as i16 }
s to_i24 { I24::new_unchecked((s * 8_388_608.0) as i32) }
s to_i32 { (s * 2_147_483_648.0) as i32 }
s to_i48 { I48::new_unchecked((s * 140_737_488_355_328.0) as i64) }
s to_i64 { (s * 9_223_372_036_854_775_808.0) as i64 }
s to_u8 { super::i8::to_u8(to_i8(s)) }
s to_u16 { super::i16::to_u16(to_i16(s)) }
s to_u24 { super::i24::to_u24(to_i24(s)) }
s to_u32 { super::i32::to_u32(to_i32(s)) }
s to_u48 { super::i48::to_u48(to_i48(s)) }
s to_u64 { super::i64::to_u64(to_i64(s)) }
s to_f32 { s as f32 }
});
/// Similar to the std `From` trait, but specifically for converting between sample types.
///
/// We use this trait to be generic over the `Sample::to_sample` and `Sample::from_sample` methods.
pub trait FromSample<S> {
fn from_sample_(s: S) -> Self;
}
impl<S> FromSample<S> for S {
#[inline]
fn from_sample_(s: S) -> Self {
s
}
}
/// Implement the `FromSample` trait for the given types.
macro_rules! impl_from_sample {
($T:ty, $fn_name:ident from $({$U:ident: $Umod:ident})*) => {
$(
impl FromSample<$U> for $T {
#[inline]
fn from_sample_(s: $U) -> Self {
self::$Umod::$fn_name(s)
}
}
)*
};
}
impl_from_sample! {i8, to_i8 from
{i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {i16, to_i16 from
{i8:i8} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {I24, to_i24 from
{i8:i8} {i16:i16} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {i32, to_i32 from
{i8:i8} {i16:i16} {I24:i24} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {I48, to_i48 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {i64, to_i64 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {u8, to_u8 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {u16, to_u16 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {U24, to_u24 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {u32:u32} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {u32, to_u32 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {U48:u48} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {U48, to_u48 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {u64:u64}
{f32:f32} {f64:f64}
}
impl_from_sample! {u64, to_u64 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48}
{f32:f32} {f64:f64}
}
impl_from_sample! {f32, to_f32 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f64:f64}
}
impl_from_sample! {f64, to_f64 from
{i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64}
{u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64}
{f32:f32}
}
/// Similar to the std `Into` trait, but specifically for converting between sample types.
///
/// This trait has a blanket implementation for all types that implement
/// [`FromSample`](./trait.FromSample.html).
pub trait ToSample<S> {
fn to_sample_(self) -> S;
}
impl<T, U> ToSample<U> for T
where
U: FromSample<T>,
{
#[inline]
fn to_sample_(self) -> U {
U::from_sample_(self)
}
}
/// Sample types which may be converted to and from some type `S`.
pub trait Duplex<S>: FromSample<S> + ToSample<S> {}
impl<S, T> Duplex<S> for T where T: FromSample<S> + ToSample<S> {}

324
vendor/dasp_sample/src/lib.rs vendored Normal file
View File

@@ -0,0 +1,324 @@
//! Use the [**Sample**](./trait.Sample.html) trait to remain generic over sample types, easily
//! access sample type conversions, apply basic audio operations and more.
//!
//! The **Sample** trait is the core abstraction throughout dasp on which most other abstractions
//! are based.
#![cfg_attr(not(feature = "std"), no_std)]
#![cfg_attr(not(feature = "std"), feature(core_intrinsics))]
#[cfg(not(feature = "std"))]
extern crate alloc;
pub use conv::{Duplex, FromSample, ToSample};
pub use types::{I24, I48, U24, U48};
pub mod conv;
mod ops;
pub mod types;
/// A trait for working generically across different **Sample** format types.
///
/// Provides methods for converting to and from any type that implements the
/// [`FromSample`](./trait.FromSample.html) trait and provides methods for performing signal
/// amplitude addition and multiplication.
///
/// # Example
///
/// ```rust
/// use dasp_sample::{I24, Sample};
///
/// fn main() {
/// assert_eq!((-1.0).to_sample::<u8>(), 0);
/// assert_eq!(0.0.to_sample::<u8>(), 128);
/// assert_eq!(0i32.to_sample::<u32>(), 2_147_483_648);
/// assert_eq!(I24::new(0).unwrap(), Sample::from_sample(0.0));
/// assert_eq!(0.0, Sample::EQUILIBRIUM);
/// }
/// ```
pub trait Sample: Copy + Clone + PartialOrd + PartialEq {
/// When summing two samples of a signal together, it is necessary for both samples to be
/// represented in some signed format. This associated `Addition` type represents the format to
/// which `Self` should be converted for optimal `Addition` performance.
///
/// For example, u32's optimal `Addition` type would be i32, u8's would be i8, f32's would be
/// f32, etc.
///
/// Specifying this as an associated type allows us to automatically determine the optimal,
/// lossless Addition format type for summing any two unique `Sample` types together.
///
/// As a user of the `sample` crate, you will never need to be concerned with this type unless
/// you are defining your own unique `Sample` type(s).
type Signed: SignedSample + Duplex<Self>;
/// When multiplying two samples of a signal together, it is necessary for both samples to be
/// represented in some signed, floating-point format. This associated `Multiplication` type
/// represents the format to which `Self` should be converted for optimal `Multiplication`
/// performance.
///
/// For example, u32's optimal `Multiplication` type would be f32, u64's would be f64, i8's
/// would be f32, etc.
///
/// Specifying this as an associated type allows us to automatically determine the optimal,
/// lossless Multiplication format type for multiplying any two unique `Sample` types together.
///
/// As a user of the `sample` crate, you will never need to be concerned with this type unless
/// you are defining your own unique `Sample` type(s).
type Float: FloatSample + Duplex<Self>;
/// The equilibrium value for the wave that this `Sample` type represents. This is normally the
/// value that is equal distance from both the min and max ranges of the sample.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(0.0, f32::EQUILIBRIUM);
/// assert_eq!(0, i32::EQUILIBRIUM);
/// assert_eq!(128, u8::EQUILIBRIUM);
/// assert_eq!(32_768_u16, Sample::EQUILIBRIUM);
/// }
/// ```
///
/// **Note:** This will likely be changed to an "associated const" if the feature lands.
const EQUILIBRIUM: Self;
/// The multiplicative identity of the signal.
///
/// In other words: A value which when used to scale/multiply the amplitude or frequency of a
/// signal, returns the same signal.
///
/// This is useful as a default, non-affecting amplitude or frequency multiplier.
///
/// # Example
///
/// ```rust
/// use dasp_sample::{Sample, U48};
///
/// fn main() {
/// assert_eq!(1.0, f32::IDENTITY);
/// assert_eq!(1.0, i8::IDENTITY);
/// assert_eq!(1.0, u8::IDENTITY);
/// assert_eq!(1.0, U48::IDENTITY);
/// }
/// ```
const IDENTITY: Self::Float = <Self::Float as FloatSample>::IDENTITY;
/// Convert `self` to any type that implements `FromSample<Self>`.
///
/// Find more details on type-specific conversion ranges and caveats in the `conv` module.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(0.0.to_sample::<i32>(), 0);
/// assert_eq!(0.0.to_sample::<u8>(), 128);
/// assert_eq!((-1.0).to_sample::<u8>(), 0);
/// }
/// ```
#[inline]
fn to_sample<S>(self) -> S
where
Self: ToSample<S>,
{
self.to_sample_()
}
/// Create a `Self` from any type that implements `ToSample<Self>`.
///
/// Find more details on type-specific conversion ranges and caveats in the `conv` module.
///
/// # Example
///
/// ```rust
/// use dasp_sample::{Sample, I24};
///
/// fn main() {
/// assert_eq!(f32::from_sample(128_u8), 0.0);
/// assert_eq!(i8::from_sample(-1.0), -128);
/// assert_eq!(I24::from_sample(0.0), I24::new(0).unwrap());
/// }
/// ```
#[inline]
fn from_sample<S>(s: S) -> Self
where
Self: FromSample<S>,
{
FromSample::from_sample_(s)
}
/// Converts `self` to the equivalent `Sample` in the associated `Signed` format.
///
/// This is a simple wrapper around `Sample::to_sample` which may provide extra convenience in
/// some cases, particularly for assisting type inference.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(128_u8.to_signed_sample(), 0i8);
/// }
/// ```
fn to_signed_sample(self) -> Self::Signed {
self.to_sample()
}
/// Converts `self` to the equivalent `Sample` in the associated `Float` format.
///
/// This is a simple wrapper around `Sample::to_sample` which may provide extra convenience in
/// some cases, particularly for assisting type inference.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(128_u8.to_float_sample(), 0.0);
/// }
/// ```
fn to_float_sample(self) -> Self::Float {
self.to_sample()
}
/// Adds (or "offsets") the amplitude of the `Sample` by the given signed amplitude.
///
/// `Self` will be converted to `Self::Signed`, the addition will occur and then the result
/// will be converted back to `Self`. These conversions allow us to correctly handle the
/// addition of unsigned signal formats.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(0.25.add_amp(0.5), 0.75);
/// assert_eq!(192u8.add_amp(-128), 64);
/// }
/// ```
#[inline]
fn add_amp(self, amp: Self::Signed) -> Self {
let self_s = self.to_signed_sample();
(self_s + amp).to_sample()
}
/// Multiplies (or "scales") the amplitude of the `Sample` by the given float amplitude.
///
/// - `amp` > 1.0 amplifies the sample.
/// - `amp` < 1.0 attenuates the sample.
/// - `amp` == 1.0 yields the same sample.
/// - `amp` == 0.0 yields the `Sample::EQUILIBRIUM`.
///
/// `Self` will be converted to `Self::Float`, the multiplication will occur and then the
/// result will be converted back to `Self`. These conversions allow us to correctly handle the
/// multiplication of integral signal formats.
///
/// # Example
///
/// ```rust
/// use dasp_sample::Sample;
///
/// fn main() {
/// assert_eq!(64_i8.mul_amp(0.5), 32);
/// assert_eq!(0.5.mul_amp(-2.0), -1.0);
/// assert_eq!(64_u8.mul_amp(0.0), 128);
/// }
/// ```
#[inline]
fn mul_amp(self, amp: Self::Float) -> Self {
let self_f = self.to_float_sample();
(self_f * amp).to_sample()
}
}
/// A macro used to simplify the implementation of `Sample`.
macro_rules! impl_sample {
($($T:ty:
Signed: $Addition:ty,
Float: $Modulation:ty,
EQUILIBRIUM: $EQUILIBRIUM:expr),*) =>
{
$(
impl Sample for $T {
type Signed = $Addition;
type Float = $Modulation;
const EQUILIBRIUM: Self = $EQUILIBRIUM;
}
)*
}
}
// Expands to `Sample` implementations for all of the following types.
impl_sample! {
i8: Signed: i8, Float: f32, EQUILIBRIUM: 0,
i16: Signed: i16, Float: f32, EQUILIBRIUM: 0,
I24: Signed: I24, Float: f32, EQUILIBRIUM: types::i24::EQUILIBRIUM,
i32: Signed: i32, Float: f32, EQUILIBRIUM: 0,
I48: Signed: I48, Float: f64, EQUILIBRIUM: types::i48::EQUILIBRIUM,
i64: Signed: i64, Float: f64, EQUILIBRIUM: 0,
u8: Signed: i8, Float: f32, EQUILIBRIUM: 128,
u16: Signed: i16, Float: f32, EQUILIBRIUM: 32_768,
U24: Signed: i32, Float: f32, EQUILIBRIUM: types::u24::EQUILIBRIUM,
u32: Signed: i32, Float: f32, EQUILIBRIUM: 2_147_483_648,
U48: Signed: i64, Float: f64, EQUILIBRIUM: types::u48::EQUILIBRIUM,
u64: Signed: i64, Float: f64, EQUILIBRIUM: 9_223_372_036_854_775_808,
f32: Signed: f32, Float: f32, EQUILIBRIUM: 0.0,
f64: Signed: f64, Float: f64, EQUILIBRIUM: 0.0
}
/// Integral and floating-point **Sample** format types whose equilibrium is at 0.
///
/// **Sample**s often need to be converted to some mutual **SignedSample** type for signal
/// addition.
pub trait SignedSample:
Sample<Signed = Self>
+ core::ops::Add<Output = Self>
+ core::ops::Sub<Output = Self>
+ core::ops::Neg<Output = Self>
{
}
macro_rules! impl_signed_sample { ($($T:ty)*) => { $( impl SignedSample for $T {} )* } }
impl_signed_sample!(i8 i16 I24 i32 I48 i64 f32 f64);
/// Sample format types represented as floating point numbers.
///
/// **Sample**s often need to be converted to some mutual **FloatSample** type for signal scaling
/// and modulation.
pub trait FloatSample:
Sample<Signed = Self, Float = Self>
+ SignedSample
+ core::ops::Mul<Output = Self>
+ core::ops::Div<Output = Self>
+ Duplex<f32>
+ Duplex<f64>
{
/// Represents the multiplicative identity of the floating point signal.
const IDENTITY: Self;
/// Calculate the square root of `Self`.
fn sample_sqrt(self) -> Self;
}
impl FloatSample for f32 {
const IDENTITY: Self = 1.0;
#[inline]
fn sample_sqrt(self) -> Self {
ops::f32::sqrt(self)
}
}
impl FloatSample for f64 {
const IDENTITY: Self = 1.0;
#[inline]
fn sample_sqrt(self) -> Self {
ops::f64::sqrt(self)
}
}

27
vendor/dasp_sample/src/ops.rs vendored Normal file
View File

@@ -0,0 +1,27 @@
pub mod f32 {
#[allow(unused_imports)]
use core;
#[cfg(not(feature = "std"))]
pub fn sqrt(x: f32) -> f32 {
unsafe { core::intrinsics::sqrtf32(x) }
}
#[cfg(feature = "std")]
pub fn sqrt(x: f32) -> f32 {
x.sqrt()
}
}
pub mod f64 {
#[allow(unused_imports)]
use core;
#[cfg(not(feature = "std"))]
pub fn sqrt(x: f64) -> f64 {
unsafe { core::intrinsics::sqrtf64(x) }
}
#[cfg(feature = "std")]
pub fn sqrt(x: f64) -> f64 {
x.sqrt()
}
}

284
vendor/dasp_sample/src/types.rs vendored Normal file
View File

@@ -0,0 +1,284 @@
//! A collection of custom, non-std **Sample** types.
pub use self::i11::I11;
pub use self::i20::I20;
pub use self::i24::I24;
pub use self::i48::I48;
pub use self::u11::U11;
pub use self::u20::U20;
pub use self::u24::U24;
pub use self::u48::U48;
macro_rules! impl_from {
($T:ident: $Rep:ident from {$U:ident : $URep:ty}) => {
impl From<$U> for $T {
#[inline]
fn from(other: $U) -> Self {
$T(other.inner() as $Rep)
}
}
};
($T:ident: $Rep:ident from $U:ident) => {
impl From<$U> for $T {
#[inline]
fn from(other: $U) -> Self {
$T(other as $Rep)
}
}
};
}
macro_rules! impl_froms {
($T:ident: $Rep:ident, {$U:ident : $URep:ty}, $($rest:tt)*) => {
impl_from!($T: $Rep from {$U: $URep});
impl_froms!($T: $Rep, $($rest)*);
};
($T:ident: $Rep:ident, {$U:ident : $URep:ty}) => {
impl_from!($T: $Rep from {$U: $URep});
};
($T:ident: $Rep:ident, $U:ident, $($rest:tt)*) => {
impl_from!($T: $Rep from $U);
impl_froms!($T: $Rep, $($rest)*);
};
($T:ident: $Rep:ident, $U:ident) => {
impl_from!($T: $Rep from $U);
};
($T:ident: $Rep:ident,) => {};
}
macro_rules! impl_neg {
($T:ident) => {
impl ::core::ops::Neg for $T {
type Output = $T;
#[inline]
fn neg(self) -> $T {
$T(-self.0)
}
}
};
}
macro_rules! new_sample_type {
($T:ident: $Rep:ident, eq: $EQ:expr, min: $MIN:expr, max: $MAX:expr, total: $TOTAL:expr, from: $($rest:tt)*) => {
pub const MIN: $T = $T($MIN);
pub const MAX: $T = $T($MAX);
pub const EQUILIBRIUM: $T = $T($EQ);
const MIN_REP: $Rep = $MIN;
const MAX_REP: $Rep = $MAX;
const TOTAL: $Rep = $TOTAL;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct $T($Rep);
impl From<$Rep> for $T {
#[inline]
fn from(val: $Rep) -> Self {
$T(val).wrap_overflow()
}
}
impl $T {
/// Construct a new sample if the given value is within range.
///
/// Returns `None` if `val` is out of range.
#[inline]
pub fn new(val: $Rep) -> Option<Self> {
if val > MAX_REP || val < MIN_REP {
None
} else {
Some($T(val))
}
}
/// Constructs a new sample without checking for overflowing.
///
/// This should *only* be used if the user can guarantee the sample will be within
/// range and they require the extra performance.
///
/// If this function is used, the sample crate can't guarantee that the returned sample
/// or any interacting samples will remain within their MIN and MAX bounds.
pub fn new_unchecked(s: $Rep) -> Self {
$T(s)
}
/// Return the internal value used to represent the sample type.
#[inline]
pub fn inner(self) -> $Rep {
self.0
}
/// Wraps self once in the case that self has overflowed.
#[inline]
fn wrap_overflow_once(self) -> Self {
if self.0 > MAX_REP { $T(self.0 - TOTAL) }
else if self.0 < MIN_REP { $T(self.0 + TOTAL) }
else { self }
}
/// Wraps self in the case that self has overflowed.
#[inline]
fn wrap_overflow(mut self) -> Self {
while self.0 > MAX_REP {
self.0 -= TOTAL;
}
while self.0 < MIN_REP {
self.0 += TOTAL;
}
self
}
}
impl ::core::ops::Add<$T> for $T {
type Output = $T;
#[inline]
fn add(self, other: Self) -> Self {
if cfg!(debug_assertions) {
$T::new(self.0 + other.0).expect("arithmetic operation overflowed")
} else {
$T(self.0 + other.0).wrap_overflow_once()
}
}
}
impl ::core::ops::Sub<$T> for $T {
type Output = $T;
#[inline]
fn sub(self, other: Self) -> Self {
if cfg!(debug_assertions) {
$T::new(self.0 - other.0).expect("arithmetic operation overflowed")
} else {
$T(self.0 - other.0).wrap_overflow_once()
}
}
}
impl ::core::ops::Mul<$T> for $T {
type Output = $T;
#[inline]
fn mul(self, other: Self) -> Self {
if cfg!(debug_assertions) {
$T::new(self.0 * other.0).expect("arithmetic operation overflowed")
} else {
$T::from(self.0 * other.0)
}
}
}
impl ::core::ops::Div<$T> for $T {
type Output = $T;
#[inline]
fn div(self, other: Self) -> Self {
$T(self.0 / other.0)
}
}
impl ::core::ops::Not for $T {
type Output = $T;
#[inline]
fn not(self) -> $T {
$T(!self.0)
}
}
impl ::core::ops::Rem<$T> for $T {
type Output = $T;
#[inline]
fn rem(self, other: Self) -> Self {
$T(self.0 % other.0)
}
}
impl ::core::ops::Shl<$T> for $T {
type Output = $T;
#[inline]
fn shl(self, other: Self) -> Self {
// TODO: Needs review
$T(self.0 << other.0)
}
}
impl ::core::ops::Shr<$T> for $T {
type Output = $T;
#[inline]
fn shr(self, other: Self) -> Self {
// TODO: Needs review
$T(self.0 >> other.0)
}
}
impl ::core::ops::BitAnd<$T> for $T {
type Output = $T;
#[inline]
fn bitand(self, other: Self) -> Self {
$T(self.0 & other.0)
}
}
impl ::core::ops::BitOr<$T> for $T {
type Output = $T;
#[inline]
fn bitor(self, other: Self) -> Self {
$T(self.0 | other.0)
}
}
impl ::core::ops::BitXor<$T> for $T {
type Output = $T;
#[inline]
fn bitxor(self, other: Self) -> Self {
$T(self.0 ^ other.0)
}
}
impl_froms!($T: $Rep, $($rest)*);
};
}
pub mod i11 {
new_sample_type!(I11: i16, eq: 0, min: -1024, max: 1023, total: 2048,
from: i8, u8);
impl_neg!(I11);
}
pub mod i20 {
use super::{I11, U11};
new_sample_type!(I20: i32, eq: 0, min: -524_288, max: 524_287, total: 1_048_576,
from: i8, {I11:i16}, i16, u8, {U11:i16}, u16);
}
pub mod i24 {
use super::{I20, U20};
new_sample_type!(I24: i32, eq: 0, min: -8_388_608, max: 8_388_607, total: 16_777_216,
from: i8, i16, {I20:i32}, u8, u16, {U20:i32});
impl_neg!(I24);
}
pub mod i48 {
use super::{I20, I24, U20, U24};
new_sample_type!(I48: i64, eq: 0, min: -140_737_488_355_328, max: 140_737_488_355_327, total: 281_474_976_710_656,
from: i8, i16, {I20:i32}, {I24:i32}, i32, u8, u16, {U20:i32}, {U24:i32}, u32);
impl_neg!(I48);
}
pub mod u11 {
new_sample_type!(U11: i16, eq: 1024, min: 0, max: 2047, total: 2048,
from: u8);
impl_neg!(U11);
}
pub mod u20 {
new_sample_type!(U20: i32, eq: 524_288, min: 0, max: 1_048_575, total: 1_048_576,
from: u8, u16);
}
pub mod u24 {
use super::U20;
new_sample_type!(U24: i32, eq: 8_388_608, min: 0, max: 16_777_215, total: 16_777_216,
from: u8, u16, {U20:i32});
}
pub mod u48 {
use super::{U20, U24};
new_sample_type!(U48: i64, eq: 140_737_488_355_328, min: 0, max: 281_474_976_710_655, total: 281_474_976_710_656,
from: u8, u16, {U20:i32}, {U24:i32}, u32);
}