rusty-tty/src/bitupsampler.rs

75 lines
2.0 KiB
Rust

extern crate rusty_dsp;
use rusty_dsp::error::DspError;
pub struct BitUpsampler<'a> {
bit_length: f64,
current_bit_length: usize,
pos: usize,
residual_error: f64,
current_bit: bool,
iterator: Box<dyn Iterator<Item = Result<bool, DspError>> + 'a>,
}
impl<'a> BitUpsampler<'a> {
pub fn from<I>(iterator: I, sampling_rate: f64, baud_rate: f64) -> BitUpsampler<'a>
where
I: Iterator<Item = Result<bool, DspError>> + 'a,
{
BitUpsampler {
bit_length: sampling_rate / baud_rate,
current_bit_length: 0,
residual_error: 0.0,
pos: 0,
current_bit: false,
iterator: Box::new(iterator),
}
}
}
impl<'a> Iterator for BitUpsampler<'a> {
type Item = Result<bool, DspError>;
fn next(&mut self) -> Option<Self::Item> {
if self.pos >= self.current_bit_length {
self.current_bit = match self.iterator.next() {
None => return None,
Some(Err(e)) => return Some(Err(e)),
Some(Ok(b)) => b,
};
self.current_bit_length = self.bit_length.floor() as usize;
self.residual_error += self.bit_length - self.bit_length.floor();
if self.residual_error >= 1.0 {
self.residual_error -= 1.0;
self.current_bit_length += 1;
}
self.pos = 0;
}
self.pos += 1;
Some(Ok(self.current_bit))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_baurate_error_correction() {
let input = vec![true, false, true, false];
let upsampler = BitUpsampler::from(input.into_iter().map(|x| Ok(x)), 10.0, 4.0);
let result_data: Result<Vec<bool>, DspError> = upsampler.collect();
assert_eq!(
result_data,
Ok(vec![
true, true, false, false, false, true, true, false, false, false
])
);
}
}