2021-02-10 01:30:50 +08:00
|
|
|
use generic_array::{ArrayLength, GenericArray};
|
|
|
|
|
|
|
|
/// Arbitrary order, high dynamic range, wide coefficient range,
|
2021-02-11 21:30:05 +08:00
|
|
|
/// lowpass filter implementation. DC gain is 1.
|
2021-02-10 01:30:50 +08:00
|
|
|
///
|
2021-02-11 21:30:05 +08:00
|
|
|
/// Type argument N is the filter order.
|
2021-02-10 01:30:50 +08:00
|
|
|
#[derive(Clone, Default)]
|
|
|
|
pub struct Lowpass<N: ArrayLength<i32>> {
|
|
|
|
// IIR state storage
|
2021-02-11 21:30:05 +08:00
|
|
|
y: GenericArray<i32, N>,
|
2021-02-10 01:30:50 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<N: ArrayLength<i32>> Lowpass<N> {
|
|
|
|
/// Update the filter with a new sample.
|
|
|
|
///
|
|
|
|
/// # Args
|
2021-02-12 01:14:28 +08:00
|
|
|
/// * `x`: Input data
|
2021-02-11 21:30:05 +08:00
|
|
|
/// * `k`: Log2 time constant, 0..31
|
2021-02-10 01:30:50 +08:00
|
|
|
///
|
2021-02-10 16:46:49 +08:00
|
|
|
/// # Return
|
2021-02-12 01:14:28 +08:00
|
|
|
/// Filtered output y, needs `k` bits headroom
|
2021-02-10 16:46:49 +08:00
|
|
|
pub fn update(&mut self, x: i32, k: u8) -> i32 {
|
2021-02-11 21:30:05 +08:00
|
|
|
debug_assert!(k & 31 == k);
|
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-12 01:14:28 +08:00
|
|
|
// Note DF-II and the zeros at Nyquist.
|
2021-02-11 21:30:05 +08:00
|
|
|
let mut x = x;
|
|
|
|
for y in self.y.iter_mut() {
|
|
|
|
let dy = x - (*y >> k);
|
|
|
|
*y += dy;
|
|
|
|
x = (*y - (dy >> 1)) >> k;
|
2021-02-10 01:30:50 +08:00
|
|
|
}
|
2021-02-11 21:30:05 +08:00
|
|
|
x
|
2021-02-10 01:30:50 +08:00
|
|
|
}
|
|
|
|
}
|