use num_complex::Complex; use std::error::Error; use std::fs::File; use std::io::{BufReader, ErrorKind, Read}; pub type IqSample = Complex; // Data chunk // #[derive(Debug)] // pub struct IqChunk { // pub samples: Vec, // } // // impl IqChunk { // pub fn new() -> Self { // IqChunk { // samples: Vec::::new(), // } // } // } pub struct FileSource { // Buffer pub reader: BufReader, // Hackrf I & Q 8 bits pub raw_buffer: Vec, // 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> { 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>; fn size_hint(&self) -> (usize, Option) { (self.len as usize, Some(self.len as usize)) } fn next(&mut self) -> Option { 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))) } }