Files
analog-sdr-video-demodulator/src/iq_reader.rs
2026-06-15 22:31:07 +02:00

91 lines
2.3 KiB
Rust

use num_complex::Complex;
use std::error::Error;
use std::fs::File;
use std::io::{BufReader, ErrorKind, Read};
pub type IqSample = Complex<f32>;
// Data chunk
// #[derive(Debug)]
// pub struct IqChunk {
// pub samples: Vec<IqSample>,
// }
//
// impl IqChunk {
// pub fn new() -> Self {
// IqChunk {
// samples: Vec::<IqSample>::new(),
// }
// }
// }
pub struct FileSource {
// Buffer
pub reader: BufReader<File>,
// Hackrf I & Q 8 bits
pub raw_buffer: Vec<u8>,
// Size of a sample chunk
pub chunk_samples_size: usize,
// raw_buffer position (in samples)
pub cursor: usize,
// The length of the file in samples
pub len: u64,
}
impl FileSource {
pub fn new(file_path: &str, chunk_samples_size: usize) -> Result<Self, Box<dyn Error>> {
let file = File::open(file_path)?;
let len = file.metadata().unwrap().len() / 2;
// Init buffer with size 16 Mo
let reader = BufReader::with_capacity(16 * 1024 * 1024, file);
// 1 sample = 2 bytes (1 byte : I, 1 byte : Q)
let raw_reader = vec![0; chunk_samples_size * 2];
Ok(Self {
reader,
raw_buffer: raw_reader,
chunk_samples_size,
cursor: chunk_samples_size,
len,
})
}
}
impl ExactSizeIterator for FileSource {}
impl Iterator for FileSource {
type Item = Result<IqSample, Box<dyn Error>>;
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len as usize, Some(self.len as usize))
}
fn next(&mut self) -> Option<Self::Item> {
if self.cursor >= self.chunk_samples_size {
// Buffer read chunk
match self.reader.read_exact(&mut self.raw_buffer) {
Ok(_) => {}
// EOF
Err(e) if e.kind() == ErrorKind::UnexpectedEof => {
return None;
}
Err(e) => {
return Some(Err(e.into()));
}
}
self.cursor = 0;
}
// Buffer read sample
let i = (self.raw_buffer[self.cursor * 2] as i8) as f32 / 128.0;
let q = (self.raw_buffer[self.cursor * 2 + 1] as i8) as f32 / 128.0;
self.cursor += 1;
Some(Ok(IqSample::new(i, q)))
}
}