use crate::block::{Block, BlockRet};
use crate::fir::FIR;
use crate::stream::{new_streamp, Streamp};
use crate::{Complex, Error, Float};
pub struct Hilbert {
src: Streamp<Float>,
dst: Streamp<Complex>,
history: Vec<Float>,
filter: FIR<Float>,
ntaps: usize,
}
impl Hilbert {
pub fn new(src: Streamp<Float>, ntaps: usize) -> Self {
assert!(ntaps & 1 == 1, "hilbert filter len must be odd");
let taps = crate::fir::hilbert(ntaps); Self {
src,
ntaps,
dst: new_streamp(),
history: vec![0.0; ntaps],
filter: FIR::new(&taps),
}
}
pub fn out(&self) -> Streamp<Complex> {
self.dst.clone()
}
}
impl Block for Hilbert {
fn block_name(&self) -> &'static str {
"Hilbert"
}
fn work(&mut self) -> Result<BlockRet, Error> {
assert_eq!(self.ntaps, self.history.len());
let (i, tags) = self.src.read_buf()?;
if i.is_empty() {
return Ok(BlockRet::Noop);
}
let mut o = self.dst.write_buf()?;
if o.is_empty() {
return Ok(BlockRet::Ok);
}
let inout = std::cmp::min(i.len(), o.len());
let len = self.history.len() + inout;
let n = len - self.ntaps;
let mut iv = Vec::with_capacity(len);
iv.extend(&self.history);
iv.extend(i.iter().take(inout).copied());
for i in 0..n {
let t = &iv[i..(i + self.ntaps)];
o.slice()[i] = Complex::new(iv[i + self.ntaps / 2], self.filter.filter(t));
}
o.produce(n, &tags);
self.history[..self.ntaps].clone_from_slice(&iv[n..len]);
i.consume(n);
Ok(BlockRet::Ok)
}
}