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