use num::traits::Num; use std::iter::FromIterator; pub struct FIRFilter<'a, NumType> where NumType: Num + Copy { coeffs: &'a [NumType], state: Vec, pos: usize, iterator: Box + 'a>, } impl<'a, NumType> FIRFilter<'a, NumType> where NumType: Num + Copy { pub fn from(iterator: I, coeffs: &'a [NumType]) -> FIRFilter<'a, NumType> where I: Iterator + 'a, { let mut state = Vec::new(); for _ in 0..coeffs.len() { state.push(NumType::zero()); } FIRFilter { coeffs: coeffs, state: state, pos: 0, iterator: Box::new(iterator), } } } impl<'a, NumType> Iterator for FIRFilter<'a, NumType> where NumType: Num + Copy { type Item = NumType; fn next(&mut self) -> Option { let cur = match self.iterator.next() { Some(x) => x, None => return None, }; self.pos = (self.pos + 1) % self.coeffs.len(); self.state[self.pos] = cur; let mut result = NumType::zero(); for i in 0..self.coeffs.len() { let pos = (self.pos + self.coeffs.len() - i) % self.coeffs.len(); result = result + (self.state[pos] * self.coeffs[i].clone()); } Some(result) } } #[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]; let upsampler = FIRFilter::from(test_data.into_iter(), &[0.5_f32, 0.5_f32]); let result_data = Vec::from_iter(upsampler); assert_eq!(result_data.len(), 8); assert_eq!( result_data, [0.0_f32, 0.5_f32, 1.5_f32, 2.5_f32, 3.5_f32, 4.5_f32, 5.5_f32, 6.5_f32] ); } }