use super::{Stream, Tag};
use num_complex::Complex;
pub struct FilterComplex {
buffer: Vec<Complex<f32>>,
taps: Vec<f32>,
}
impl FilterComplex {
pub fn with_taps(taps: &[f32]) -> Self {
let n_taps = taps.len();
Self {
buffer: vec![Complex::new(0.0, 0.0); n_taps * 2],
taps: taps.to_vec(),
}
}
fn dot(&self, data: &[Complex<f32>]) -> Complex<f32> {
let mut x = Complex::new(0.0, 0.0);
for (i, &tap) in self.taps.iter().enumerate() {
x += tap * data[i];
}
x
}
}
impl Stream<Complex<f32>, Complex<f32>> for FilterComplex {
fn receive(&mut self, data: &[Complex<f32>], _tag: &mut Tag) -> Vec<Complex<f32>> {
let mut output = Vec::with_capacity(data.len());
let n_taps = self.taps.len();
if data.len() < n_taps {
for &sample in data {
for i in 1..n_taps {
self.buffer[i - 1] = self.buffer[i];
}
self.buffer[n_taps - 1] = sample;
output.push(self.dot(&self.buffer[..n_taps]));
}
return output;
}
let mut ptr = n_taps - 1;
let tmp = 0..(n_taps - 1);
for j in tmp {
self.buffer[ptr] = data[j];
output.push(self.dot(&self.buffer[j..]));
ptr += 1;
}
for i in 0..(data.len() - n_taps + 1) {
output.push(self.dot(&data[i..]));
}
ptr = 0;
let tmp = (data.len() - n_taps + 1)..data.len();
for i in tmp {
self.buffer[ptr] = data[i];
ptr += 1;
}
output
}
fn reset(&mut self) {
self.buffer.fill(Complex::new(0.0, 0.0));
}
}
pub struct DownsampleKFilter {
k: usize,
buffer: Vec<Complex<f32>>,
taps: Vec<f32>,
count: usize,
}
impl DownsampleKFilter {
pub fn with_params(k: usize, taps: &[f32]) -> Self {
Self {
k,
buffer: vec![Complex::new(0.0, 0.0); taps.len() * 2],
taps: taps.to_vec(),
count: 0,
}
}
pub fn dot(&self, data: &[Complex<f32>]) -> Complex<f32> {
let mut x = Complex::new(0.0, 0.0);
for (i, &tap) in self.taps.iter().enumerate() {
x += tap * data[i];
}
x
}
}
impl Stream<Complex<f32>, Complex<f32>> for DownsampleKFilter {
fn receive(&mut self, data: &[Complex<f32>], _tag: &mut Tag) -> Vec<Complex<f32>> {
let mut output = Vec::with_capacity(data.len());
let n_taps = self.taps.len();
for &sample in data {
for i in (1..n_taps).rev() {
self.buffer[i] = self.buffer[i - 1];
}
self.buffer[0] = sample;
if self.count.is_multiple_of(self.k) {
let filtered = self.dot(&self.buffer);
output.push(filtered);
}
self.count += 1;
}
output
}
fn reset(&mut self) {
self.buffer.fill(Complex::new(0.0, 0.0));
self.count = 0
}
}
pub const COHERENT_TAPS: &[f32; 17] = &[
2.069_957_2e-6_f32,
3.186_101_5e-5_f32,
3.406_053e-4_f32,
2.528_929_9e-3_f32,
1.304_114_5e-2_f32,
4.670_767_5e-2_f32,
1.161_861_4e-1_f32,
2.007_307_9e-1_f32,
2.408_613_9e-1_f32,
2.007_307_9e-1_f32,
1.161_861_4e-1_f32,
4.670_767_5e-2_f32,
1.304_114_5e-2_f32,
2.528_929_9e-3_f32,
3.406_053e-4_f32,
3.186_101_5e-5_f32,
2.069_957_2e-6_f32,
];
pub const BLACKMAN_HARRIS_28_3: &[f32; 26] = &[
6.325_423_6e-5_f32,
-2.900_152_5e-4_f32,
-1.542_062_5e-3_f32,
-1.649_724_6e-3_f32,
3.127_939e-3_f32,
1.094_944_1e-2_f32,
9.049_758e-3_f32,
-1.436_858_4e-2_f32,
-4.456_159_5e-2_f32,
-3.448_836_5e-2_f32,
5.534_742_8e-2_f32,
2.018_279_1e-1_f32,
3.165_346e-1_f32,
3.165_346e-1_f32,
2.018_279_1e-1_f32,
5.534_742_8e-2_f32,
-3.448_836_5e-2_f32,
-4.456_159_5e-2_f32,
-1.436_858_4e-2_f32,
9.049_758e-3_f32,
1.094_944_1e-2_f32,
3.127_939e-3_f32,
-1.649_724_6e-3_f32,
-1.542_062_5e-3_f32,
-2.900_152_5e-4_f32,
6.325_423_6e-5_f32,
];