121 lines
2.8 KiB
Rust
121 lines
2.8 KiB
Rust
use num::traits::{Num, NumCast};
|
|
use std::iter::FromIterator;
|
|
|
|
pub struct Upsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone,
|
|
{
|
|
factor: u16,
|
|
state: u16,
|
|
sample: Option<NumType>,
|
|
iterator: Box<dyn Iterator<Item = NumType> + 'a>,
|
|
}
|
|
|
|
impl<'a, NumType> Upsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone,
|
|
{
|
|
pub fn from<I>(iterator: I, factor: u16) -> Upsampler<'a, NumType>
|
|
where
|
|
I: Iterator<Item = NumType> + 'a,
|
|
{
|
|
Upsampler {
|
|
factor: factor,
|
|
state: 0,
|
|
sample: Some(NumType::zero()),
|
|
iterator: Box::new(iterator),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, NumType> Iterator for Upsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone,
|
|
{
|
|
type Item = NumType;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
if self.state == 0 {
|
|
self.sample = self.iterator.next();
|
|
}
|
|
self.state = (self.state + 1) % self.factor;
|
|
|
|
return self.sample.clone();
|
|
}
|
|
}
|
|
|
|
pub struct Downsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone + NumCast,
|
|
{
|
|
factor: u16,
|
|
iterator: Box<dyn Iterator<Item = NumType> + 'a>,
|
|
}
|
|
|
|
impl<'a, NumType> Downsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone + NumCast,
|
|
{
|
|
pub fn from<I>(iterator: I, factor: u16) -> Downsampler<'a, NumType>
|
|
where
|
|
I: Iterator<Item = NumType> + 'a,
|
|
{
|
|
Downsampler {
|
|
factor: factor,
|
|
iterator: Box::new(iterator),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'a, NumType> Iterator for Downsampler<'a, NumType>
|
|
where
|
|
NumType: Num + Clone + NumCast,
|
|
{
|
|
type Item = NumType;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
let mut result = NumType::zero();
|
|
for _ in 0..self.factor {
|
|
match self.iterator.next() {
|
|
Some(x) => result = result + x,
|
|
None => return None,
|
|
}
|
|
}
|
|
result = result / NumType::from(self.factor).unwrap();
|
|
|
|
return Some(result);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn upsampler_test() {
|
|
let test_data = vec![1_f32, 2_f32, 3_f32, 4_f32, 5_f32];
|
|
|
|
let upsampler = Upsampler::from(test_data.into_iter(), 2);
|
|
|
|
let result_data = Vec::from_iter(upsampler);
|
|
assert_eq!(result_data.len(), 10);
|
|
assert_eq!(
|
|
result_data,
|
|
[1_f32, 1_f32, 2_f32, 2_f32, 3_f32, 3_f32, 4_f32, 4_f32, 5_f32, 5_f32]
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn downsampler_test() {
|
|
let test_data = vec![
|
|
1_f32, 1_f32, 2_f32, 2_f32, 3_f32, 3_f32, 4_f32, 4_f32, 5_f32, 5_f32,
|
|
];
|
|
|
|
let downsampler = Downsampler::from(test_data.into_iter(), 2);
|
|
|
|
let result_data = Vec::from_iter(downsampler);
|
|
assert_eq!(result_data.len(), 5);
|
|
assert_eq!(result_data, [1_f32, 2_f32, 3_f32, 4_f32, 5_f32]);
|
|
}
|
|
}
|