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
16use crate::types::{I24, I48, U24, U48};
17
18macro_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
118macro_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
126macro_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
135conversions!(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
184conversions!(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
237conversions!(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
269conversions!(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
309conversions!(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
341conversions!(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
377conversions!(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
409conversions!(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
439conversions!(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
463conversions!(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
489conversions!(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
509conversions!(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.
533conversions!(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.
551conversions!(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.
570pub trait FromSample<S> {
571 fn from_sample_(s: S) -> Self;
572}
573
574impl<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.
582macro_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
595impl_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
601impl_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
607impl_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
613impl_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
619impl_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
625impl_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
631impl_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
637impl_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
643impl_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
649impl_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
655impl_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
661impl_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
667impl_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
673impl_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).
683pub trait ToSample<S> {
684 fn to_sample_(self) -> S;
685}
686
687impl<T, U> ToSample<U> for T
688where
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`.
698pub trait Duplex<S>: FromSample<S> + ToSample<S> {}
699impl<S, T> Duplex<S> for T where T: FromSample<S> + ToSample<S> {}
700