75 lines
2.0 KiB
Rust
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
|
|
])
|
|
);
|
|
}
|
|
}
|