apt-decoder/src/aptsyncer.rs

119 lines
3.7 KiB
Rust

const SYNC_LENGHT : usize = 40;
const SYNCA_SEQ : [bool; 40] = [false, false, false, false,
true, true, false, false, // Pulse 1
true, true, false, false, // Pulse 2
true, true, false, false, // Pulse 3
true, true, false, false, // Pulse 4
true, true, false, false, // Pulse 5
true, true, false, false, // Pulse 6
true, true, false, false, // Pulse 7
false, false, false, false,
false, false, false, false,];
const SYNCB_SEQ : [bool; 40] = [false, false, false, false,
true, true, true, false, false,
true, true, true, false, false,
true, true, true, false, false,
true, true, true, false, false,
true, true, true, false, false,
true, true, true, false, false,
true, true, true, false, false,
false];
pub enum SyncedSample {
Sample(f32),
SyncA(f32),
SyncB(f32)
}
pub struct APTSyncer<'a> {
state: [f32; SYNC_LENGHT],
pos : usize,
nones_read: usize,
avg_level : f32,
iterator: Box<Iterator<Item=f32> + 'a>
}
impl<'a> APTSyncer<'a> {
pub fn from<I>(mut iterator: I) -> APTSyncer<'a> where I: Iterator<Item=f32> + 'a {
let mut state = [0.0; SYNC_LENGHT];
let mut avg_level = 0.5;
for i in 0..SYNC_LENGHT {
match iterator.next() {
Some(x) => {
state[i] = x;
avg_level = 0.25 * x + avg_level * 0.75;
},
None => panic!("Could not retrieve enough samples to prime syncer")
}
}
APTSyncer {
state: state,
pos: 0,
nones_read: 0,
avg_level: avg_level,
iterator: Box::new(iterator)
}
}
fn is_marker(&mut self) -> (bool, bool) {
let mut count_a = 0;
let mut count_b = 0;
for i in 0..SYNC_LENGHT {
let sync_pos = (self.pos + i) % SYNC_LENGHT;
let sample = self.state[sync_pos] / (self.avg_level * 2.0);
if (sample > 0.5 && SYNCA_SEQ[i]) || (sample <= 0.5 && !SYNCA_SEQ[i]) {
count_a += 1;
}
if (sample > 0.5 && SYNCB_SEQ[i]) || (sample <= 0.5 && !SYNCB_SEQ[i]) {
count_b += 1;
}
/*
if !count_a && !count_b {
break;
}
*/
}
return (count_a > 35, count_b > 35);
}
}
impl<'a> Iterator for APTSyncer<'a> {
type Item = SyncedSample;
fn next(&mut self) -> Option<Self::Item> {
let (is_a, is_b) = self.is_marker();
let sample = self.state[self.pos];
match self.iterator.next() {
Some(x) => {
self.state[self.pos] = x;
self.avg_level = 0.25 * x + self.avg_level * 0.75;
},
None => self.nones_read += 1
};
if self.nones_read >= SYNC_LENGHT {
return None;
}
self.pos = (self.pos + 1) % SYNC_LENGHT;
if is_a {
return Some(SyncedSample::SyncA(sample));
}
else if is_b {
return Some(SyncedSample::SyncB(sample));
}
else {
return Some(SyncedSample::Sample(sample));
}
}
}