Panics
Will panic if the const generic N is zero, or if either of the coefficients arrays is not
length N + 1.
19 #[must_use] 20 pub fn new(b: &[f64], a: &[f64]) -> Self { 21 assert!(N > 0); 22 assert_eq!(b.len(), N + 1); 23 assert_eq!(a.len(), N + 1); 24 25 Self { 26 b0: b[0], 27 b: b[1..].try_into().unwrap(), 28 a: a[1..].try_into().unwrap(), 29 prev_samples: array::from_fn(|_| 0.0), 30 prev_outputs: array::from_fn(|_| 0.0), 31 tiny_offset: 1e-30, 32 } 33 }
Returns a filter that simply returns input samples as-is
48 #[must_use] 49 pub fn filter(&mut self, sample: f64) -> f64 { 50 // Hack to avoid the filter getting stuck at a subnormal value 51 // See <https://www.earlevel.com/main/2019/04/19/floating-point-denormals/> 52 let sample = sample + self.tiny_offset; 53 self.tiny_offset = -self.tiny_offset; 54 55 let output = self.b0 * sample 56 + iter::zip(&self.b, &self.prev_samples).map(|(&coeff, &n)| coeff * n).sum::<f64>() 57 - iter::zip(&self.a, &self.prev_outputs).map(|(&coeff, &n)| coeff * n).sum::<f64>(); 58 59 for i in (1..N).rev() { 60 self.prev_samples[i] = self.prev_samples[i - 1]; 61 self.prev_outputs[i] = self.prev_outputs[i - 1]; 62 } 63 self.prev_samples[0] = sample; 64 self.prev_outputs[0] = output; 65 66 output 67 } 68 69 pub fn reset(&mut self) { 70 self.prev_samples.fill(0.0); 71 self.prev_outputs.fill(0.0); 72 } 73} 74 75pub type FirstOrderIirFilter = IirFilter<1>; 76pub type SecondOrderIirFilter = IirFilter<2>;