diff --git a/src/config.rs b/src/config.rs index 3370f98..bb7da1c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,6 @@ // definitions for the FFT pub const BLOCK_LEN: usize = 512; pub const SAMP_RATE: f32 = 48000.0; + +// samples read from stdin per update +pub const SAMPLES_PER_UPDATE: usize = BLOCK_LEN/2; diff --git a/src/main.rs b/src/main.rs index 2f18e15..2632fd3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ // vim: noet use std::process::exit; +use std::collections::VecDeque; use byteorder::{NativeEndian, ReadBytesExt}; @@ -34,17 +35,24 @@ fn main() println!("Done! Starting main loop…"); // array for samples directly read from stream - let mut samples = [0i16; config::BLOCK_LEN]; + let mut samples: VecDeque = VecDeque::with_capacity(config::BLOCK_LEN); // main loop loop { // read a block of samples and exit gracefully on EOF - for sample in samples.iter_mut() { + for _i in 0 .. config::SAMPLES_PER_UPDATE { + // avoid increasing the size of the deque + if samples.len() == config::BLOCK_LEN { + samples.pop_front(); + } + + // read a sample from the input let res = stdin.read_i16::(); + // if everything is ok, append it to the samples deque match res { - Ok(s) => *sample = s, + Ok(s) => samples.push_back(s), Err(e) if e.kind() == std::io::ErrorKind::UnexpectedEof => { println!("End of stream. Exiting."); exit(0); @@ -53,7 +61,13 @@ fn main() } } - sigproc.import_i16_mono(&samples).unwrap(); + // only run calculations if the deque has been filled enough + if samples.len() < config::BLOCK_LEN { + continue; + } + + + sigproc.import_i16_mono_from_iter(samples.iter()).unwrap(); sigproc.update_fft().unwrap(); let energy_bass = sigproc.get_energy_in_band( 0.0, 400.0); diff --git a/src/signal_processing.rs b/src/signal_processing.rs index 3d946c3..b233082 100644 --- a/src/signal_processing.rs +++ b/src/signal_processing.rs @@ -1,5 +1,7 @@ // vim: noet +#[allow(dead_code)] + use fftw::array::AlignedVec; use fftw::plan::*; use fftw::types::*; @@ -88,6 +90,20 @@ impl SignalProcessing Ok(()) } + pub fn import_i16_mono_from_iter<'a>(&mut self, mut iter: impl std::iter::Iterator) -> std::result::Result<(), &str> + { + for fft_samp in self.fft_input.iter_mut() { + match iter.next() { + Some(sample) => *fft_samp = *sample as f32, + None => return Err("Too few samples in input.") + } + } + + self.apply_window(); + + Ok(()) + } + pub fn update_fft(&mut self) -> fftw::error::Result<()> { self.fft_plan.r2c(&mut self.fft_input, &mut self.fft_output)?;