use num_complex::Complex32 as C32;
use crate::core::{Block, WorkReport};
use crate::dsp::LpCascade;
use crate::util::atan2_approx;
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct PmQuadratureDemod {
fs: f32, k: f32, post_lp: LpCascade,
prev: C32, }
impl PmQuadratureDemod {
pub fn new(fs: f32, k: f32, audio_bw_hz: f32) -> Self {
let lp = LpCascade::design(fs, audio_bw_hz * 0.9);
Self {
fs,
k,
post_lp: lp,
prev: C32::new(1.0, 0.0),
}
}
}
impl Block for PmQuadratureDemod {
type In = C32;
type Out = f32;
#[inline(always)]
fn process(&mut self, input: &[Self::In], output: &mut [Self::Out]) -> WorkReport {
let n = input.len().min(output.len());
if n == 0 {
return WorkReport { in_read: 0, out_written: 0 };
}
let mut prev = self.prev;
for i in 0..n {
let z = input[i];
let w = z * prev.conj();
output[i] = self.post_lp.process(self.k * atan2_approx(w.im, w.re));
prev = z;
}
self.prev = prev;
WorkReport { in_read: n, out_written: n }
}
}