1#![feature(conservative_impl_trait)]
63
64use std::ops::{Add, Mul, Deref, DerefMut};
65
66pub trait FirCoefs: Default + Deref<Target = [<Self as FirCoefs>::Sample]> + DerefMut {
68 type Sample: Copy + Clone + Default + Add<Output = Self::Sample> +
70 Mul<f32, Output = Self::Sample>;
71
72 fn size() -> usize;
74 fn coefs() -> &'static [f32];
76
77 fn verify_symmetry() {
80 for i in 0..Self::size() / 2 {
81 assert_eq!(Self::coefs()[i], Self::coefs()[Self::size() - i - 1]);
82 }
83 }
84}
85
86#[macro_export]
89macro_rules! impl_fir {
90 ($name:ident, $sample:ty, $size:expr, $coefs:expr) => {
91 pub struct $name([$sample; $size]);
92
93 impl $crate::FirCoefs for $name {
94 type Sample = $sample;
95 fn size() -> usize { $size }
96 fn coefs() -> &'static [f32] {
97 static COEFS: [f32; $size] = $coefs;
98 &COEFS[..]
99 }
100 }
101
102 impl Default for $name {
103 fn default() -> Self {
104 $name([<Self as $crate::FirCoefs>::Sample::default(); $size])
105 }
106 }
107
108 impl std::ops::Deref for $name {
109 type Target = [$sample];
110 fn deref(&self) -> &Self::Target { &self.0[..] }
111 }
112
113 impl std::ops::DerefMut for $name {
114 fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0[..] }
115 }
116 };
117}
118
119pub struct FirFilter<C: FirCoefs> {
121 inner: C,
123 idx: usize,
125}
126
127impl<C: FirCoefs> FirFilter<C> {
128 pub fn new() -> FirFilter<C> {
130 FirFilter {
131 inner: C::default(),
132 idx: 0,
133 }
134 }
135
136 pub fn feed(&mut self, sample: C::Sample) -> C::Sample {
138 self.inner[self.idx] = sample;
140
141 self.idx += 1;
143 self.idx %= C::size();
144
145 self.calc()
146 }
147
148 fn calc(&self) -> C::Sample {
151 let (hleft, hright) = self.inner.split_at(self.idx);
152 let (cleft, cright) = C::coefs().split_at(C::size() - self.idx);
153
154 cleft.iter().zip(hright)
155 .fold(C::Sample::default(), |s, (&c, &x)| s + x * c) +
156 cright.iter().zip(hleft)
157 .fold(C::Sample::default(), |s, (&c, &x)| s + x * c)
158 }
159
160 #[inline]
163 pub fn history<'a>(&'a self) -> impl Iterator<Item = &'a C::Sample> {
164 let (left, right) = self.inner.split_at(self.idx);
165 right.iter().chain(left.iter())
166 }
167
168 pub fn history_unordered<'a>(&'a self) -> impl Iterator<Item = &'a C::Sample> {
174 self.inner.iter()
175 }
176}
177
178#[cfg(test)]
179mod test {
180 use super::*;
181
182 impl_fir!(TestFIR, f32, 4, [
183 1.0,
184 0.0,
185 2.0,
186 0.0,
187 ]);
188
189 impl_fir!(SymmetricOddFIR, f32, 5, [
190 0.2,
191 0.4,
192 1.0,
193 0.4,
194 0.2,
195 ]);
196
197 impl_fir!(SymmetricEvenFIR, f32, 6, [
198 0.2,
199 0.4,
200 1.0,
201 1.0,
202 0.4,
203 0.2,
204 ]);
205
206 impl_fir!(NonSymmetricOddFIR, f32, 5, [
207 0.2,
208 0.4,
209 1.0,
210 0.5,
211 0.2,
212 ]);
213
214 impl_fir!(NonSymmetricEvenFIR, f32, 6, [
215 0.2,
216 0.4,
217 1.0,
218 1.0,
219 0.5,
220 0.2,
221 ]);
222
223 #[test]
224 fn test_fir() {
225 let mut f = FirFilter::<TestFIR>::new();
226
227 assert!(f.feed(100.0) == 0.0);
228 assert!(f.feed(200.0) == 200.0);
229 assert!(f.feed(300.0) == 400.0);
230 assert!(f.feed(400.0) == 700.0);
231 assert!(f.feed(0.0) == 1000.0);
232 assert!(f.feed(0.0) == 300.0);
233 assert!(f.feed(0.0) == 400.0);
234 assert!(f.feed(0.0) == 0.0);
235 assert!(f.feed(0.0) == 0.0);
236 assert!(f.feed(100.0) == 0.0);
237 assert!(f.feed(200.0) == 200.0);
238 assert!(f.feed(300.0) == 400.0);
239 assert!(f.feed(400.0) == 700.0);
240
241 let mut iter = f.history();
242
243 assert_eq!(iter.next().unwrap(), &100.0);
244 assert_eq!(iter.next().unwrap(), &200.0);
245 assert_eq!(iter.next().unwrap(), &300.0);
246 assert_eq!(iter.next().unwrap(), &400.0);
247
248 let mut iter = f.history_unordered();
249
250 assert_eq!(iter.next().unwrap(), &400.0);
251 assert_eq!(iter.next().unwrap(), &100.0);
252 assert_eq!(iter.next().unwrap(), &200.0);
253 assert_eq!(iter.next().unwrap(), &300.0);
254 }
255
256 #[test]
257 fn test_verify_symmetry() {
258 SymmetricOddFIR::verify_symmetry();
259 SymmetricEvenFIR::verify_symmetry();
260 }
261
262 #[test]
263 #[should_panic]
264 fn test_verify_nonsymmetry_odd() {
265 NonSymmetricOddFIR::verify_symmetry();
266 }
267
268 #[test]
269 #[should_panic]
270 fn test_verify_nonsymmetry_even() {
271 NonSymmetricEvenFIR::verify_symmetry();
272 }
273}