1#[cfg(not(feature = "std"))]
4#[allow(unused_imports)]
5use num_traits::float::FloatCore as _;
6
7use dsp_fixedpoint::Q32;
8use dsp_process::{SplitInplace, SplitProcess};
9
10#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
14#[repr(u8)]
15pub enum Tpa {
16 Z = 0x0,
18 A = 0xA,
20 B = 0xB,
22 B1 = 0xE,
24 X = 0x1,
26 C = 0xC,
28 C1 = 0xF,
30 D = 0xD,
32}
33
34impl From<u8> for Tpa {
35 #[inline]
36 fn from(value: u8) -> Self {
37 match value {
38 0xa => Tpa::A,
39 0xb => Tpa::B,
40 0xe => Tpa::B1,
41 0x1 => Tpa::X,
42 0xc => Tpa::C,
43 0xf => Tpa::C1,
44 0xd => Tpa::D,
45 _ => Tpa::Z,
46 }
47 }
48}
49
50impl Tpa {
51 fn quantize(self, g: f64) -> Option<Q32<32>> {
52 let a = match self {
55 Self::Z => 0.0,
56 Self::A => g - 1.0,
57 Self::B | Self::B1 => -g,
58 Self::X => 0.0,
59 Self::C | Self::C1 => g,
60 Self::D => -1.0 - g,
61 };
62 (-0.5..=0.0).contains(&a).then_some(Q32::from_f64(a))
63 }
64
65 #[inline]
66 fn adapt(&self, x: [i32; 2], a: Q32<32>) -> [i32; 2] {
67 match self {
68 Tpa::A => {
69 let c = x[1] - x[0];
70 let y = (c * a).wrapping_add(x[1]);
71 [y.wrapping_add(c), y]
72 }
73 Tpa::B => {
74 let c = x[0] - x[1];
75 let y = (c * a).wrapping_add(x[1]);
76 [y, y.wrapping_add(c)]
77 }
78 Tpa::B1 => {
79 let c = x[0] - x[1];
80 let y = c * a;
81 [y.wrapping_add(x[1]), y.wrapping_add(x[0])]
82 }
83 Tpa::X => [x[1], x[0]],
84 Tpa::C => {
85 let c = x[1] - x[0];
86 let y = (c * a).wrapping_sub(x[1]);
87 [y, y.wrapping_add(c)]
88 }
89 Tpa::C1 => {
90 let c = x[1] - x[0];
91 let y = c * a;
92 [y.wrapping_sub(x[1]), y.wrapping_sub(x[0])]
93 }
94 Tpa::D => {
95 let c = x[0] - x[1];
96 let y = (c * a).wrapping_sub(x[1]);
97 [y.wrapping_add(c), y]
98 }
99 Tpa::Z => x,
100 }
101 }
102}
103
104#[derive(Debug, Clone)]
111pub struct Wdf<const N: usize, const M: u32> {
112 pub a: [Q32<32>; N],
114}
115
116impl<const N: usize, const M: u32> Default for Wdf<N, M> {
117 fn default() -> Self {
118 Self {
119 a: [Default::default(); N],
120 }
121 }
122}
123
124impl<const N: usize, const M: u32> Wdf<N, M> {
125 pub fn quantize(g: &[f64; N]) -> Option<Self> {
131 let mut a = [Default::default(); N];
132 let mut m = M;
133 for (a, g) in a.iter_mut().zip(g) {
134 *a = Tpa::from((m & 0xf) as u8).quantize(*g)?;
135 m >>= 4;
136 }
137 debug_assert_eq!(m, 0);
138 Some(Self { a })
139 }
140}
141
142#[derive(Clone, Debug)]
144pub struct WdfState<const N: usize> {
145 pub z: [i32; N],
147}
148
149impl<const N: usize> Default for WdfState<N> {
150 fn default() -> Self {
151 Self { z: [0; N] }
152 }
153}
154
155impl<const N: usize, const M: u32> SplitProcess<i32, i32, WdfState<N>> for Wdf<N, M> {
156 #[inline]
157 fn process(&self, state: &mut WdfState<N>, x: i32) -> i32 {
158 let mut y = 0;
159 let (m, x, z) =
160 self.a
161 .iter()
162 .zip(state.z.iter_mut())
163 .fold((M, x, &mut y), |(m, mut x, y), (a, z)| {
164 [*y, x] = Tpa::from((m & 0xf) as u8).adapt([x, *z], *a);
165 (m >> 4, x, z)
166 });
167 debug_assert_eq!(m, 0);
168 *z = x;
169 y
170 }
171}
172
173impl<const N: usize, const M: u32> SplitInplace<i32, WdfState<N>> for Wdf<N, M> {}