80 lines
1.6 KiB
Rust
80 lines
1.6 KiB
Rust
#![allow(unused_parens)]
|
|
|
|
use std::io::prelude::*;
|
|
use std::fs::File;
|
|
use std::env::args;
|
|
|
|
fn main()
|
|
{
|
|
let argv = args().collect::<Vec<String>>();
|
|
if argv.len() != 4
|
|
{
|
|
eprintln!("usage: skew <offset‰> <mismatch‰> <target.dat>");
|
|
return;
|
|
}
|
|
// offset: permil phase offset in transmission from receiver
|
|
// mismatch: permil frequency error in transmission sample rate from receiver sample rate
|
|
|
|
let offset =
|
|
(
|
|
argv[1]
|
|
.parse::<f32>()
|
|
.unwrap()
|
|
/ 1000.0
|
|
);
|
|
let mismatch =
|
|
(
|
|
argv[2]
|
|
.parse::<f32>()
|
|
.unwrap()
|
|
.max(-999.0) // no closer to 0 than 1 permil
|
|
/ 1000.0
|
|
);
|
|
|
|
let mut input = File::open(&argv[3]).unwrap();
|
|
let mut data:Vec<f32> = Vec::new();
|
|
loop
|
|
{
|
|
let mut buffer:[u8;4] = [0x00;4];
|
|
match input.read_exact(&mut buffer)
|
|
{
|
|
Ok(_) => (),
|
|
Err(_) => break,
|
|
};
|
|
data.push(f32::from_be_bytes(buffer));
|
|
}
|
|
|
|
let output_length =
|
|
(
|
|
(
|
|
data.len() as f32
|
|
/
|
|
(1.0 + mismatch)
|
|
)
|
|
as usize
|
|
);
|
|
|
|
let mut result:Vec<f32> = Vec::with_capacity(output_length);
|
|
for i in 0..output_length
|
|
{
|
|
let skew = offset + (i as f32) * mismatch;
|
|
let shift = skew.floor() as usize;
|
|
let upper_misalign = skew.fract();
|
|
let lower_misalign = 1.0 - skew.fract();
|
|
|
|
result.push(
|
|
upper_misalign * data[(i + shift + 1) % data.len()]
|
|
+
|
|
lower_misalign * data[(i + shift + 0) % data.len()]
|
|
);
|
|
}
|
|
|
|
let mut output = File::create(&argv[3]).unwrap();
|
|
let mut output_buffer:Vec<u8> = Vec::with_capacity(data.len() * 4);
|
|
for &point in result.iter()
|
|
{
|
|
output_buffer.extend_from_slice(&point.to_be_bytes());
|
|
}
|
|
output.write_all(&output_buffer).unwrap();
|
|
}
|