pounder_test/dsp/src/lowpass.rs

36 lines
1.0 KiB
Rust
Raw Normal View History

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-11 21:30:05 +08:00
/// Type argument N is the filter order.
#[derive(Clone, Default)]
pub struct Lowpass<N: ArrayLength<i32>> {
// IIR state storage
2021-02-11 21:30:05 +08:00
y: GenericArray<i32, N>,
}
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 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);
// 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-11 21:30:05 +08:00
x
}
}