1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
use crate::sinc_interpolator::{AvxSample, NeonSample, SseSample};

#[cfg(feature = "fft_resampler")]
use realfft::FftNum;

#[cfg(not(feature = "fft_resampler"))]
use num_traits::{FromPrimitive, Signed};
#[cfg(not(feature = "fft_resampler"))]
use std::fmt::Debug;

#[cfg(not(feature = "fft_resampler"))]
pub trait FftNum: Copy + FromPrimitive + Signed + Sync + Send + Debug + 'static {}

#[cfg(not(feature = "fft_resampler"))]
impl<T> FftNum for T where T: Copy + FromPrimitive + Signed + Sync + Send + Debug + 'static {}

/// The trait governing a single sample.
///
/// There are two types which implements this trait so far:
/// * [f32]
/// * [f64]
pub trait Sample
where
    Self: Copy
        + CoerceFrom<usize>
        + CoerceFrom<f64>
        + CoerceFrom<f32>
        + FftNum
        + std::ops::Mul
        + std::ops::Div
        + std::ops::Add
        + std::ops::Sub
        + std::ops::MulAssign
        + std::ops::RemAssign
        + std::ops::DivAssign
        + std::ops::SubAssign
        + std::ops::AddAssign
        + AvxSample
        + SseSample
        + NeonSample
        + Send,
{
    const PI: Self;

    /// Calculate the sine of `self`.
    fn sin(self) -> Self;

    /// Calculate the cosine of `self`.
    fn cos(self) -> Self;

    /// Coerce `value` into the current type.
    ///
    /// Coercions are governed through the private `CoerceFrom` trait.
    fn coerce<T>(value: T) -> Self
    where
        Self: CoerceFrom<T>,
    {
        Self::coerce_from(value)
    }
}

impl Sample for f32 {
    const PI: Self = std::f32::consts::PI;

    fn sin(self) -> Self {
        f32::sin(self)
    }

    fn cos(self) -> Self {
        f32::cos(self)
    }
}

impl Sample for f64 {
    const PI: Self = std::f64::consts::PI;

    fn sin(self) -> Self {
        f64::sin(self)
    }

    fn cos(self) -> Self {
        f64::cos(self)
    }
}

/// The trait used to coerce a value infallibly from one type to another.
///
/// This is similar to doing `value as T` where `T` is a floating point type.
/// Loss of precision may happen during coercions if the coerced from value
/// doesn't fit fully within the target type.
pub trait CoerceFrom<T> {
    /// Perform a coercion from `value` into the current type.
    fn coerce_from(value: T) -> Self;
}

impl CoerceFrom<usize> for f32 {
    fn coerce_from(value: usize) -> Self {
        value as f32
    }
}

impl CoerceFrom<usize> for f64 {
    fn coerce_from(value: usize) -> Self {
        value as f64
    }
}

impl CoerceFrom<f64> for f32 {
    fn coerce_from(value: f64) -> Self {
        value as f32
    }
}

impl CoerceFrom<f64> for f64 {
    fn coerce_from(value: f64) -> Self {
        value
    }
}

impl CoerceFrom<f32> for f32 {
    fn coerce_from(value: f32) -> Self {
        value
    }
}

impl CoerceFrom<f32> for f64 {
    fn coerce_from(value: f32) -> Self {
        value as f64
    }
}