sample/
types.rs

1//! A collection of custom, non-std **Sample** types.
2
3pub use self::i11::I11;
4pub use self::u11::U11;
5pub use self::i20::I20;
6pub use self::u20::U20;
7pub use self::i24::I24;
8pub use self::u24::U24;
9pub use self::i48::I48;
10pub use self::u48::U48;
11
12
13macro_rules! impl_from {
14    ($T:ident: $Rep:ident from {$U:ident : $URep:ty}) => {
15        impl From<$U> for $T {
16            #[inline]
17            fn from(other: $U) -> Self {
18                $T(other.inner() as $Rep)
19            }
20        }
21    };
22    ($T:ident: $Rep:ident from $U:ident) => {
23        impl From<$U> for $T {
24            #[inline]
25            fn from(other: $U) -> Self {
26                $T(other as $Rep)
27            }
28        }
29    };
30}
31
32macro_rules! impl_froms {
33    ($T:ident: $Rep:ident, {$U:ident : $URep:ty}, $($rest:tt)*) => {
34        impl_from!($T: $Rep from {$U: $URep});
35        impl_froms!($T: $Rep, $($rest)*);
36    };
37    ($T:ident: $Rep:ident, {$U:ident : $URep:ty}) => {
38        impl_from!($T: $Rep from {$U: $URep});
39    };
40    ($T:ident: $Rep:ident, $U:ident, $($rest:tt)*) => {
41        impl_from!($T: $Rep from $U);
42        impl_froms!($T: $Rep, $($rest)*);
43    };
44    ($T:ident: $Rep:ident, $U:ident) => {
45        impl_from!($T: $Rep from $U);
46    };
47    ($T:ident: $Rep:ident,) => {};
48}
49
50macro_rules! impl_neg {
51    ($T:ident) => {
52        impl ::core::ops::Neg for $T {
53            type Output = $T;
54            #[inline]
55            fn neg(self) -> $T {
56                $T(-self.0)
57            }
58        }
59    };
60}
61
62macro_rules! new_sample_type {
63    ($T:ident: $Rep:ident, eq: $EQ:expr, min: $MIN:expr, max: $MAX:expr, total: $TOTAL:expr, from: $($rest:tt)*) => {
64        pub const MIN: $T = $T($MIN);
65        pub const MAX: $T = $T($MAX);
66        pub const EQUILIBRIUM: $T = $T($EQ);
67        const MIN_REP: $Rep = $MIN;
68        const MAX_REP: $Rep = $MAX;
69        const TOTAL: $Rep = $TOTAL;
70
71        #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
72        pub struct $T($Rep);
73
74        impl From<$Rep> for $T {
75            #[inline]
76            fn from(val: $Rep) -> Self {
77                $T(val).wrap_overflow()
78            }
79        }
80
81        impl $T {
82            /// Construct a new sample if the given value is within range.
83            ///
84            /// Returns `None` if `val` is out of range.
85            #[inline]
86            pub fn new(val: $Rep) -> Option<Self> {
87                if val > MAX_REP || val < MIN_REP {
88                    None
89                } else {
90                    Some($T(val))
91                }
92            }
93
94            /// Constructs a new sample without checking for overflowing.
95            ///
96            /// This should *only* be used if the user can guarantee the sample will be within
97            /// range and they require the extra performance.
98            ///
99            /// If this function is used, the sample crate can't guarantee that the returned sample
100            /// or any interacting samples will remain within their MIN and MAX bounds.
101            pub fn new_unchecked(s: $Rep) -> Self {
102                $T(s)
103            }
104
105            /// Return the internal value used to represent the sample type.
106            #[inline]
107            pub fn inner(self) -> $Rep {
108                self.0
109            }
110
111            /// Wraps self once in the case that self has overflowed.
112            #[inline]
113            fn wrap_overflow_once(self) -> Self {
114                if      self.0 > MAX_REP { $T(self.0 - TOTAL) }
115                else if self.0 < MIN_REP { $T(self.0 + TOTAL) }
116                else                     { self }
117            }
118
119            /// Wraps self in the case that self has overflowed.
120            #[inline]
121            fn wrap_overflow(mut self) -> Self {
122                while self.0 > MAX_REP {
123                    self.0 -= TOTAL;
124                }
125                while self.0 < MIN_REP {
126                    self.0 += TOTAL;
127                }
128                self
129            }
130        }
131
132        impl ::core::ops::Add<$T> for $T {
133            type Output = $T;
134            #[inline]
135            fn add(self, other: Self) -> Self {
136                if cfg!(debug_assertions) {
137                    $T::new(self.0 + other.0).expect("arithmetic operation overflowed")
138                } else {
139                    $T(self.0 + other.0).wrap_overflow_once()
140                }
141            }
142        }
143
144        impl ::core::ops::Sub<$T> for $T {
145            type Output = $T;
146            #[inline]
147            fn sub(self, other: Self) -> Self {
148                if cfg!(debug_assertions) {
149                    $T::new(self.0 - other.0).expect("arithmetic operation overflowed")
150                } else {
151                    $T(self.0 - other.0).wrap_overflow_once()
152                }
153            }
154        }
155
156        impl ::core::ops::Mul<$T> for $T {
157            type Output = $T;
158            #[inline]
159            fn mul(self, other: Self) -> Self {
160                if cfg!(debug_assertions) {
161                    $T::new(self.0 * other.0).expect("arithmetic operation overflowed")
162                } else {
163                    $T::from(self.0 * other.0)
164                }
165            }
166        }
167
168        impl ::core::ops::Div<$T> for $T {
169            type Output = $T;
170            #[inline]
171            fn div(self, other: Self) -> Self {
172                $T(self.0 / other.0)
173            }
174        }
175
176        impl ::core::ops::Not for $T {
177            type Output = $T;
178            #[inline]
179            fn not(self) -> $T {
180                $T(!self.0)
181            }
182        }
183
184        impl ::core::ops::Rem<$T> for $T {
185            type Output = $T;
186            #[inline]
187            fn rem(self, other: Self) -> Self {
188                $T(self.0 % other.0)
189            }
190        }
191
192        impl ::core::ops::Shl<$T> for $T {
193            type Output = $T;
194            #[inline]
195            fn shl(self, other: Self) -> Self {
196                // TODO: Needs review
197                $T(self.0 << other.0)
198            }
199        }
200
201        impl ::core::ops::Shr<$T> for $T {
202            type Output = $T;
203            #[inline]
204            fn shr(self, other: Self) -> Self {
205                // TODO: Needs review
206                $T(self.0 >> other.0)
207            }
208        }
209
210        impl ::core::ops::BitAnd<$T> for $T {
211            type Output = $T;
212            #[inline]
213            fn bitand(self, other: Self) -> Self {
214                $T(self.0 & other.0)
215            }
216        }
217
218        impl ::core::ops::BitOr<$T> for $T {
219            type Output = $T;
220            #[inline]
221            fn bitor(self, other: Self) -> Self {
222                $T(self.0 | other.0)
223            }
224        }
225
226        impl ::core::ops::BitXor<$T> for $T {
227            type Output = $T;
228            #[inline]
229            fn bitxor(self, other: Self) -> Self {
230                $T(self.0 ^ other.0)
231            }
232        }
233
234        impl_froms!($T: $Rep, $($rest)*);
235    };
236}
237
238pub mod i11 {
239    new_sample_type!(I11: i16, eq: 0, min: -1024, max: 1023, total: 2048,
240                     from: i8, u8);
241    impl_neg!(I11);
242}
243
244pub mod u11 {
245    new_sample_type!(U11: i16, eq: 1024, min: 0, max: 2047, total: 2048,
246                     from: u8);
247    impl_neg!(U11);
248}
249
250pub mod i20 {
251    use super::{I11, U11};
252    new_sample_type!(I20: i32, eq: 0, min: -524_288, max: 524_287, total: 1_048_576,
253                     from: i8, {I11:i16}, i16, u8, {U11:i16}, u16);
254}
255
256pub mod u20 {
257    new_sample_type!(U20: i32, eq: 524_288, min: 0, max: 1_048_575, total: 1_048_576,
258                     from: u8, u16);
259}
260
261pub mod i24 {
262    use super::{I20, U20};
263    new_sample_type!(I24: i32, eq: 0, min: -8_388_608, max: 8_388_607, total: 16_777_216,
264                     from: i8, i16, {I20:i32}, u8, u16, {U20:i32});
265    impl_neg!(I24);
266}
267
268pub mod u24 {
269    use super::U20;
270    new_sample_type!(U24: i32, eq: 8_388_608, min: 0, max: 16_777_215, total: 16_777_216,
271                     from: u8, u16, {U20:i32});
272}
273
274pub mod i48 {
275    use super::{I20, I24, U20, U24};
276    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,
277                     from: i8, i16, {I20:i32}, {I24:i32}, i32, u8, u16, {U20:i32}, {U24:i32}, u32);
278    impl_neg!(I48);
279}
280
281pub mod u48 {
282    use super::{U20, U24};
283    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,
284                     from: u8, u16, {U20:i32}, {U24:i32}, u32);
285}