diff --git a/src/audio_receiver/input_dsp.rs b/src/audio_receiver/input_dsp.rs index f0a7232..d1625a4 100644 --- a/src/audio_receiver/input_dsp.rs +++ b/src/audio_receiver/input_dsp.rs @@ -3,8 +3,6 @@ use std::io::Write; use cpal::{FromSample, Sample, SampleRate}; -use ringbuf::{traits::*, LocalRb}; - use rustfft::{num_complex::Complex, FftPlanner}; use super::ForeignTwoStateCarrier; @@ -19,7 +17,7 @@ pub fn take_input_pcm( T: ToString + Sample + FromSample + std::fmt::Debug, f64: FromSample, { - let fft_size = (sample_rate / carrier.symbol_rate).round() as u32; + let fft_size = (sample_rate.0 as f64 / carrier.clock_hz).round() as usize; pcm_buffer.extend(pcm.iter().map(|s| Complex { re: s.to_sample::(), @@ -27,30 +25,50 @@ pub fn take_input_pcm( })); let mut fft_planner = FftPlanner::::new(); - let fft_machine = fft_planner.plan_fft_forward(fft_size); // TODO: cfgable - let mut fft_frame = pcm_buffer[..fft_size]; + let fft_machine = fft_planner.plan_fft_forward(fft_size); // Zero-pad for a better freq resolution. 8192 fft should be fast enough - if fft_size < 8192 { - fft_frame.extend([0.0_f64].repeat(8192 - fft_size)); - } - let mut window_offset = 0; + let mut prev_phase = f64::NAN; + + // window must not extend beyond pcm_buffer + while !carrier.acquired && window_offset + pcm_buffer.len() < fft_size { + let pcm_buffer_contiguous = pcm_buffer.make_contiguous(); + let mut fft_frame: Vec> = if fft_size < 8192 { + let mut frm = + [Complex { re: 0.0f64, im: 0.0f64 }].repeat(8192 - fft_size); + frm.extend( + &pcm_buffer_contiguous[window_offset..(fft_size+window_offset)] + ); + frm + } else { + pcm_buffer_contiguous[window_offset..(fft_size+window_offset)] + .to_vec() + }; - while !carrier.acquired - && pcm_buffer.len() >= fft_size - && window_offset < fft_size - { fft_machine.process(&mut fft_frame); + let clock_freq_index = + (fft_size as f64 * carrier.clock_hz / sample_rate.0 as f64) + .round() as usize; - let frame_index = fft_size * carrier.clock_hz / sample_rate.0 as usize; - if let Some(bin) = fft_frame.get(frame_index) { - // yay - } + if let Some(bin) = fft_frame.get(clock_freq_index) { + if bin.re + bin.im < 0.000000001 { break; } // too small to use. + // arbitrary number; + // tune as needed + let phase = f64::atan2(bin.im, bin.re); + + // if the phase just passed 0, increasing: + if phase > 0.0 && phase - prev_phase > 0.0 { + carrier.acquired = true; + } else { + window_offset += 1; + } + prev_phase = phase; + } else { break; } } while carrier.acquired && pcm_buffer.len() >= fft_size { - fft_machine.process(&mut fft_frame); + //fft_machine.process(&mut fft_frame); /*for (i, s) in fft_frame.iter().enumerate() { let freq = sample_rate.0 as usize * i / fft_size; diff --git a/src/audio_receiver/mod.rs b/src/audio_receiver/mod.rs index 1b18802..2c59bfc 100644 --- a/src/audio_receiver/mod.rs +++ b/src/audio_receiver/mod.rs @@ -56,7 +56,7 @@ pub fn audio_receiver_main( // TODO: determine freqs from handshake let mut foreign_carrier = ForeignTwoStateCarrier { acquired: false, - symbol_rate: 1200.0, + clock_hz: 1200.0, freq_low: Some(2400.0), freq_high: Some(3600.0), };