1 | //! Pure functions and traits for converting between i8, i16, I24, i32, I48, i64, u8, u16, U24, |
2 | //! u32, U48, u64, f32 and f64. |
3 | //! |
4 | //! Each conversion function is performance focused, memory-sensitive and expects that the user has |
5 | //! validated their input prior to the function call. |
6 | //! |
7 | //! No conversion function will ever cast to a type with a size in bytes larger than the largest |
8 | //! between the source and target sample types. |
9 | //! |
10 | //! The conversion functions do *not* check the range of incoming values for floating point values |
11 | //! or any of the custom `I24`, `U24`, `I48` and `U48` types. |
12 | //! |
13 | //! Note that floating point conversions use the range -1.0 <= v < 1.0: |
14 | //! `(1.0 as f64).to_sample::<i16>()` will overflow! |
15 | |
16 | use crate::types::{I24, I48, U24, U48}; |
17 | |
18 | macro_rules! conversion_fn { |
19 | ($Rep:ty, $s:ident to_i8 { $body:expr }) => { |
20 | #[inline] |
21 | pub fn to_i8($s: $Rep) -> i8 { |
22 | $body |
23 | } |
24 | }; |
25 | |
26 | ($Rep:ty, $s:ident to_i16 { $body:expr }) => { |
27 | #[inline] |
28 | pub fn to_i16($s: $Rep) -> i16 { |
29 | $body |
30 | } |
31 | }; |
32 | |
33 | ($Rep:ty, $s:ident to_i24 { $body:expr }) => { |
34 | #[inline] |
35 | pub fn to_i24($s: $Rep) -> I24 { |
36 | $body |
37 | } |
38 | }; |
39 | |
40 | ($Rep:ty, $s:ident to_i32 { $body:expr }) => { |
41 | #[inline] |
42 | pub fn to_i32($s: $Rep) -> i32 { |
43 | $body |
44 | } |
45 | }; |
46 | |
47 | ($Rep:ty, $s:ident to_i48 { $body:expr }) => { |
48 | #[inline] |
49 | pub fn to_i48($s: $Rep) -> I48 { |
50 | $body |
51 | } |
52 | }; |
53 | |
54 | ($Rep:ty, $s:ident to_i64 { $body:expr }) => { |
55 | #[inline] |
56 | pub fn to_i64($s: $Rep) -> i64 { |
57 | $body |
58 | } |
59 | }; |
60 | |
61 | ($Rep:ty, $s:ident to_u8 { $body:expr }) => { |
62 | #[inline] |
63 | pub fn to_u8($s: $Rep) -> u8 { |
64 | $body |
65 | } |
66 | }; |
67 | |
68 | ($Rep:ty, $s:ident to_u16 { $body:expr }) => { |
69 | #[inline] |
70 | pub fn to_u16($s: $Rep) -> u16 { |
71 | $body |
72 | } |
73 | }; |
74 | |
75 | ($Rep:ty, $s:ident to_u24 { $body:expr }) => { |
76 | #[inline] |
77 | pub fn to_u24($s: $Rep) -> U24 { |
78 | $body |
79 | } |
80 | }; |
81 | |
82 | ($Rep:ty, $s:ident to_u32 { $body:expr }) => { |
83 | #[inline] |
84 | pub fn to_u32($s: $Rep) -> u32 { |
85 | $body |
86 | } |
87 | }; |
88 | |
89 | ($Rep:ty, $s:ident to_u48 { $body:expr }) => { |
90 | #[inline] |
91 | pub fn to_u48($s: $Rep) -> U48 { |
92 | $body |
93 | } |
94 | }; |
95 | |
96 | ($Rep:ty, $s:ident to_u64 { $body:expr }) => { |
97 | #[inline] |
98 | pub fn to_u64($s: $Rep) -> u64 { |
99 | $body |
100 | } |
101 | }; |
102 | |
103 | ($Rep:ty, $s:ident to_f32 { $body:expr }) => { |
104 | #[inline] |
105 | pub fn to_f32($s: $Rep) -> f32 { |
106 | $body |
107 | } |
108 | }; |
109 | |
110 | ($Rep:ty, $s:ident to_f64 { $body:expr }) => { |
111 | #[inline] |
112 | pub fn to_f64($s: $Rep) -> f64 { |
113 | $body |
114 | } |
115 | }; |
116 | } |
117 | |
118 | macro_rules! conversion_fns { |
119 | ($Rep:ty, $s:ident $fn_name:tt { $body:expr } $($rest:tt)*) => { |
120 | conversion_fn!($Rep, $s $fn_name { $body }); |
121 | conversion_fns!($Rep, $($rest)*); |
122 | }; |
123 | ($Rep:ty, ) => {}; |
124 | } |
125 | |
126 | macro_rules! conversions { |
127 | ($T:ident, $mod_name:ident { $($rest:tt)* }) => { |
128 | pub mod $mod_name { |
129 | use $crate::types::{I24, U24, I48, U48}; |
130 | conversion_fns!($T, $($rest)*); |
131 | } |
132 | }; |
133 | } |
134 | |
135 | conversions!(i8, i8 { |
136 | s to_i16 { (s as i16) << 8 } |
137 | s to_i24 { I24::new_unchecked((s as i32) << 16) } |
138 | s to_i32 { (s as i32) << 24 } |
139 | s to_i48 { I48::new_unchecked((s as i64) << 40) } |
140 | s to_i64 { (s as i64) << 56 } |
141 | s to_u8 { |
142 | if s < 0 { |
143 | // 128i8 overflows, so we must use 127 + 1 instead. |
144 | (s + 127 + 1) as u8 |
145 | } else { |
146 | (s as u8) + 128 |
147 | } |
148 | } |
149 | s to_u16 { |
150 | if s < 0 { |
151 | ((s + 127 + 1) as u16) << 8 |
152 | } else { |
153 | (s as u16 + 128) << 8 |
154 | } |
155 | } |
156 | s to_u24 { |
157 | U24::new_unchecked((s as i32 + 128) << 16) |
158 | } |
159 | s to_u32 { |
160 | if s < 0 { |
161 | ((s + 127 + 1) as u32) << 24 |
162 | } else { |
163 | (s as u32 + 128) << 24 |
164 | } |
165 | } |
166 | s to_u48 { |
167 | U48::new_unchecked((s as i64 + 128) << 40) |
168 | } |
169 | s to_u64 { |
170 | if s < 0 { |
171 | ((s + 127 + 1) as u64) << 56 |
172 | } else { |
173 | (s as u64 + 128) << 56 |
174 | } |
175 | } |
176 | s to_f32 { |
177 | s as f32 / 128.0 |
178 | } |
179 | s to_f64 { |
180 | s as f64 / 128.0 |
181 | } |
182 | }); |
183 | |
184 | conversions!(i16, i16 { |
185 | s to_i8 { (s >> 8) as i8 } |
186 | s to_i24 { I24::new_unchecked((s as i32) << 8) } |
187 | s to_i32 { (s as i32) << 16 } |
188 | s to_i48 { I48::new_unchecked((s as i64) << 32) } |
189 | s to_i64 { (s as i64) << 48 } |
190 | s to_u8 { |
191 | super::i8::to_u8(to_i8(s)) |
192 | } |
193 | s to_u16 { |
194 | if s < 0 { |
195 | // 32_768i16 overflows, so we must use + 1 instead. |
196 | (s + 32_767 + 1) as u16 |
197 | } else { |
198 | s as u16 + 32_768 |
199 | } |
200 | } |
201 | s to_u24 { |
202 | if s < 0 { |
203 | U24::new_unchecked(((s + 32_767 + 1) as i32) << 8) |
204 | } else { |
205 | U24::new_unchecked((s as i32 + 32_768) << 8) |
206 | } |
207 | } |
208 | s to_u32 { |
209 | if s < 0 { |
210 | ((s + 32_767 + 1) as u32) << 16 |
211 | } else { |
212 | ((s as u32) + 32_768) << 16 |
213 | } |
214 | } |
215 | s to_u48 { |
216 | if s < 0 { |
217 | U48::new_unchecked(((s + 32_767 + 1) as i64) << 32) |
218 | } else { |
219 | U48::new_unchecked((s as i64 + 32_768) << 32) |
220 | } |
221 | } |
222 | s to_u64 { |
223 | if s < 0 { |
224 | ((s + 32_767 + 1) as u64) << 48 |
225 | } else { |
226 | ((s as u64) + 32_768) << 48 |
227 | } |
228 | } |
229 | s to_f32 { |
230 | s as f32 / 32_768.0 |
231 | } |
232 | s to_f64 { |
233 | s as f64 / 32_768.0 |
234 | } |
235 | }); |
236 | |
237 | conversions!(I24, i24 { |
238 | s to_i8 { (s.inner() >> 16) as i8 } |
239 | s to_i16 { (s.inner() >> 8) as i16 } |
240 | s to_i32 { s.inner() << 8 } |
241 | s to_i48 { I48::new_unchecked((s.inner() as i64) << 24) } |
242 | s to_i64 { (s.inner() as i64) << 40 } |
243 | s to_u8 { |
244 | super::i8::to_u8(to_i8(s)) |
245 | } |
246 | s to_u16 { |
247 | super::i16::to_u16(to_i16(s)) |
248 | } |
249 | s to_u24 { |
250 | U24::new_unchecked(s.inner() + 8_388_608) |
251 | } |
252 | s to_u32 { |
253 | ((s.inner() + 8_388_608) as u32) << 8 |
254 | } |
255 | s to_u48 { |
256 | U48::new_unchecked((s.inner() as i64 + 8_388_608) << 24) |
257 | } |
258 | s to_u64 { |
259 | ((s.inner() + 8_388_608) as u64) << 40 |
260 | } |
261 | s to_f32 { |
262 | s.inner() as f32 / 8_388_608.0 |
263 | } |
264 | s to_f64 { |
265 | s.inner() as f64 / 8_388_608.0 |
266 | } |
267 | }); |
268 | |
269 | conversions!(i32, i32 { |
270 | s to_i8 { (s >> 24) as i8 } |
271 | s to_i16 { (s >> 16) as i16 } |
272 | s to_i24 { I24::new_unchecked(s >> 8) } |
273 | s to_i48 { I48::new_unchecked((s as i64) << 16) } |
274 | s to_i64 { (s as i64) << 32 } |
275 | s to_u8 { |
276 | super::i8::to_u8(to_i8(s)) |
277 | } |
278 | s to_u16 { |
279 | super::i16::to_u16(to_i16(s)) |
280 | } |
281 | s to_u24 { |
282 | super::i24::to_u24(to_i24(s)) |
283 | } |
284 | s to_u32 { |
285 | if s < 0 { |
286 | (s + 2_147_483_647 + 1) as u32 |
287 | } else { |
288 | s as u32 + 2_147_483_648 |
289 | } |
290 | } |
291 | s to_u48 { |
292 | U48::new_unchecked((s as i64 + 2_147_483_648) << 16) |
293 | } |
294 | s to_u64 { |
295 | if s < 0 { |
296 | ((s + 2_147_483_647 + 1) as u64) << 32 |
297 | } else { |
298 | (s as u64) + 2_147_483_648 << 32 |
299 | } |
300 | } |
301 | s to_f32 { |
302 | s as f32 / 2_147_483_648.0 |
303 | } |
304 | s to_f64 { |
305 | s as f64 / 2_147_483_648.0 |
306 | } |
307 | }); |
308 | |
309 | conversions!(I48, i48 { |
310 | s to_i8 { (s.inner() >> 40) as i8 } |
311 | s to_i16 { (s.inner() >> 32) as i16 } |
312 | s to_i24 { I24::new_unchecked((s.inner() >> 24) as i32) } |
313 | s to_i32 { (s.inner() >> 16) as i32 } |
314 | s to_i64 { s.inner() << 16 } |
315 | s to_u8 { |
316 | super::i8::to_u8(to_i8(s)) |
317 | } |
318 | s to_u16 { |
319 | super::i16::to_u16(to_i16(s)) |
320 | } |
321 | s to_u24 { |
322 | super::i24::to_u24(to_i24(s)) |
323 | } |
324 | s to_u32 { |
325 | super::i32::to_u32(to_i32(s)) |
326 | } |
327 | s to_u48 { |
328 | U48::new_unchecked(s.inner() + 140_737_488_355_328) |
329 | } |
330 | s to_u64 { |
331 | ((s.inner() + 140_737_488_355_328) as u64) << 16 |
332 | } |
333 | s to_f32 { |
334 | s.inner() as f32 / 140_737_488_355_328.0 |
335 | } |
336 | s to_f64 { |
337 | s.inner() as f64 / 140_737_488_355_328.0 |
338 | } |
339 | }); |
340 | |
341 | conversions!(i64, i64 { |
342 | s to_i8 { (s >> 56) as i8 } |
343 | s to_i16 { (s >> 48) as i16 } |
344 | s to_i24 { I24::new_unchecked((s >> 40) as i32) } |
345 | s to_i32 { (s >> 32) as i32 } |
346 | s to_i48 { I48::new_unchecked(s >> 16) } |
347 | s to_u8 { |
348 | super::i8::to_u8(to_i8(s)) |
349 | } |
350 | s to_u16 { |
351 | super::i16::to_u16(to_i16(s)) |
352 | } |
353 | s to_u24 { |
354 | super::i24::to_u24(to_i24(s)) |
355 | } |
356 | s to_u32 { |
357 | super::i32::to_u32(to_i32(s)) |
358 | } |
359 | s to_u48 { |
360 | super::i48::to_u48(to_i48(s)) |
361 | } |
362 | s to_u64 { |
363 | if s < 0 { |
364 | (s + 9_223_372_036_854_775_807 + 1) as u64 |
365 | } else { |
366 | s as u64 + 9_223_372_036_854_775_808 |
367 | } |
368 | } |
369 | s to_f32 { |
370 | s as f32 / 9_223_372_036_854_775_808.0 |
371 | } |
372 | s to_f64 { |
373 | s as f64 / 9_223_372_036_854_775_808.0 |
374 | } |
375 | }); |
376 | |
377 | conversions!(u8, u8 { |
378 | s to_i8 { |
379 | if s < 128 { |
380 | s as i8 - 127 - 1 |
381 | } else { |
382 | (s - 128) as i8 |
383 | } |
384 | } |
385 | s to_i16 { |
386 | (s as i16 - 128) << 8 |
387 | } |
388 | s to_i24 { |
389 | I24::new_unchecked((s as i32 - 128) << 16) |
390 | } |
391 | s to_i32 { |
392 | (s as i32 - 128) << 24 |
393 | } |
394 | s to_i48 { |
395 | I48::new_unchecked((s as i64 - 128) << 40) |
396 | } |
397 | s to_i64 { |
398 | (s as i64 - 128) << 56 |
399 | } |
400 | s to_u16 { (s as u16) << 8 } |
401 | s to_u24 { U24::new_unchecked((s as i32) << 16) } |
402 | s to_u32 { (s as u32) << 24 } |
403 | s to_u48 { U48::new_unchecked((s as i64) << 40) } |
404 | s to_u64 { (s as u64) << 56 } |
405 | s to_f32 { super::i8::to_f32(to_i8(s)) } |
406 | s to_f64 { super::i8::to_f64(to_i8(s)) } |
407 | }); |
408 | |
409 | conversions!(u16, u16 { |
410 | s to_i8 { super::u8::to_i8(to_u8(s)) } |
411 | s to_i16 { |
412 | if s < 32_768 { |
413 | s as i16 - 32_767 - 1 |
414 | } else { |
415 | (s - 32_768) as i16 |
416 | } |
417 | } |
418 | s to_i24 { |
419 | I24::new_unchecked((s as i32 - 32_768) << 8) |
420 | } |
421 | s to_i32 { |
422 | (s as i32 - 32_768) << 16 |
423 | } |
424 | s to_i48 { |
425 | I48::new_unchecked((s as i64 - 32_768) << 32) |
426 | } |
427 | s to_i64 { |
428 | (s as i64 - 32_768) << 48 |
429 | } |
430 | s to_u8 { (s >> 8) as u8 } |
431 | s to_u24 { U24::new_unchecked((s as i32) << 8) } |
432 | s to_u32 { (s as u32) << 16 } |
433 | s to_u48 { U48::new_unchecked((s as i64) << 32) } |
434 | s to_u64 { (s as u64) << 48 } |
435 | s to_f32 { super::i16::to_f32(to_i16(s)) } |
436 | s to_f64 { super::i16::to_f64(to_i16(s)) } |
437 | }); |
438 | |
439 | conversions!(U24, u24 { |
440 | s to_i8 { super::u8::to_i8(to_u8(s)) } |
441 | s to_i16 { super::u16::to_i16(to_u16(s)) } |
442 | s to_i24 { |
443 | I24::new_unchecked(s.inner() - 8_388_608) |
444 | } |
445 | s to_i32 { |
446 | (s.inner() - 8_388_608) << 8 |
447 | } |
448 | s to_i48 { |
449 | I48::new_unchecked(((s.inner() as i64) - 8_388_608) << 24) |
450 | } |
451 | s to_i64 { |
452 | (s.inner() as i64 - 8_388_608) << 40 |
453 | } |
454 | s to_u8 { (s.inner() >> 16) as u8 } |
455 | s to_u16 { (s.inner() >> 8) as u16 } |
456 | s to_u32 { (s.inner() as u32) << 8 } |
457 | s to_u48 { U48::new_unchecked((s.inner() as i64) << 24) } |
458 | s to_u64 { (s.inner() as u64) << 40 } |
459 | s to_f32 { super::i24::to_f32(to_i24(s)) } |
460 | s to_f64 { super::i24::to_f64(to_i24(s)) } |
461 | }); |
462 | |
463 | conversions!(u32, u32 { |
464 | s to_i8 { super::u8::to_i8(to_u8(s)) } |
465 | s to_i16 { super::u16::to_i16(to_u16(s)) } |
466 | s to_i24 { super::u24::to_i24(to_u24(s)) } |
467 | s to_i32 { |
468 | if s < 2_147_483_648 { |
469 | s as i32 - 2_147_483_647 - 1 |
470 | } else { |
471 | (s - 2_147_483_648) as i32 |
472 | } |
473 | } |
474 | s to_i48 { |
475 | I48::new_unchecked((s as i64 - 2_147_483_648) << 16) |
476 | } |
477 | s to_i64 { |
478 | (s as i64 - 2_147_483_648) << 32 |
479 | } |
480 | s to_u8 { (s >> 24) as u8 } |
481 | s to_u16 { (s >> 16) as u16 } |
482 | s to_u24 { U24::new_unchecked((s >> 8) as i32) } |
483 | s to_u48 { U48::new_unchecked((s as i64) << 16) } |
484 | s to_u64 { (s as u64) << 32 } |
485 | s to_f32 { super::i32::to_f32(to_i32(s)) } |
486 | s to_f64 { super::i32::to_f64(to_i32(s)) } |
487 | }); |
488 | |
489 | conversions!(U48, u48 { |
490 | s to_i8 { super::u8::to_i8(to_u8(s)) } |
491 | s to_i16 { super::u16::to_i16(to_u16(s)) } |
492 | s to_i24 { super::u24::to_i24(to_u24(s)) } |
493 | s to_i32 { super::u32::to_i32(to_u32(s)) } |
494 | s to_i48 { |
495 | I48::new_unchecked(s.inner() - 140_737_488_355_328) |
496 | } |
497 | s to_i64 { |
498 | (s.inner() - 140_737_488_355_328) << 16 |
499 | } |
500 | s to_u8 { (s.inner() >> 40) as u8 } |
501 | s to_u16 { (s.inner() >> 32) as u16 } |
502 | s to_u24 { U24::new_unchecked((s.inner() >> 24) as i32) } |
503 | s to_u32 { (s.inner() >> 16) as u32 } |
504 | s to_u64 { (s.inner() as u64) << 16 } |
505 | s to_f32 { super::i48::to_f32(to_i48(s)) } |
506 | s to_f64 { super::i48::to_f64(to_i48(s)) } |
507 | }); |
508 | |
509 | conversions!(u64, u64 { |
510 | s to_i8 { super::u8::to_i8(to_u8(s)) } |
511 | s to_i16 { super::u16::to_i16(to_u16(s)) } |
512 | s to_i24 { super::u24::to_i24(to_u24(s)) } |
513 | s to_i32 { super::u32::to_i32(to_u32(s)) } |
514 | s to_i48 { super::u48::to_i48(to_u48(s)) } |
515 | s to_i64 { |
516 | if s < 9_223_372_036_854_775_808 { |
517 | s as i64 - 9_223_372_036_854_775_807 - 1 |
518 | } else { |
519 | (s - 9_223_372_036_854_775_808) as i64 |
520 | } |
521 | } |
522 | s to_u8 { (s >> 56) as u8 } |
523 | s to_u16 { (s >> 48) as u16 } |
524 | s to_u24 { U24::new_unchecked((s >> 40) as i32) } |
525 | s to_u32 { (s >> 32) as u32 } |
526 | s to_u48 { U48::new_unchecked((s >> 16) as i64) } |
527 | s to_f32 { super::i64::to_f32(to_i64(s)) } |
528 | s to_f64 { super::i64::to_f64(to_i64(s)) } |
529 | }); |
530 | |
531 | // The following conversions assume `-1.0 <= s < 1.0` (note that +1.0 is excluded) and will |
532 | // overflow otherwise. |
533 | conversions!(f32, f32 { |
534 | s to_i8 { (s * 128.0) as i8 } |
535 | s to_i16 { (s * 32_768.0) as i16 } |
536 | s to_i24 { I24::new_unchecked((s * 8_388_608.0) as i32) } |
537 | s to_i32 { (s * 2_147_483_648.0) as i32 } |
538 | s to_i48 { I48::new_unchecked((s * 140_737_488_355_328.0) as i64) } |
539 | s to_i64 { (s * 9_223_372_036_854_775_808.0) as i64 } |
540 | s to_u8 { super::i8::to_u8(to_i8(s)) } |
541 | s to_u16 { super::i16::to_u16(to_i16(s)) } |
542 | s to_u24 { super::i24::to_u24(to_i24(s)) } |
543 | s to_u32 { super::i32::to_u32(to_i32(s)) } |
544 | s to_u48 { super::i48::to_u48(to_i48(s)) } |
545 | s to_u64 { super::i64::to_u64(to_i64(s)) } |
546 | s to_f64 { s as f64 } |
547 | }); |
548 | |
549 | // The following conversions assume `-1.0 <= s < 1.0` (note that +1.0 is excluded) and will |
550 | // overflow otherwise. |
551 | conversions!(f64, f64 { |
552 | s to_i8 { (s * 128.0) as i8 } |
553 | s to_i16 { (s * 32_768.0) as i16 } |
554 | s to_i24 { I24::new_unchecked((s * 8_388_608.0) as i32) } |
555 | s to_i32 { (s * 2_147_483_648.0) as i32 } |
556 | s to_i48 { I48::new_unchecked((s * 140_737_488_355_328.0) as i64) } |
557 | s to_i64 { (s * 9_223_372_036_854_775_808.0) as i64 } |
558 | s to_u8 { super::i8::to_u8(to_i8(s)) } |
559 | s to_u16 { super::i16::to_u16(to_i16(s)) } |
560 | s to_u24 { super::i24::to_u24(to_i24(s)) } |
561 | s to_u32 { super::i32::to_u32(to_i32(s)) } |
562 | s to_u48 { super::i48::to_u48(to_i48(s)) } |
563 | s to_u64 { super::i64::to_u64(to_i64(s)) } |
564 | s to_f32 { s as f32 } |
565 | }); |
566 | |
567 | /// Similar to the std `From` trait, but specifically for converting between sample types. |
568 | /// |
569 | /// We use this trait to be generic over the `Sample::to_sample` and `Sample::from_sample` methods. |
570 | pub trait FromSample<S> { |
571 | fn from_sample_(s: S) -> Self; |
572 | } |
573 | |
574 | impl<S> FromSample<S> for S { |
575 | #[inline ] |
576 | fn from_sample_(s: S) -> Self { |
577 | s |
578 | } |
579 | } |
580 | |
581 | /// Implement the `FromSample` trait for the given types. |
582 | macro_rules! impl_from_sample { |
583 | ($T:ty, $fn_name:ident from $({$U:ident: $Umod:ident})*) => { |
584 | $( |
585 | impl FromSample<$U> for $T { |
586 | #[inline] |
587 | fn from_sample_(s: $U) -> Self { |
588 | self::$Umod::$fn_name(s) |
589 | } |
590 | } |
591 | )* |
592 | }; |
593 | } |
594 | |
595 | impl_from_sample! {i8, to_i8 from |
596 | {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
597 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
598 | {f32:f32} {f64:f64} |
599 | } |
600 | |
601 | impl_from_sample! {i16, to_i16 from |
602 | {i8:i8} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
603 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
604 | {f32:f32} {f64:f64} |
605 | } |
606 | |
607 | impl_from_sample! {I24, to_i24 from |
608 | {i8:i8} {i16:i16} {i32:i32} {I48:i48} {i64:i64} |
609 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
610 | {f32:f32} {f64:f64} |
611 | } |
612 | |
613 | impl_from_sample! {i32, to_i32 from |
614 | {i8:i8} {i16:i16} {I24:i24} {I48:i48} {i64:i64} |
615 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
616 | {f32:f32} {f64:f64} |
617 | } |
618 | |
619 | impl_from_sample! {I48, to_i48 from |
620 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {i64:i64} |
621 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
622 | {f32:f32} {f64:f64} |
623 | } |
624 | |
625 | impl_from_sample! {i64, to_i64 from |
626 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} |
627 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
628 | {f32:f32} {f64:f64} |
629 | } |
630 | |
631 | impl_from_sample! {u8, to_u8 from |
632 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
633 | {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
634 | {f32:f32} {f64:f64} |
635 | } |
636 | |
637 | impl_from_sample! {u16, to_u16 from |
638 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
639 | {u8:u8} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
640 | {f32:f32} {f64:f64} |
641 | } |
642 | |
643 | impl_from_sample! {U24, to_u24 from |
644 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
645 | {u8:u8} {u16:u16} {u32:u32} {U48:u48} {u64:u64} |
646 | {f32:f32} {f64:f64} |
647 | } |
648 | |
649 | impl_from_sample! {u32, to_u32 from |
650 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
651 | {u8:u8} {u16:u16} {U24:u24} {U48:u48} {u64:u64} |
652 | {f32:f32} {f64:f64} |
653 | } |
654 | |
655 | impl_from_sample! {U48, to_u48 from |
656 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
657 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {u64:u64} |
658 | {f32:f32} {f64:f64} |
659 | } |
660 | |
661 | impl_from_sample! {u64, to_u64 from |
662 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
663 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} |
664 | {f32:f32} {f64:f64} |
665 | } |
666 | |
667 | impl_from_sample! {f32, to_f32 from |
668 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
669 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
670 | {f64:f64} |
671 | } |
672 | |
673 | impl_from_sample! {f64, to_f64 from |
674 | {i8:i8} {i16:i16} {I24:i24} {i32:i32} {I48:i48} {i64:i64} |
675 | {u8:u8} {u16:u16} {U24:u24} {u32:u32} {U48:u48} {u64:u64} |
676 | {f32:f32} |
677 | } |
678 | |
679 | /// Similar to the std `Into` trait, but specifically for converting between sample types. |
680 | /// |
681 | /// This trait has a blanket implementation for all types that implement |
682 | /// [`FromSample`](./trait.FromSample.html). |
683 | pub trait ToSample<S> { |
684 | fn to_sample_(self) -> S; |
685 | } |
686 | |
687 | impl<T, U> ToSample<U> for T |
688 | where |
689 | U: FromSample<T>, |
690 | { |
691 | #[inline ] |
692 | fn to_sample_(self) -> U { |
693 | U::from_sample_(self) |
694 | } |
695 | } |
696 | |
697 | /// Sample types which may be converted to and from some type `S`. |
698 | pub trait Duplex<S>: FromSample<S> + ToSample<S> {} |
699 | impl<S, T> Duplex<S> for T where T: FromSample<S> + ToSample<S> {} |
700 | |