use crate::*; /// A unit of time, represented as an atomic 64-bit float. /// /// According to https://stackoverflow.com/a/873367, as per IEEE754, /// every integer between 1 and 2^53 can be represented exactly. /// This should mean that, even at 192kHz sampling rate, over 1 year of audio /// can be clocked in microseconds with f64 without losing precision. pub trait TimeUnit: InteriorMutable {} /// Implement an arithmetic operation for a unit of time #[macro_export] macro_rules! impl_op { ($T:ident, $Op:ident, $method:ident, |$a:ident,$b:ident|{$impl:expr}) => { impl $Op for $T { type Output = Self; #[inline] fn $method (self, other: Self) -> Self::Output { let $a = self.get(); let $b = other.get(); Self($impl.into()) } } impl $Op for $T { type Output = Self; #[inline] fn $method (self, other: usize) -> Self::Output { let $a = self.get(); let $b = other as f64; Self($impl.into()) } } impl $Op for $T { type Output = Self; #[inline] fn $method (self, other: f64) -> Self::Output { let $a = self.get(); let $b = other; Self($impl.into()) } } } } /// Define and implement a unit of time #[macro_export] macro_rules! impl_time_unit { ($T:ident) => { impl Gettable for $T { fn get (&self) -> f64 { self.0.load(Relaxed) } } impl InteriorMutable for $T { fn set (&self, value: f64) -> f64 { let old = self.get(); self.0.store(value, Relaxed); old } } impl TimeUnit for $T {} impl_op!($T, Add, add, |a, b|{a + b}); impl_op!($T, Sub, sub, |a, b|{a - b}); impl_op!($T, Mul, mul, |a, b|{a * b}); impl_op!($T, Div, div, |a, b|{a / b}); impl_op!($T, Rem, rem, |a, b|{a % b}); impl From for $T { fn from (value: f64) -> Self { Self(value.into()) } } impl From for $T { fn from (value: usize) -> Self { Self((value as f64).into()) } } impl From<$T> for f64 { fn from (value: $T) -> Self { value.get() } } impl From<$T> for usize { fn from (value: $T) -> Self { value.get() as usize } } impl From<&$T> for f64 { fn from (value: &$T) -> Self { value.get() } } impl From<&$T> for usize { fn from (value: &$T) -> Self { value.get() as usize } } impl Clone for $T { fn clone (&self) -> Self { Self(self.get().into()) } } } }