rusty-dsp/src/firfilter.rs

82 lines
2.0 KiB
Rust
Raw Permalink Normal View History

2020-03-17 22:41:25 +01:00
use num::traits::Num;
2020-06-03 21:54:48 +02:00
use super::error::DspError;
2020-03-17 22:41:25 +01:00
pub struct FIRFilter<'a, NumType>
where
2020-05-22 17:33:30 +02:00
NumType: Num + Copy,
{
2020-03-17 22:41:25 +01:00
coeffs: &'a [NumType],
state: Vec<NumType>,
2020-03-14 23:08:57 +01:00
pos: usize,
2020-06-03 21:54:48 +02:00
iterator: Box<dyn Iterator<Item = Result<NumType, DspError>> + 'a>,
2020-03-14 23:08:57 +01:00
}
2020-03-17 22:41:25 +01:00
impl<'a, NumType> FIRFilter<'a, NumType>
where
2020-05-22 17:33:30 +02:00
NumType: Num + Copy,
{
2020-03-17 22:41:25 +01:00
pub fn from<I>(iterator: I, coeffs: &'a [NumType]) -> FIRFilter<'a, NumType>
2020-03-14 23:08:57 +01:00
where
2020-06-03 21:54:48 +02:00
I: Iterator<Item = Result<NumType, DspError>> + 'a,
2020-03-14 23:08:57 +01:00
{
let mut state = Vec::new();
for _ in 0..coeffs.len() {
2020-03-17 22:41:25 +01:00
state.push(NumType::zero());
2020-03-14 23:08:57 +01:00
}
FIRFilter {
coeffs: coeffs,
state: state,
pos: 0,
iterator: Box::new(iterator),
}
}
}
2020-03-17 22:41:25 +01:00
impl<'a, NumType> Iterator for FIRFilter<'a, NumType>
2020-05-22 17:33:30 +02:00
where
NumType: Num + Copy,
{
2020-06-03 21:54:48 +02:00
type Item = Result<NumType, DspError>;
2020-03-14 23:08:57 +01:00
2020-06-03 21:54:48 +02:00
fn next(&mut self) -> Option<Self::Item> {
2020-03-14 23:08:57 +01:00
let cur = match self.iterator.next() {
2020-06-03 21:54:48 +02:00
Some(Ok(x)) => x,
Some(Err(e)) => return Some(Err(e)),
2020-03-14 23:08:57 +01:00
None => return None,
};
self.pos = (self.pos + 1) % self.coeffs.len();
self.state[self.pos] = cur;
2020-03-17 22:41:25 +01:00
let mut result = NumType::zero();
2020-03-14 23:08:57 +01:00
for i in 0..self.coeffs.len() {
let pos = (self.pos + self.coeffs.len() - i) % self.coeffs.len();
2020-06-03 21:54:48 +02:00
result = result + (self.state[pos] * self.coeffs[i]);
2020-03-14 23:08:57 +01:00
}
2020-06-03 21:54:48 +02:00
Some(Ok(result))
2020-03-14 23:08:57 +01:00
}
}
2020-03-17 22:41:25 +01:00
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn fir_avg_test() {
let test_data = vec![0_f32, 1_f32, 2_f32, 3_f32, 4_f32, 5_f32, 6_f32, 7_f32];
2020-06-03 21:54:48 +02:00
let upsampler = FIRFilter::from(test_data.into_iter().map(|x| Ok(x)), &[0.5_f32, 0.5_f32]);
2020-03-17 22:41:25 +01:00
2020-06-03 21:54:48 +02:00
let result_data: Result<Vec<f32>, DspError> = upsampler.collect();
2020-03-17 22:41:25 +01:00
assert_eq!(
result_data,
2020-06-03 21:54:48 +02:00
Ok(vec![
0.0_f32, 0.5_f32, 1.5_f32, 2.5_f32, 3.5_f32, 4.5_f32, 5.5_f32, 6.5_f32
]),
2020-03-17 22:41:25 +01:00
);
}
}