symphonia_core/
conv.rs

1// Symphonia
2// Copyright (c) 2019-2022 The Project Symphonia Developers.
3//
4// This Source Code Form is subject to the terms of the Mozilla Public
5// License, v. 2.0. If a copy of the MPL was not distributed with this
6// file, You can obtain one at https://mozilla.org/MPL/2.0/.
7
8//! The `conv` module provides methods to convert samples between different sample types (formats).
9use crate::sample::{i24, u24, Sample};
10
11pub mod dither {
12    //! The `dither` module provides methods to apply a dither to a sample.
13    //!
14    //! Dithering is the process of adding noise to the least significant digits of a sample before
15    //! down-converting (quantizing) it to a smaller sample type. The purpose of dithering is to
16    //! decorrelate the quantization error of the down-conversion from the source signal.
17    //!
18    //! Dithering is only applied on lossy conversions. Therefore the `dither` module will only
19    //! apply a dither to the following down-conversions:
20    //!
21    //! * { `i32`, `u32` } to { `i24`, `u24`, `i16`, `u16`, `i8`, `u8` }
22    //! * { `i24`, `u24` } to { `i16`, `u16`, `i8`, `u8` }
23    //! * { `i16`, `u16` } to { `i8`, `u8` }
24    //!
25    //! Multiple dithering algorithms are provided, each drawing noise from a different probability
26    //! distribution. In addition to different distributions, a dithering algorithm may also shape
27    //! the noise such that the bulk of the noise is placed in an inaudible frequency range.
28    use super::FromSample;
29    use crate::sample::Sample;
30    use crate::sample::{i24, u24};
31    use std::marker::PhantomData;
32
33    mod prng {
34        #[inline]
35        fn split_mix_64(x: &mut u64) -> u64 {
36            *x = x.wrapping_add(0x9e37_79b9_7f4a_7c15);
37            let mut z = *x;
38            z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
39            z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
40            z ^ (z >> 31)
41        }
42
43        /// `Xoshiro128pp` implements the xoshiro128++ pseudo-random number generator.
44        ///
45        /// This PRNG is the basis for all built-in dithering algorithms. It is one of, if not the
46        /// most, performant PRNGs that generate statistically valid random numbers. Note that it is
47        /// not cryptographically secure, but for dithering audio it is more than sufficient.
48        ///
49        /// `Xoshiro128pp` should be initialized with a reasonably random 64-bit seed, however the
50        /// seed will be further randomized via the SplitMix64 algorithm.
51        pub struct Xoshiro128pp {
52            s: [u32; 4],
53        }
54
55        impl Xoshiro128pp {
56            pub fn new(mut seed: u64) -> Self {
57                let a = split_mix_64(&mut seed);
58                let b = split_mix_64(&mut seed);
59
60                Xoshiro128pp {
61                    s: [
62                        (a & 0xffff_ffff) as u32,
63                        (a >> 32) as u32,
64                        (b & 0xffff_ffff) as u32,
65                        (b >> 32) as u32,
66                    ],
67                }
68            }
69
70            #[inline(always)]
71            fn rotl(x: u32, k: u32) -> u32 {
72                (x << k) | (x >> (32 - k))
73            }
74
75            #[inline]
76            pub fn next(&mut self) -> u32 {
77                let x = self.s[0].wrapping_add(self.s[3]);
78
79                let result = Xoshiro128pp::rotl(x, 7).wrapping_add(self.s[0]);
80
81                let t = self.s[1] << 9;
82
83                self.s[2] ^= self.s[0];
84                self.s[3] ^= self.s[1];
85                self.s[1] ^= self.s[2];
86                self.s[0] ^= self.s[3];
87
88                self.s[2] ^= t;
89
90                self.s[3] = Xoshiro128pp::rotl(self.s[3], 11);
91
92                result
93            }
94        }
95    }
96
97    /// `RandomNoise` represents a sample of noise of a specified length in bits.
98    ///
99    /// TODO: `RandomNoise` should be parameterized by the number of bits once const generics land.
100    #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Default)]
101    pub struct RandomNoise(pub i32);
102
103    impl RandomNoise {
104        /// Instantiate a noise sample from a random 32-bit source.
105        pub fn from(random: i32, n_bits: u32) -> Self {
106            RandomNoise(random >> (32 - n_bits))
107        }
108    }
109
110    /// `AddNoise` is a trait for converting random noise into a `Sample`.
111    pub trait AddNoise<S: Sample> {
112        fn add_noise(self, sample: S) -> S;
113    }
114
115    macro_rules! add_noise_impl {
116        ($sample_type:ty, $self:ident, $sample:ident, $conv:expr) => (
117            impl AddNoise<$sample_type> for RandomNoise {
118                #[inline]
119                fn add_noise($self, $sample: $sample_type) -> $sample_type { $conv }
120            }
121        )
122    }
123
124    add_noise_impl!(i8, self, s, {
125        i8::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
126    });
127    add_noise_impl!(u8, self, s, {
128        u8::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
129    });
130    add_noise_impl!(i16, self, s, {
131        i16::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
132    });
133    add_noise_impl!(u16, self, s, {
134        u16::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
135    });
136    add_noise_impl!(i24, self, s, {
137        i24::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
138    });
139    add_noise_impl!(u24, self, s, {
140        u24::from_sample(f32::from_sample(s) + f32::from_sample(self.0))
141    });
142    add_noise_impl!(i32, self, s, {
143        i32::from_sample(f64::from_sample(s) + f64::from_sample(self.0))
144    });
145    add_noise_impl!(u32, self, s, {
146        u32::from_sample(f64::from_sample(s) + f64::from_sample(self.0))
147    });
148    add_noise_impl!(f32, self, s, s + f32::from_sample(self.0));
149    add_noise_impl!(f64, self, s, s + f64::from_sample(self.0));
150
151    /// `Dither` is a trait for implementing dithering algorithms.
152    pub trait Dither<F: Sample, T: Sample> {
153        /// Dithers a `Sample` of source sample format `F` for an eventual conversion to the
154        /// destination sample format `T`.
155        fn dither(&mut self, sample: F) -> F;
156    }
157
158    /// The `Identity` dithering algorithm performs no dithering and returns the original sample.
159    pub struct Identity<F: Sample, T: Sample> {
160        from_type: PhantomData<F>,
161        to_type: PhantomData<T>,
162    }
163
164    impl<F: Sample, T: Sample> Identity<F, T> {
165        pub fn new() -> Self {
166            Identity { from_type: PhantomData, to_type: PhantomData }
167        }
168    }
169
170    impl<F: Sample, T: Sample> Dither<F, T> for Identity<F, T> {
171        fn dither(&mut self, sample: F) -> F {
172            sample
173        }
174    }
175
176    impl<F: Sample, T: Sample> Default for Identity<F, T> {
177        fn default() -> Self {
178            Self::new()
179        }
180    }
181
182    /// `Rectangular` implements a dither using uniformly distributed (white) noise without shaping.
183    pub struct Rectangular<F: Sample, T: Sample> {
184        prng: prng::Xoshiro128pp,
185        from_type: PhantomData<F>,
186        to_type: PhantomData<T>,
187    }
188
189    impl<F: Sample, T: Sample> Rectangular<F, T> {
190        pub fn new() -> Self {
191            Rectangular {
192                prng: prng::Xoshiro128pp::new(0xb2c1_01f4_425b_987e),
193                from_type: PhantomData,
194                to_type: PhantomData,
195            }
196        }
197    }
198
199    impl<F: Sample, T: Sample> Dither<F, T> for Rectangular<F, T>
200    where
201        RandomNoise: AddNoise<F>,
202    {
203        fn dither(&mut self, sample: F) -> F {
204            // A dither should be applied if and only if the effective number of bits of the source
205            // sample format is greater than that of the destination sample format.
206            debug_assert!(F::EFF_BITS > T::EFF_BITS);
207
208            // The number of low-order bits being truncated by the conversion will be dithered.
209            let dither_bits = 32 - T::EFF_BITS;
210
211            // Add the noise to the sample.
212            let noise = RandomNoise::from(self.prng.next() as i32, dither_bits);
213            noise.add_noise(sample)
214        }
215    }
216
217    impl<F: Sample, T: Sample> Default for Rectangular<F, T> {
218        fn default() -> Self {
219            Self::new()
220        }
221    }
222
223    /// `Triangular` implements a dither using a triangular distribution of noise without shaping.
224    pub struct Triangular<F: Sample, T: Sample> {
225        prng: prng::Xoshiro128pp,
226        from_type: PhantomData<F>,
227        to_type: PhantomData<T>,
228    }
229
230    impl<F: Sample, T: Sample> Triangular<F, T> {
231        pub fn new() -> Self {
232            Triangular {
233                prng: prng::Xoshiro128pp::new(0xb2c1_01f4_425b_987e),
234                from_type: PhantomData,
235                to_type: PhantomData,
236            }
237        }
238    }
239
240    impl<F: Sample, T: Sample> Dither<F, T> for Triangular<F, T>
241    where
242        RandomNoise: AddNoise<F>,
243    {
244        fn dither(&mut self, sample: F) -> F {
245            debug_assert!(F::EFF_BITS > T::EFF_BITS);
246
247            let dither_bits = 32 - T::EFF_BITS;
248
249            // Generate a triangular distribution from the uniform distribution.
250            let tpdf = (self.prng.next() as i32 >> 1) + (self.prng.next() as i32 >> 1);
251
252            // Add the noise to the sample.
253            let noise = RandomNoise::from(tpdf, dither_bits);
254            noise.add_noise(sample)
255        }
256    }
257
258    impl<F: Sample, T: Sample> Default for Triangular<F, T> {
259        fn default() -> Self {
260            Self::new()
261        }
262    }
263
264    /// Enumeration of dither algorithms.
265    pub enum DitherType {
266        /// No dithering.
267        Identity,
268        /// Apply rectangular dithering. See `Rectangular` for more details.
269        Rectangular,
270        /// Apply triangular dithering. See `Triangular` for more details.
271        Triangular,
272    }
273
274    /// `MaybeDither` conditionally applies a dither to a sample depending on the source and
275    /// destination sample types.
276    pub trait MaybeDither<T: Sample>: Sample {
277        const DITHERABLE: bool;
278
279        fn maybe_dither<D: Dither<Self, T>>(self, dither: &mut D) -> Self;
280    }
281
282    /// Never apply a dither for this conversion.
283    macro_rules! dither_never {
284        ($to:ty, $from:ty) => {
285            impl MaybeDither<$to> for $from {
286                const DITHERABLE: bool = false;
287                #[inline(always)]
288                fn maybe_dither<D: Dither<$from, $to>>(self, _: &mut D) -> Self {
289                    self
290                }
291            }
292        };
293    }
294
295    /// Maybe apply a dither for this conversion.
296    macro_rules! dither_maybe {
297        ($to:ty, $from:ty) => {
298            impl MaybeDither<$to> for $from {
299                const DITHERABLE: bool = true;
300                #[inline(always)]
301                fn maybe_dither<D: Dither<$from, $to>>(self, dither: &mut D) -> Self {
302                    dither.dither(self)
303                }
304            }
305        };
306    }
307
308    // Dither table for conversions to u8
309    dither_never!(u8, u8);
310    dither_maybe!(u8, u16);
311    dither_maybe!(u8, u24);
312    dither_maybe!(u8, u32);
313    dither_never!(u8, i8);
314    dither_maybe!(u8, i16);
315    dither_maybe!(u8, i24);
316    dither_maybe!(u8, i32);
317    dither_never!(u8, f32);
318    dither_never!(u8, f64);
319
320    // Dither table for conversions to u16
321    dither_never!(u16, u8);
322    dither_never!(u16, u16);
323    dither_maybe!(u16, u24);
324    dither_maybe!(u16, u32);
325    dither_never!(u16, i8);
326    dither_never!(u16, i16);
327    dither_maybe!(u16, i24);
328    dither_maybe!(u16, i32);
329    dither_never!(u16, f32);
330    dither_never!(u16, f64);
331
332    // Dither table for conversions to u24
333    dither_never!(u24, u8);
334    dither_never!(u24, u16);
335    dither_never!(u24, u24);
336    dither_maybe!(u24, u32);
337    dither_never!(u24, i8);
338    dither_never!(u24, i16);
339    dither_never!(u24, i24);
340    dither_maybe!(u24, i32);
341    dither_never!(u24, f32);
342    dither_never!(u24, f64);
343
344    // Dither table for conversions to u32
345    dither_never!(u32, u8);
346    dither_never!(u32, u16);
347    dither_never!(u32, u24);
348    dither_never!(u32, u32);
349    dither_never!(u32, i8);
350    dither_never!(u32, i16);
351    dither_never!(u32, i24);
352    dither_never!(u32, i32);
353    dither_never!(u32, f32);
354    dither_never!(u32, f64);
355
356    // Dither table for conversions to i8
357    dither_never!(i8, u8);
358    dither_maybe!(i8, u16);
359    dither_maybe!(i8, u24);
360    dither_maybe!(i8, u32);
361    dither_never!(i8, i8);
362    dither_maybe!(i8, i16);
363    dither_maybe!(i8, i24);
364    dither_maybe!(i8, i32);
365    dither_never!(i8, f32);
366    dither_never!(i8, f64);
367
368    // Dither table for conversions to i16
369    dither_never!(i16, u8);
370    dither_never!(i16, u16);
371    dither_maybe!(i16, u24);
372    dither_maybe!(i16, u32);
373    dither_never!(i16, i8);
374    dither_never!(i16, i16);
375    dither_maybe!(i16, i24);
376    dither_maybe!(i16, i32);
377    dither_never!(i16, f32);
378    dither_never!(i16, f64);
379
380    // Dither table for conversions to i24
381    dither_never!(i24, u8);
382    dither_never!(i24, u16);
383    dither_never!(i24, u24);
384    dither_maybe!(i24, u32);
385    dither_never!(i24, i8);
386    dither_never!(i24, i16);
387    dither_never!(i24, i24);
388    dither_maybe!(i24, i32);
389    dither_never!(i24, f32);
390    dither_never!(i24, f64);
391
392    // Dither table for conversions to i32
393    dither_never!(i32, u8);
394    dither_never!(i32, u16);
395    dither_never!(i32, u24);
396    dither_never!(i32, u32);
397    dither_never!(i32, i8);
398    dither_never!(i32, i16);
399    dither_never!(i32, i24);
400    dither_never!(i32, i32);
401    dither_never!(i32, f32);
402    dither_never!(i32, f64);
403
404    // Dither table for conversions to f32
405    dither_never!(f32, u8);
406    dither_never!(f32, u16);
407    dither_never!(f32, u24);
408    dither_never!(f32, u32);
409    dither_never!(f32, i8);
410    dither_never!(f32, i16);
411    dither_never!(f32, i24);
412    dither_never!(f32, i32);
413    dither_never!(f32, f32);
414    dither_never!(f32, f64);
415
416    // Dither table for conversions to f64
417    dither_never!(f64, u8);
418    dither_never!(f64, u16);
419    dither_never!(f64, u24);
420    dither_never!(f64, u32);
421    dither_never!(f64, i8);
422    dither_never!(f64, i16);
423    dither_never!(f64, i24);
424    dither_never!(f64, i32);
425    dither_never!(f64, f32);
426    dither_never!(f64, f64);
427}
428
429/// `FromSample` implements a conversion from `Sample` type `F` to `Self`.
430///
431/// This may be a lossy conversion if converting from a sample type of higher precision to one of
432/// lower precision. No dithering is applied.
433pub trait FromSample<F> {
434    fn from_sample(val: F) -> Self;
435}
436
437// Notes on sample format converters
438//
439// In total there are 10 different sample formats, so there are 100 different sample format
440// converters. Of the 100 sample format converters, there are 64 int <-> int, 32 int <-> float, and
441// 4 float <-> float converters.
442//
443// A minimum version of Rust 1.45 is required. As of Rust 1.45 a `<float> as <integer>` cast
444// saturates (clamps) to the bounds of the integer. Therefore, no clamping is required. Symphonia
445// takes advantage of this behaviour.
446
447macro_rules! impl_convert {
448    ($from:ty, $to:ty, $sample:ident, $func:expr) => {
449        impl FromSample<$from> for $to {
450            #[inline(always)]
451            fn from_sample($sample: $from) -> Self {
452                $func
453            }
454        }
455    };
456}
457
458// i8 to ...
459
460#[inline(always)]
461fn i8_to_u8(s: i8) -> u8 {
462    (s as u8).wrapping_add(0x80)
463}
464
465impl_convert!(i8, u8, s, i8_to_u8(s)); // u8
466impl_convert!(i8, u16, s, (i8_to_u8(s) as u16) << 8); // u16
467impl_convert!(i8, u24, s, u24::from((i8_to_u8(s) as u32) << 16)); // u24
468impl_convert!(i8, u32, s, (i8_to_u8(s) as u32) << 24); // u3
469
470impl_convert!(i8, i8, s, s); // i8
471impl_convert!(i8, i16, s, (s as i16) << 8); // i16
472impl_convert!(i8, i24, s, i24::from((s as i32) << 16)); // i24
473impl_convert!(i8, i32, s, (s as i32) << 24); // i32
474
475impl_convert!(i8, f32, s, s as f32 / 128.0); // f32
476impl_convert!(i8, f64, s, s as f64 / 128.0); // f64
477
478// i16 to ...
479
480#[inline(always)]
481fn i16_to_u16(s: i16) -> u16 {
482    (s as u16).wrapping_add(0x8000)
483}
484
485impl_convert!(i16, u8, s, (i16_to_u16(s) >> 8) as u8); // u8
486impl_convert!(i16, u16, s, i16_to_u16(s)); // u16
487impl_convert!(i16, u24, s, u24::from((i16_to_u16(s) as u32) << 8)); // u24
488impl_convert!(i16, u32, s, (i16_to_u16(s) as u32) << 16); // u32
489
490impl_convert!(i16, i8, s, (s >> 8) as i8); // i8
491impl_convert!(i16, i16, s, s); // i16
492impl_convert!(i16, i24, s, i24::from((s as i32) << 8)); // i24
493impl_convert!(i16, i32, s, (s as i32) << 16); // i32
494
495impl_convert!(i16, f32, s, s as f32 / 32_768.0); // f32
496impl_convert!(i16, f64, s, s as f64 / 32_768.0); // f64
497
498// i24 to ...
499
500#[inline(always)]
501fn i24_to_u32(s: i24) -> u32 {
502    ((s.clamped().inner() << 8) as u32).wrapping_add(0x8000_0000)
503}
504
505impl_convert!(i24, u8, s, (i24_to_u32(s) >> 24) as u8); // u8
506impl_convert!(i24, u16, s, (i24_to_u32(s) >> 16) as u16); // u16
507impl_convert!(i24, u24, s, u24::from(i24_to_u32(s) >> 8)); // u24
508impl_convert!(i24, u32, s, i24_to_u32(s)); // u32
509
510impl_convert!(i24, i8, s, (s.clamped().inner() >> 16) as i8); // i8
511impl_convert!(i24, i16, s, (s.clamped().inner() >> 8) as i16); // i16
512impl_convert!(i24, i24, s, s); // i24
513impl_convert!(i24, i32, s, (s.clamped().inner()) << 8); // i32
514
515impl_convert!(i24, f32, s, s.clamped().inner() as f32 / 8_388_608.0); // f32
516impl_convert!(i24, f64, s, s.clamped().inner() as f64 / 8_388_608.0); // f64
517
518// i32 to ...
519
520#[inline(always)]
521fn i32_to_u32(s: i32) -> u32 {
522    (s as u32).wrapping_add(0x8000_0000)
523}
524
525impl_convert!(i32, u8, s, (i32_to_u32(s) >> 24) as u8); // u8
526impl_convert!(i32, u16, s, (i32_to_u32(s) >> 16) as u16); // u16
527impl_convert!(i32, u24, s, u24::from(i32_to_u32(s) >> 8)); // u24
528impl_convert!(i32, u32, s, i32_to_u32(s)); // u32
529
530impl_convert!(i32, i8, s, (s >> 24) as i8); // i8
531impl_convert!(i32, i16, s, (s >> 16) as i16); // i16
532impl_convert!(i32, i24, s, i24::from(s >> 8)); // i24
533impl_convert!(i32, i32, s, s); // i32
534
535impl_convert!(i32, f32, s, (s as f64 / 2_147_483_648.0) as f32); // f32
536impl_convert!(i32, f64, s, s as f64 / 2_147_483_648.0); // f64
537
538// u8 to ...
539
540impl_convert!(u8, u8, s, s); // u8
541impl_convert!(u8, u16, s, (s as u16) << 8); // u16
542impl_convert!(u8, u24, s, u24::from((s as u32) << 16)); // u24
543impl_convert!(u8, u32, s, (s as u32) << 24); // u32
544
545impl_convert!(u8, i8, s, s.wrapping_sub(0x80) as i8); // i8
546impl_convert!(u8, i16, s, ((s.wrapping_sub(0x80) as i8) as i16) << 8); // i16
547impl_convert!(u8, i24, s, i24::from(((s.wrapping_sub(0x80) as i8) as i32) << 16)); // i24
548impl_convert!(u8, i32, s, ((s.wrapping_sub(0x80) as i8) as i32) << 24); // i32
549
550impl_convert!(u8, f32, s, ((s as f32) / 128.0) - 1.0); // f32
551impl_convert!(u8, f64, s, ((s as f64) / 128.0) - 1.0); // f64
552
553// u16 to ...
554
555impl_convert!(u16, u8, s, (s >> 8) as u8); // u8
556impl_convert!(u16, u16, s, s); // u16
557impl_convert!(u16, u24, s, u24::from((s as u32) << 8)); // u24
558impl_convert!(u16, u32, s, (s as u32) << 16); // u32
559
560impl_convert!(u16, i8, s, (s.wrapping_sub(0x8000) >> 8) as i8); // i8
561impl_convert!(u16, i16, s, s.wrapping_sub(0x8000) as i16); // i16
562impl_convert!(u16, i24, s, i24::from(((s.wrapping_sub(0x8000) as i16) as i32) << 8)); // i24
563impl_convert!(u16, i32, s, ((s.wrapping_sub(0x8000) as i16) as i32) << 16); // i32
564
565impl_convert!(u16, f32, s, ((s as f32) / 32_768.0) - 1.0); // f32
566impl_convert!(u16, f64, s, ((s as f64) / 32_768.0) - 1.0); // f64
567
568// u24 to ...
569
570impl_convert!(u24, u8, s, (s.clamped().inner() >> 16) as u8); // u8
571impl_convert!(u24, u16, s, (s.clamped().inner() >> 8) as u16); // u16
572impl_convert!(u24, u24, s, s); // u24
573impl_convert!(u24, u32, s, s.clamped().inner() << 8); // u32
574
575impl_convert!(u24, i8, s, (s.clamped().inner().wrapping_sub(0x80_0000) >> 16) as i8); // i8
576impl_convert!(u24, i16, s, (s.clamped().inner().wrapping_sub(0x80_0000) >> 8) as i16); // i16
577impl_convert!(u24, i24, s, i24::from(s.clamped().inner().wrapping_sub(0x80_0000) as i32)); // i24
578impl_convert!(u24, i32, s, (s.clamped().inner().wrapping_sub(0x80_0000) << 8) as i32); // i32
579
580impl_convert!(u24, f32, s, ((s.clamped().inner() as f32) / 8_388_608.0) - 1.0); // f32
581impl_convert!(u24, f64, s, ((s.clamped().inner() as f64) / 8_388_608.0) - 1.0); // f64
582
583// u32 to ...
584
585impl_convert!(u32, u8, s, (s >> 24) as u8); // u8
586impl_convert!(u32, u16, s, (s >> 16) as u16); // u16
587impl_convert!(u32, u24, s, u24::from(s >> 8)); // u24
588impl_convert!(u32, u32, s, s); // u32
589
590impl_convert!(u32, i8, s, (s.wrapping_sub(0x8000_0000) >> 24) as i8); // i8
591impl_convert!(u32, i16, s, (s.wrapping_sub(0x8000_0000) >> 16) as i16); // i16
592impl_convert!(u32, i24, s, i24::from((s.wrapping_sub(0x8000_0000) as i32) >> 8)); // i24
593impl_convert!(u32, i32, s, s.wrapping_sub(0x8000_0000) as i32); // i32
594
595impl_convert!(u32, f32, s, (((s as f64) / 2_147_483_648.0) - 1.0) as f32); // f32
596impl_convert!(u32, f64, s, ((s as f64) / 2_147_483_648.0) - 1.0); // f64
597
598// f32 to ...
599
600impl_convert!(f32, u8, s, ((s.clamped() + 1.0) * 128.0) as u8); // u8
601impl_convert!(f32, u16, s, ((s.clamped() + 1.0) * 32_768.0) as u16); // u16
602impl_convert!(f32, u24, s, u24::from(((s.clamped() + 1.0) * 8_388_608.0) as u32)); // u24
603impl_convert!(f32, u32, s, ((s.clamped() + 1.0) as f64 * 2_147_483_648.0) as u32); // u32
604
605impl_convert!(f32, i8, s, (s.clamped() * 128.0) as i8); // i8
606impl_convert!(f32, i16, s, (s.clamped() * 32_768.0) as i16); // i16
607impl_convert!(f32, i24, s, i24::from((s.clamped() * 8_388_608.0) as i32)); // i24
608impl_convert!(f32, i32, s, (s.clamped() as f64 * 2_147_483_648.0) as i32); // i32
609
610impl_convert!(f32, f32, s, s); // f32
611impl_convert!(f32, f64, s, s as f64); // f64
612
613// f64 to ...
614
615impl_convert!(f64, u8, s, ((s.clamped() + 1.0) * 128.0) as u8); // u8
616impl_convert!(f64, u16, s, ((s.clamped() + 1.0) * 32_768.0) as u16); // u16
617impl_convert!(f64, u24, s, u24::from(((s.clamped() + 1.0) * 8_388_608.0) as u32)); // u24
618impl_convert!(f64, u32, s, ((s.clamped() + 1.0) * 2_147_483_648.0) as u32); // u32
619
620impl_convert!(f64, i8, s, (s.clamped() * 128.0) as i8); // i8
621impl_convert!(f64, i16, s, (s.clamped() * 32_768.0) as i16); // i16
622impl_convert!(f64, i24, s, i24::from((s.clamped() * 8_388_608.0) as i32)); // i24
623impl_convert!(f64, i32, s, (s.clamped() * 2_147_483_648.0) as i32); // i32
624
625impl_convert!(f64, f32, s, s as f32); // f32
626impl_convert!(f64, f64, s, s); // f64
627
628/// `IntoSample` implements a conversion from `Self` to `Sample` type `T`.
629///
630/// This may be a lossy conversion if converting from a sample type of higher precision to one of
631/// lower precision. No dithering is applied.
632pub trait IntoSample<T> {
633    fn into_sample(self) -> T;
634}
635
636impl<F, T: FromSample<F>> IntoSample<T> for F {
637    #[inline]
638    fn into_sample(self) -> T {
639        T::from_sample(self)
640    }
641}
642
643/// `ReversibleSample` is a trait that when implemented for `Self`, that `Sample` type implements
644/// reversible conversions between `Self` and the parameterized `Sample` type `S`.
645pub trait ReversibleSample<S>: Sample + FromSample<S> + IntoSample<S> {}
646impl<S, T> ReversibleSample<S> for T where T: Sample + FromSample<S> + IntoSample<S> {}
647
648pub trait ConvertibleSample:
649    Sample
650    + FromSample<i8>
651    + FromSample<u8>
652    + FromSample<i16>
653    + FromSample<u16>
654    + FromSample<i24>
655    + FromSample<u24>
656    + FromSample<i32>
657    + FromSample<u32>
658    + FromSample<f32>
659    + FromSample<f64>
660{
661}
662
663impl<S> ConvertibleSample for S where
664    S: Sample
665        + FromSample<i8>
666        + FromSample<u8>
667        + FromSample<i16>
668        + FromSample<u16>
669        + FromSample<i24>
670        + FromSample<u24>
671        + FromSample<i32>
672        + FromSample<u32>
673        + FromSample<f32>
674        + FromSample<f64>
675{
676}
677
678#[cfg(test)]
679mod tests {
680    use super::FromSample;
681    use crate::sample::{i24, u24, Sample};
682    use std::{i16, i32, i8, u16, u32, u8};
683
684    #[test]
685    fn verify_u8_from_sample() {
686        assert_eq!(u8::from_sample(u8::MAX), u8::MAX);
687        assert_eq!(u8::from_sample(u8::MID), u8::MID);
688        assert_eq!(u8::from_sample(u8::MIN), u8::MIN);
689
690        assert_eq!(u8::from_sample(u16::MAX), u8::MAX);
691        assert_eq!(u8::from_sample(u16::MID), u8::MID);
692        assert_eq!(u8::from_sample(u16::MIN), u8::MIN);
693
694        assert_eq!(u8::from_sample(u24::MAX), u8::MAX);
695        assert_eq!(u8::from_sample(u24::MID), u8::MID);
696        assert_eq!(u8::from_sample(u24::MIN), u8::MIN);
697
698        assert_eq!(u8::from_sample(u32::MAX), u8::MAX);
699        assert_eq!(u8::from_sample(u32::MID), u8::MID);
700        assert_eq!(u8::from_sample(u32::MIN), u8::MIN);
701
702        assert_eq!(u8::from_sample(i8::MAX), u8::MAX);
703        assert_eq!(u8::from_sample(i8::MID), u8::MID);
704        assert_eq!(u8::from_sample(i8::MIN), u8::MIN);
705
706        assert_eq!(u8::from_sample(i16::MAX), u8::MAX);
707        assert_eq!(u8::from_sample(i16::MID), u8::MID);
708        assert_eq!(u8::from_sample(i16::MIN), u8::MIN);
709
710        assert_eq!(u8::from_sample(i24::MAX), u8::MAX);
711        assert_eq!(u8::from_sample(i24::MID), u8::MID);
712        assert_eq!(u8::from_sample(i24::MIN), u8::MIN);
713
714        assert_eq!(u8::from_sample(i32::MAX), u8::MAX);
715        assert_eq!(u8::from_sample(i32::MID), u8::MID);
716        assert_eq!(u8::from_sample(i32::MIN), u8::MIN);
717
718        assert_eq!(u8::from_sample(1.0f32), u8::MAX);
719        assert_eq!(u8::from_sample(0f32), u8::MID);
720        assert_eq!(u8::from_sample(-1.0f32), u8::MIN);
721
722        assert_eq!(u8::from_sample(1.0f64), u8::MAX);
723        assert_eq!(u8::from_sample(0f64), u8::MID);
724        assert_eq!(u8::from_sample(-1.0f64), u8::MIN);
725    }
726
727    #[test]
728    fn verify_u16_from_sample() {
729        assert_eq!(u16::from_sample(u8::MAX), u16::MAX - 255);
730        assert_eq!(u16::from_sample(u8::MID), u16::MID);
731        assert_eq!(u16::from_sample(u8::MIN), u16::MIN);
732
733        assert_eq!(u16::from_sample(u16::MAX), u16::MAX);
734        assert_eq!(u16::from_sample(u16::MID), u16::MID);
735        assert_eq!(u16::from_sample(u16::MIN), u16::MIN);
736
737        assert_eq!(u16::from_sample(u24::MAX), u16::MAX);
738        assert_eq!(u16::from_sample(u24::MID), u16::MID);
739        assert_eq!(u16::from_sample(u24::MIN), u16::MIN);
740
741        assert_eq!(u16::from_sample(u32::MAX), u16::MAX);
742        assert_eq!(u16::from_sample(u32::MID), u16::MID);
743        assert_eq!(u16::from_sample(u32::MIN), u16::MIN);
744
745        assert_eq!(u16::from_sample(i8::MAX), u16::MAX - 255);
746        assert_eq!(u16::from_sample(i8::MID), u16::MID);
747        assert_eq!(u16::from_sample(i8::MIN), u16::MIN);
748
749        assert_eq!(u16::from_sample(i16::MAX), u16::MAX);
750        assert_eq!(u16::from_sample(i16::MID), u16::MID);
751        assert_eq!(u16::from_sample(i16::MIN), u16::MIN);
752
753        assert_eq!(u16::from_sample(i24::MAX), u16::MAX);
754        assert_eq!(u16::from_sample(i24::MID), u16::MID);
755        assert_eq!(u16::from_sample(i24::MIN), u16::MIN);
756
757        assert_eq!(u16::from_sample(i32::MAX), u16::MAX);
758        assert_eq!(u16::from_sample(i32::MID), u16::MID);
759        assert_eq!(u16::from_sample(i32::MIN), u16::MIN);
760
761        assert_eq!(u16::from_sample(1.0f32), u16::MAX);
762        assert_eq!(u16::from_sample(0f32), u16::MID);
763        assert_eq!(u16::from_sample(-1.0f32), u16::MIN);
764
765        assert_eq!(u16::from_sample(1.0f64), u16::MAX);
766        assert_eq!(u16::from_sample(0f64), u16::MID);
767        assert_eq!(u16::from_sample(-1.0f64), u16::MIN);
768    }
769
770    #[test]
771    fn verify_u24_from_sample() {
772        assert_eq!(u24::from_sample(u8::MAX), u24::MAX - u24::from(65_535u32));
773        assert_eq!(u24::from_sample(u8::MID), u24::MID);
774        assert_eq!(u24::from_sample(u8::MIN), u24::MIN);
775
776        assert_eq!(u24::from_sample(u16::MAX), u24::MAX - u24::from(255u32));
777        assert_eq!(u24::from_sample(u16::MID), u24::MID);
778        assert_eq!(u24::from_sample(u16::MIN), u24::MIN);
779
780        assert_eq!(u24::from_sample(u24::MAX), u24::MAX);
781        assert_eq!(u24::from_sample(u24::MID), u24::MID);
782        assert_eq!(u24::from_sample(u24::MIN), u24::MIN);
783
784        assert_eq!(u24::from_sample(u32::MAX), u24::MAX);
785        assert_eq!(u24::from_sample(u32::MID), u24::MID);
786        assert_eq!(u24::from_sample(u32::MIN), u24::MIN);
787
788        assert_eq!(u24::from_sample(i8::MAX), u24::MAX - u24::from(65_535u32));
789        assert_eq!(u24::from_sample(i8::MID), u24::MID);
790        assert_eq!(u24::from_sample(i8::MIN), u24::MIN);
791
792        assert_eq!(u24::from_sample(i16::MAX), u24::MAX - u24::from(255u32));
793        assert_eq!(u24::from_sample(i16::MID), u24::MID);
794        assert_eq!(u24::from_sample(i16::MIN), u24::MIN);
795
796        assert_eq!(u24::from_sample(i24::MAX), u24::MAX);
797        assert_eq!(u24::from_sample(i24::MID), u24::MID);
798        assert_eq!(u24::from_sample(i24::MIN), u24::MIN);
799
800        assert_eq!(u24::from_sample(i32::MAX), u24::MAX);
801        assert_eq!(u24::from_sample(i32::MID), u24::MID);
802        assert_eq!(u24::from_sample(i32::MIN), u24::MIN);
803
804        assert_eq!(u24::from_sample(1.0f32), u24::MAX);
805        assert_eq!(u24::from_sample(0f32), u24::MID);
806        assert_eq!(u24::from_sample(-1.0f32), u24::MIN);
807
808        assert_eq!(u24::from_sample(1.0f64), u24::MAX);
809        assert_eq!(u24::from_sample(0f64), u24::MID);
810        assert_eq!(u24::from_sample(-1.0f64), u24::MIN);
811    }
812
813    #[test]
814    fn verify_u32_from_sample() {
815        assert_eq!(u32::from_sample(u8::MAX), u32::MAX - 16_777_215);
816        assert_eq!(u32::from_sample(u8::MID), u32::MID);
817        assert_eq!(u32::from_sample(u8::MIN), u32::MIN);
818
819        assert_eq!(u32::from_sample(u16::MAX), u32::MAX - 65_535);
820        assert_eq!(u32::from_sample(u16::MID), u32::MID);
821        assert_eq!(u32::from_sample(u16::MIN), u32::MIN);
822
823        assert_eq!(u32::from_sample(u24::MAX), u32::MAX - 255);
824        assert_eq!(u32::from_sample(u24::MID), u32::MID);
825        assert_eq!(u32::from_sample(u24::MIN), u32::MIN);
826
827        assert_eq!(u32::from_sample(u32::MAX), u32::MAX);
828        assert_eq!(u32::from_sample(u32::MID), u32::MID);
829        assert_eq!(u32::from_sample(u32::MIN), u32::MIN);
830
831        assert_eq!(u32::from_sample(i8::MAX), u32::MAX - 16_777_215);
832        assert_eq!(u32::from_sample(i8::MID), u32::MID);
833        assert_eq!(u32::from_sample(i8::MIN), u32::MIN);
834
835        assert_eq!(u32::from_sample(i16::MAX), u32::MAX - 65_535);
836        assert_eq!(u32::from_sample(i16::MID), u32::MID);
837        assert_eq!(u32::from_sample(i16::MIN), u32::MIN);
838
839        assert_eq!(u32::from_sample(i24::MAX), u32::MAX - 255);
840        assert_eq!(u32::from_sample(i24::MID), u32::MID);
841        assert_eq!(u32::from_sample(i24::MIN), u32::MIN);
842
843        assert_eq!(u32::from_sample(i32::MAX), u32::MAX);
844        assert_eq!(u32::from_sample(i32::MID), u32::MID);
845        assert_eq!(u32::from_sample(i32::MIN), u32::MIN);
846
847        assert_eq!(u32::from_sample(1.0f32), u32::MAX);
848        assert_eq!(u32::from_sample(0f32), u32::MID);
849        assert_eq!(u32::from_sample(-1.0f32), u32::MIN);
850
851        assert_eq!(u32::from_sample(1.0f64), u32::MAX);
852        assert_eq!(u32::from_sample(0f64), u32::MID);
853        assert_eq!(u32::from_sample(-1.0f64), u32::MIN);
854    }
855
856    #[test]
857    fn verify_i8_from_sample() {
858        assert_eq!(i8::from_sample(u8::MAX), i8::MAX);
859        assert_eq!(i8::from_sample(u8::MID), i8::MID);
860        assert_eq!(i8::from_sample(u8::MIN), i8::MIN);
861
862        assert_eq!(i8::from_sample(u16::MAX), i8::MAX);
863        assert_eq!(i8::from_sample(u16::MID), i8::MID);
864        assert_eq!(i8::from_sample(u16::MIN), i8::MIN);
865
866        assert_eq!(i8::from_sample(u24::MAX), i8::MAX);
867        assert_eq!(i8::from_sample(u24::MID), i8::MID);
868        assert_eq!(i8::from_sample(u24::MIN), i8::MIN);
869
870        assert_eq!(i8::from_sample(u32::MAX), i8::MAX);
871        assert_eq!(i8::from_sample(u32::MID), i8::MID);
872        assert_eq!(i8::from_sample(u32::MIN), i8::MIN);
873
874        assert_eq!(i8::from_sample(i8::MAX), i8::MAX);
875        assert_eq!(i8::from_sample(i8::MID), i8::MID);
876        assert_eq!(i8::from_sample(i8::MIN), i8::MIN);
877
878        assert_eq!(i8::from_sample(i16::MAX), i8::MAX);
879        assert_eq!(i8::from_sample(i16::MID), i8::MID);
880        assert_eq!(i8::from_sample(i16::MIN), i8::MIN);
881
882        assert_eq!(i8::from_sample(i24::MAX), i8::MAX);
883        assert_eq!(i8::from_sample(i24::MID), i8::MID);
884        assert_eq!(i8::from_sample(i24::MIN), i8::MIN);
885
886        assert_eq!(i8::from_sample(i32::MAX), i8::MAX);
887        assert_eq!(i8::from_sample(i32::MID), i8::MID);
888        assert_eq!(i8::from_sample(i32::MIN), i8::MIN);
889
890        assert_eq!(i8::from_sample(1.0f32), i8::MAX);
891        assert_eq!(i8::from_sample(0f32), i8::MID);
892        assert_eq!(i8::from_sample(-1.0f32), i8::MIN);
893
894        assert_eq!(i8::from_sample(1.0f64), i8::MAX);
895        assert_eq!(i8::from_sample(0f64), i8::MID);
896        assert_eq!(i8::from_sample(-1.0f64), i8::MIN);
897    }
898
899    #[test]
900    fn verify_i16_from_sample() {
901        assert_eq!(i16::from_sample(u8::MAX), i16::MAX - 255);
902        assert_eq!(i16::from_sample(u8::MID), i16::MID);
903        assert_eq!(i16::from_sample(u8::MIN), i16::MIN);
904
905        assert_eq!(i16::from_sample(u16::MAX), i16::MAX);
906        assert_eq!(i16::from_sample(u16::MID), i16::MID);
907        assert_eq!(i16::from_sample(u16::MIN), i16::MIN);
908
909        assert_eq!(i16::from_sample(u24::MAX), i16::MAX);
910        assert_eq!(i16::from_sample(u24::MID), i16::MID);
911        assert_eq!(i16::from_sample(u24::MIN), i16::MIN);
912
913        assert_eq!(i16::from_sample(u32::MAX), i16::MAX);
914        assert_eq!(i16::from_sample(u32::MID), i16::MID);
915        assert_eq!(i16::from_sample(u32::MIN), i16::MIN);
916
917        assert_eq!(i16::from_sample(i8::MAX), i16::MAX - 255);
918        assert_eq!(i16::from_sample(i8::MID), i16::MID);
919        assert_eq!(i16::from_sample(i8::MIN), i16::MIN);
920
921        assert_eq!(i16::from_sample(i16::MAX), i16::MAX);
922        assert_eq!(i16::from_sample(i16::MID), i16::MID);
923        assert_eq!(i16::from_sample(i16::MIN), i16::MIN);
924
925        assert_eq!(i16::from_sample(i24::MAX), i16::MAX);
926        assert_eq!(i16::from_sample(i24::MID), i16::MID);
927        assert_eq!(i16::from_sample(i24::MIN), i16::MIN);
928
929        assert_eq!(i16::from_sample(i32::MAX), i16::MAX);
930        assert_eq!(i16::from_sample(i32::MID), i16::MID);
931        assert_eq!(i16::from_sample(i32::MIN), i16::MIN);
932
933        assert_eq!(i16::from_sample(1.0f32), i16::MAX);
934        assert_eq!(i16::from_sample(0f32), i16::MID);
935        assert_eq!(i16::from_sample(-1.0f32), i16::MIN);
936
937        assert_eq!(i16::from_sample(1.0f64), i16::MAX);
938        assert_eq!(i16::from_sample(0f64), i16::MID);
939        assert_eq!(i16::from_sample(-1.0f64), i16::MIN);
940    }
941
942    #[test]
943    fn verify_i24_from_sample() {
944        assert_eq!(i24::from_sample(u8::MAX), i24::MAX - i24::from(65_535));
945        assert_eq!(i24::from_sample(u8::MID), i24::MID);
946        assert_eq!(i24::from_sample(u8::MIN), i24::MIN);
947
948        assert_eq!(i24::from_sample(u16::MAX), i24::MAX - i24::from(255));
949        assert_eq!(i24::from_sample(u16::MID), i24::MID);
950        assert_eq!(i24::from_sample(u16::MIN), i24::MIN);
951
952        assert_eq!(i24::from_sample(u24::MAX), i24::MAX);
953        assert_eq!(i24::from_sample(u24::MID), i24::MID);
954        assert_eq!(i24::from_sample(u24::MIN), i24::MIN);
955
956        assert_eq!(i24::from_sample(u32::MAX), i24::MAX);
957        assert_eq!(i24::from_sample(u32::MID), i24::MID);
958        assert_eq!(i24::from_sample(u32::MIN), i24::MIN);
959
960        assert_eq!(i24::from_sample(i8::MAX), i24::MAX - i24::from(65_535));
961        assert_eq!(i24::from_sample(i8::MID), i24::MID);
962        assert_eq!(i24::from_sample(i8::MIN), i24::MIN);
963
964        assert_eq!(i24::from_sample(i16::MAX), i24::MAX - i24::from(255));
965        assert_eq!(i24::from_sample(i16::MID), i24::MID);
966        assert_eq!(i24::from_sample(i16::MIN), i24::MIN);
967
968        assert_eq!(i24::from_sample(i24::MAX), i24::MAX);
969        assert_eq!(i24::from_sample(i24::MID), i24::MID);
970        assert_eq!(i24::from_sample(i24::MIN), i24::MIN);
971
972        assert_eq!(i24::from_sample(i32::MAX), i24::MAX);
973        assert_eq!(i24::from_sample(i32::MID), i24::MID);
974        assert_eq!(i24::from_sample(i32::MIN), i24::MIN);
975
976        assert_eq!(i24::from_sample(1.0f32), i24::MAX);
977        assert_eq!(i24::from_sample(0f32), i24::MID);
978        assert_eq!(i24::from_sample(-1.0f32), i24::MIN);
979
980        assert_eq!(i24::from_sample(1.0f64), i24::MAX);
981        assert_eq!(i24::from_sample(0f64), i24::MID);
982        assert_eq!(i24::from_sample(-1.0f64), i24::MIN);
983    }
984
985    #[test]
986    fn verify_i32_from_sample() {
987        assert_eq!(i32::from_sample(u8::MAX), i32::MAX - 16_777_215);
988        assert_eq!(i32::from_sample(u8::MID), i32::MID);
989        assert_eq!(i32::from_sample(u8::MIN), i32::MIN);
990
991        assert_eq!(i32::from_sample(u16::MAX), i32::MAX - 65_535);
992        assert_eq!(i32::from_sample(u16::MID), i32::MID);
993        assert_eq!(i32::from_sample(u16::MIN), i32::MIN);
994
995        assert_eq!(i32::from_sample(u24::MAX), i32::MAX - 255);
996        assert_eq!(i32::from_sample(u24::MID), i32::MID);
997        assert_eq!(i32::from_sample(u24::MIN), i32::MIN);
998
999        assert_eq!(i32::from_sample(u32::MAX), i32::MAX);
1000        assert_eq!(i32::from_sample(u32::MID), i32::MID);
1001        assert_eq!(i32::from_sample(u32::MIN), i32::MIN);
1002
1003        assert_eq!(i32::from_sample(i8::MAX), i32::MAX - 16_777_215);
1004        assert_eq!(i32::from_sample(i8::MID), i32::MID);
1005        assert_eq!(i32::from_sample(i8::MIN), i32::MIN);
1006
1007        assert_eq!(i32::from_sample(i16::MAX), i32::MAX - 65_535);
1008        assert_eq!(i32::from_sample(i16::MID), i32::MID);
1009        assert_eq!(i32::from_sample(i16::MIN), i32::MIN);
1010
1011        assert_eq!(i32::from_sample(i24::MAX), i32::MAX - 255);
1012        assert_eq!(i32::from_sample(i24::MID), i32::MID);
1013        assert_eq!(i32::from_sample(i24::MIN), i32::MIN);
1014
1015        assert_eq!(i32::from_sample(i32::MAX), i32::MAX);
1016        assert_eq!(i32::from_sample(i32::MID), i32::MID);
1017        assert_eq!(i32::from_sample(i32::MIN), i32::MIN);
1018
1019        assert_eq!(i32::from_sample(1.0f32), i32::MAX);
1020        assert_eq!(i32::from_sample(0f32), i32::MID);
1021        assert_eq!(i32::from_sample(-1.0f32), i32::MIN);
1022
1023        assert_eq!(i32::from_sample(1.0f64), i32::MAX);
1024        assert_eq!(i32::from_sample(0f64), i32::MID);
1025        assert_eq!(i32::from_sample(-1.0f64), i32::MIN);
1026    }
1027
1028    #[test]
1029    fn verify_f64_from_sample() {
1030        assert_eq!(f64::from_sample(u8::MAX), 127.0 / 128.0);
1031        assert_eq!(f64::from_sample(u8::MID), 0.0);
1032        assert_eq!(f64::from_sample(u8::MIN), -1.0);
1033
1034        assert_eq!(f64::from_sample(u16::MAX), 32_767.0 / 32_768.0);
1035        assert_eq!(f64::from_sample(u16::MID), 0.0);
1036        assert_eq!(f64::from_sample(u16::MIN), -1.0);
1037
1038        assert_eq!(f64::from_sample(u24::MAX), 8_388_607.0 / 8_388_608.0);
1039        assert_eq!(f64::from_sample(u24::MID), 0.0);
1040        assert_eq!(f64::from_sample(u24::MIN), -1.0);
1041
1042        assert_eq!(f64::from_sample(u32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
1043        assert_eq!(f64::from_sample(u32::MID), 0.0);
1044        assert_eq!(f64::from_sample(u32::MIN), -1.0);
1045
1046        assert_eq!(f64::from_sample(i8::MAX), 127.0 / 128.0);
1047        assert_eq!(f64::from_sample(i8::MID), 0.0);
1048        assert_eq!(f64::from_sample(i8::MIN), -1.0);
1049
1050        assert_eq!(f64::from_sample(i16::MAX), 32_767.0 / 32_768.0);
1051        assert_eq!(f64::from_sample(i16::MID), 0.0);
1052        assert_eq!(f64::from_sample(i16::MIN), -1.0);
1053
1054        assert_eq!(f64::from_sample(i24::MAX), 8_388_607.0 / 8_388_608.0);
1055        assert_eq!(f64::from_sample(i24::MID), 0.0);
1056        assert_eq!(f64::from_sample(i24::MIN), -1.0);
1057
1058        assert_eq!(f64::from_sample(i32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
1059        assert_eq!(f64::from_sample(i32::MID), 0.0);
1060        assert_eq!(f64::from_sample(i32::MIN), -1.0);
1061
1062        assert_eq!(f64::from_sample(1.0f32), 1.0);
1063        assert_eq!(f64::from_sample(0f32), 0.0);
1064        assert_eq!(f64::from_sample(-1.0f32), -1.0);
1065
1066        assert_eq!(f64::from_sample(1.0f64), 1.0);
1067        assert_eq!(f64::from_sample(0f64), 0.0);
1068        assert_eq!(f64::from_sample(-1.0f64), -1.0);
1069    }
1070
1071    #[test]
1072    fn verify_f32_from_sample() {
1073        assert_eq!(f32::from_sample(u8::MAX), 127.0 / 128.0);
1074        assert_eq!(f32::from_sample(u8::MID), 0.0);
1075        assert_eq!(f32::from_sample(u8::MIN), -1.0);
1076
1077        assert_eq!(f32::from_sample(u16::MAX), 32_767.0 / 32_768.0);
1078        assert_eq!(f32::from_sample(u16::MID), 0.0);
1079        assert_eq!(f32::from_sample(u16::MIN), -1.0);
1080
1081        assert_eq!(f32::from_sample(u24::MAX), 8_388_607.0 / 8_388_608.0);
1082        assert_eq!(f32::from_sample(u24::MID), 0.0);
1083        assert_eq!(f32::from_sample(u24::MIN), -1.0);
1084
1085        assert_eq!(f32::from_sample(u32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
1086        assert_eq!(f32::from_sample(u32::MID), 0.0);
1087        assert_eq!(f32::from_sample(u32::MIN), -1.0);
1088
1089        assert_eq!(f32::from_sample(i8::MAX), 127.0 / 128.0);
1090        assert_eq!(f32::from_sample(i8::MID), 0.0);
1091        assert_eq!(f32::from_sample(i8::MIN), -1.0);
1092
1093        assert_eq!(f32::from_sample(i16::MAX), 32_767.0 / 32_768.0);
1094        assert_eq!(f32::from_sample(i16::MID), 0.0);
1095        assert_eq!(f32::from_sample(i16::MIN), -1.0);
1096
1097        assert_eq!(f32::from_sample(i24::MAX), 8_388_607.0 / 8_388_608.0);
1098        assert_eq!(f32::from_sample(i24::MID), 0.0);
1099        assert_eq!(f32::from_sample(i24::MIN), -1.0);
1100
1101        assert_eq!(f32::from_sample(i32::MAX), 2_147_483_647.0 / 2_147_483_648.0);
1102        assert_eq!(f32::from_sample(i32::MID), 0.0);
1103        assert_eq!(f32::from_sample(i32::MIN), -1.0);
1104
1105        assert_eq!(f32::from_sample(1.0f32), 1.0);
1106        assert_eq!(f32::from_sample(0f32), 0.0);
1107        assert_eq!(f32::from_sample(-1.0f32), -1.0);
1108
1109        assert_eq!(f32::from_sample(1.0f64), 1.0);
1110        assert_eq!(f32::from_sample(0f64), 0.0);
1111        assert_eq!(f32::from_sample(-1.0f64), -1.0);
1112    }
1113}