use super::FirLowpass;
use crate::core::{Block, WorkReport};
use num_complex::Complex32 as C32;
#[derive(Debug, Clone)]
pub struct FirDecimator {
fs: f32,
m: usize,
lp_i: FirLowpass,
lp_q: FirLowpass,
ri: Vec<f32>,
rq: Vec<f32>,
yi: Vec<f32>,
yq: Vec<f32>,
}
impl FirDecimator {
pub fn new(fs: f32, m: usize, cutoff_hz: f32, trans_hz: f32) -> Self {
let lp_i = FirLowpass::design(fs, cutoff_hz, trans_hz);
let lp_q = FirLowpass::design(fs, cutoff_hz, trans_hz);
Self {
fs,
m: m.max(1),
lp_i,
lp_q,
ri: Vec::new(),
rq: Vec::new(),
yi: Vec::new(),
yq: Vec::new(),
}
}
}
impl Block for FirDecimator {
type In = C32;
type Out = C32;
fn process(&mut self, input: &[Self::In], output: &mut [Self::Out]) -> WorkReport {
let n = input.len();
if self.ri.len() < n {
self.ri.resize(n, 0.0);
self.rq.resize(n, 0.0);
}
if self.yi.len() < n {
self.yi.resize(n, 0.0);
self.yq.resize(n, 0.0);
}
for (k, s) in input.iter().enumerate().take(n) {
self.ri[k] = s.re;
self.rq[k] = s.im;
}
self.lp_i.process(&self.ri[..n], &mut self.yi[..n]);
self.lp_q.process(&self.rq[..n], &mut self.yq[..n]);
let m = self.m;
let n_out = n.div_ceil(m);
let n_write = n_out.min(output.len());
for (j, out) in output.iter_mut().enumerate().take(n_write) {
let k = j * m;
*out = C32::new(self.yi[k], self.yq[k]);
}
WorkReport {
in_read: n,
out_written: n_write,
}
}
}