Skip to main content

scope/input/
file.rs

1use std::{
2	fs::File,
3	io::{self, Read},
4};
5
6use super::{
7	format::{SampleParser, Signed16PCM},
8	stream_to_matrix, Matrix,
9};
10
11/// Reads the file into the buffer until the buffer is full or the EOF is reached.
12///
13/// If it reaches the EOF before the buffer is full pad the buffer with zeros.
14pub fn read_with_padding(file: &mut File, buffer: &mut [u8]) -> io::Result<()> {
15	let mut read_so_far = 0;
16
17	while read_so_far < buffer.len() {
18		let remaining_slice = &mut buffer[read_so_far..];
19
20		let n = file.read(remaining_slice)?;
21		if n > 0 {
22			read_so_far += n;
23		} else {
24			// End of File reached -> pad with zeros
25			// buffer: [........0000]
26			for b in remaining_slice {
27				*b = 0;
28			}
29
30			return Ok(());
31		}
32	}
33
34	Ok(())
35}
36
37pub struct FileSource {
38	file: File,
39	buffer: Vec<u8>,
40	channels: usize,
41	limit_rate: bool,
42	ms_sleep: u64,
43	// TODO support more formats
44}
45
46impl FileSource {
47	#[allow(clippy::new_ret_no_self)]
48	pub fn new(
49		path: &str,
50		opts: &crate::cfg::SourceOptions,
51		limit_rate: bool,
52	) -> Result<Box<dyn super::DataSource<f64>>, std::io::Error> {
53		let samples_per_batch = (opts.buffer * opts.channels as u32) / 2;
54		let batches_per_second = opts.sample_rate / samples_per_batch;
55		let ms_sleep = (1000 / batches_per_second) as u64;
56		Ok(Box::new(FileSource {
57			channels: opts.channels,
58			limit_rate,
59			ms_sleep,
60			file: File::open(path)?,
61			buffer: vec![0u8; opts.buffer as usize * opts.channels],
62		}))
63	}
64}
65
66impl super::DataSource<f64> for FileSource {
67	fn recv(&mut self) -> Option<Matrix<f64>> {
68		if self.limit_rate {
69			std::thread::sleep(std::time::Duration::from_millis(self.ms_sleep));
70		}
71		match read_with_padding(&mut self.file, &mut self.buffer) {
72			Ok(()) => Some(stream_to_matrix(
73				self.buffer.chunks(2).map(Signed16PCM::parse),
74				self.channels,
75				32768.0,
76			)),
77			Err(_e) => None, // TODO log it
78		}
79	}
80}