2021-02-10 01:30:50 +08:00
|
|
|
use generic_array::{ArrayLength, GenericArray};
|
|
|
|
|
|
|
|
/// Arbitrary order, high dynamic range, wide coefficient range,
|
|
|
|
/// lowpass filter implementation.
|
|
|
|
///
|
|
|
|
/// Type argument N is the filter order + 1.
|
|
|
|
#[derive(Clone, Default)]
|
|
|
|
pub struct Lowpass<N: ArrayLength<i32>> {
|
|
|
|
// IIR state storage
|
|
|
|
xy: GenericArray<i32, N>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<N: ArrayLength<i32>> Lowpass<N> {
|
|
|
|
/// Update the filter with a new sample.
|
|
|
|
///
|
|
|
|
/// # Args
|
|
|
|
/// * `x`: Input data
|
2021-02-10 16:46:49 +08:00
|
|
|
/// * `k`: Log2 time constant
|
2021-02-10 01:30:50 +08:00
|
|
|
///
|
2021-02-10 16:46:49 +08:00
|
|
|
/// # Return
|
2021-02-10 01:30:50 +08:00
|
|
|
/// Filtered output y
|
2021-02-10 16:46:49 +08:00
|
|
|
pub fn update(&mut self, x: i32, k: u8) -> i32 {
|
2021-02-10 01:30:50 +08:00
|
|
|
// This is an unrolled and optimized first-order IIR loop
|
|
|
|
// that works for all possible time constants.
|
2021-02-10 16:46:49 +08:00
|
|
|
// Note the zero(s) at Nyquist and the benign overflow (DF-I).
|
|
|
|
let mut x0 = x;
|
|
|
|
let mut x1 = self.xy[0];
|
2021-02-10 20:31:41 +08:00
|
|
|
self.xy[0] = x0;
|
2021-02-10 01:30:50 +08:00
|
|
|
for y1 in self.xy[1..].iter_mut() {
|
2021-02-10 20:27:56 +08:00
|
|
|
x0 = *y1 + (((x0 >> 1) + (x1 >> 1) - *y1 + (1 << (k - 1))) >> k);
|
2021-02-10 01:30:50 +08:00
|
|
|
x1 = *y1;
|
|
|
|
*y1 = x0;
|
|
|
|
}
|
|
|
|
x0
|
|
|
|
}
|
|
|
|
}
|