1pub trait AudioSample: Copy + Send + Default + 'static {
12 #[inline(always)]
14 fn silence() -> Self {
15 Self::default()
16 }
17 fn max_pos_amplitude() -> Self;
18 fn max_neg_amplitude() -> Self;
19}
20
21pub trait FromSample<S> {
23 fn from_sample(other: S) -> Self;
25}
26
27pub trait IntoSample<S> {
29 fn into_sample(self) -> S;
31}
32
33pub trait SampleDelta: Copy + Default {
35 fn sample_delta(self, after: Self) -> Option<Self>;
37}
38
39pub trait MulNorm {
41 fn saturating_add(self, other: Self) -> Self;
45 fn mul_norm(self, other: Self) -> Self;
49}
50
51impl SampleDelta for f32 {
52 #[inline]
53 fn sample_delta(self, after: f32) -> Option<f32> {
54 let delta = after - self;
55 if delta.abs() > core::f32::EPSILON {
56 Some(delta)
57 }
58 else {
59 None
60 }
61 }
62}
63
64macro_rules! impl_sample_delta_int {
65 ($ty:ty) => {
66 impl SampleDelta for $ty {
67 #[inline]
68 fn sample_delta(self, after: $ty) -> Option<$ty> {
69 let delta = after - self;
70 if delta != 0 {
71 Some(delta)
72 }
73 else {
74 None
75 }
76 }
77 }
78 };
79}
80
81impl_sample_delta_int!(i16);
82impl_sample_delta_int!(i32);
83
84impl AudioSample for f32 {
85 #[inline(always)] fn max_pos_amplitude() -> Self { 1.0 }
86 #[inline(always)] fn max_neg_amplitude() -> Self { -1.0 }
87}
88impl AudioSample for i16 {
89 #[inline(always)] fn max_pos_amplitude() -> Self { i16::max_value() }
90 #[inline(always)] fn max_neg_amplitude() -> Self { i16::min_value() }
91}
92impl AudioSample for i8 {
93 #[inline(always)] fn max_pos_amplitude() -> Self { i8::max_value() }
94 #[inline(always)] fn max_neg_amplitude() -> Self { i8::min_value() }
95}
96impl AudioSample for u16 {
97 #[inline(always)]
98 fn silence() -> Self {
99 0x8000
100 }
101 #[inline(always)] fn max_pos_amplitude() -> Self { u16::max_value() }
102 #[inline(always)] fn max_neg_amplitude() -> Self { 0 }
103}
104impl AudioSample for u8 {
105 #[inline(always)]
106 fn silence() -> Self {
107 0x80
108 }
109 #[inline(always)] fn max_pos_amplitude() -> Self { u8::max_value() }
110 #[inline(always)] fn max_neg_amplitude() -> Self { 0 }
111}
112
113impl<S: FromSample<T>, T> IntoSample<S> for T {
114 #[inline]
115 fn into_sample(self) -> S {
116 S::from_sample(self)
117 }
118}
119
120impl<T: AudioSample> FromSample<T> for T {
121 #[inline(always)]
122 fn from_sample(other: T) -> T {
123 other
124 }
125}
126
127macro_rules! impl_from_sample {
128 ($int:ty, $uint:ty, $ft:ty) => {
129 impl FromSample<$int> for $ft {
130 #[inline]
131 fn from_sample(other: $int) -> $ft {
132 if other < 0 {
133 other as $ft / -(<$int>::min_value() as $ft)
134 } else {
135 other as $ft / <$int>::max_value() as $ft
136 }
137 }
138 }
139
140 impl FromSample<$ft> for $int {
141 #[inline]
142 fn from_sample(other: $ft) -> $int {
143 if other >= 0.0 {
144 (other * <$int>::max_value() as $ft) as $int
145 } else {
146 (-other * <$int>::min_value() as $ft) as $int
147 }
148 }
149 }
150
151 impl FromSample<$uint> for $ft {
152 #[inline]
153 fn from_sample(other: $uint) -> $ft {
154 <$ft>::from_sample(<$int>::from_sample(other))
155 }
156 }
157
158 impl FromSample<$uint> for $int {
159 #[inline]
160 fn from_sample(other: $uint) -> $int {
161 other.wrapping_sub(<$int>::min_value() as $uint) as $int
162 }
163 }
164
165 impl FromSample<$int> for $uint {
166 #[inline]
167 fn from_sample(other: $int) -> $uint {
168 other.wrapping_sub(<$int>::min_value()) as $uint
169 }
170 }
171
172 impl FromSample<$ft> for $uint {
173 #[inline]
174 fn from_sample(other: $ft) -> $uint {
175 <$uint>::from_sample(<$int>::from_sample(other))
176 }
177 }
178
179 };
180}
181
182impl_from_sample!(i8, u8, f32);
183impl_from_sample!(i16, u16, f32);
184
185impl MulNorm for f32 {
186 fn saturating_add(self, other: f32) -> f32 {
187 (self + other).clamp(-1.0, 1.0)
188 }
189
190 fn mul_norm(self, other: f32) -> f32 {
191 self * other
192 }
193}
194
195impl MulNorm for i16 {
196 fn saturating_add(self, other: i16) -> i16 {
197 self.saturating_add(other)
198 }
199
200 fn mul_norm(self, other: i16) -> i16 {
201 ((self as i32 * other as i32) >> 15) as i16
202 }
203}
204
205impl MulNorm for i32 {
206 fn saturating_add(self, other: i32) -> i32 {
207 self.saturating_add(other)
208 }
209
210 fn mul_norm(self, other: i32) -> i32 {
211 ((self as i64 * other as i64) >> 31) as i32
212 }
213}
214
215#[cfg(test)]
216mod test {
217 use super::*;
218
219 #[test]
220 fn i16_from_i16() {
221 for (f, t) in vec![(0i16, 0i16), (123, 123), (-456, -456), (32767, 32767), (-32768, -32768)] {
222 assert_eq!(i16::from_sample(f), t);
223 assert_eq!(IntoSample::<i16>::into_sample(f), t);
224 }
225 }
226
227 #[test]
228 fn i16_from_u16() {
229 for (f, t) in vec![(32768u16, 0i16), (32769, 1), (16384, -16384), (65535, 32767), (0, -32768)] {
230 assert_eq!(i16::from_sample(f), t);
231 assert_eq!(IntoSample::<i16>::into_sample(f), t);
232 }
233 }
234
235 #[test]
236 fn i16_from_f32() {
237 for (f, t) in vec![(0.0f32, 0i16), (1.0/32767.0, 1), (-0.5, -16384), (1.0, 32767), (-1.0, -32768)] {
238 assert_eq!(i16::from_sample(f), t);
239 assert_eq!(IntoSample::<i16>::into_sample(f), t);
240 }
241 }
242
243 #[test]
244 fn u16_from_i16() {
245 for (f, t) in vec![(0i16, 32768u16), (1, 32769), (-16384, 16384), (32767, 65535), (-32768, 0)] {
246 assert_eq!(u16::from_sample(f), t);
247 assert_eq!(IntoSample::<u16>::into_sample(f), t);
248 }
249 }
250
251 #[test]
252 fn u16_from_u16() {
253 for (f, t) in vec![(32768u16, 32768u16), (32769, 32769), (16384, 16384), (65535, 65535), (0, 0)] {
254 assert_eq!(u16::from_sample(f), t);
255 assert_eq!(IntoSample::<u16>::into_sample(f), t);
256 }
257 }
258
259 #[test]
260 fn u16_from_f32() {
261 for (f, t) in vec![(0.0f32, 32768u16), (1.0/32767.0, 32769), (-0.5, 16384), (1.0, 65535), (-1.0, 0)] {
262 assert_eq!(u16::from_sample(f), t);
263 assert_eq!(IntoSample::<u16>::into_sample(f), t);
264 }
265 }
266
267 #[test]
268 fn f32_from_i16() {
269 for (f, t) in vec![(0i16, 0.0f32), (1, 1.0/32767.0), (-16384, -0.5), (32767, 1.0), (-32768, -1.0)] {
270 assert_eq!(f32::from_sample(f), t);
271 assert_eq!(IntoSample::<f32>::into_sample(f), t);
272 }
273 }
274
275 #[test]
276 fn f32_from_u16() {
277 for (f, t) in vec![(32768u16, 0.0f32), (32769, 1.0/32767.0), (16384, -0.5), (65535, 1.0), (0, -1.0)] {
278 assert_eq!(f32::from_sample(f), t);
279 assert_eq!(IntoSample::<f32>::into_sample(f), t);
280 }
281 }
282
283 #[test]
284 fn f32_from_f32() {
285 for (f, t) in vec![(0.0f32, 0.0f32), (-0.5, -0.5), (0.5, 0.5), (1.0, 1.0), (-1.0, -1.0)] {
286 assert_eq!(f32::from_sample(f), t);
287 assert_eq!(IntoSample::<f32>::into_sample(f), t);
288 }
289 }
290}