begin correcting fft stuff. need to find a way to sync to signal

This commit is contained in:
TerraMaster85 2025-01-12 18:32:37 -05:00
parent f050cec085
commit 3639b4ddfa
5 changed files with 98 additions and 34 deletions

7
run.sh Executable file
View file

@ -0,0 +1,7 @@
#!/bin/bash
set -e
ROOT="$(git rev-parse --show-toplevel)"
ROOT="${ROOT:-.}"
cargo build --release --bin sang
sudo setcap CAP_NET_ADMIN+ep "$ROOT/target/release/sang"
"$ROOT/target/release/sang"

View file

@ -1,13 +1,47 @@
use cpal::{FromSample, Sample};
use std::io::Write;
use std::collections::VecDeque;
use cpal::{FromSample, Sample, SampleRate};
use rustfft::{FftPlanner, num_complex::Complex};
pub fn take_input_pcm<T>(pcm: &[T], channel: &tokio::sync::mpsc::Sender<Vec<f64>>) where T: Sample + FromSample<f64> + std::fmt::Debug, f64: FromSample<T> {
let mut pcm_complex = pcm.iter().map(|s| Complex { re: s.to_sample::<f64>(), im: 0.0f64 }).collect::<Vec<Complex<_>>>();
pub fn take_input_pcm<T>(
pcm: &[T],
sample_rate: SampleRate,
channel: &tokio::sync::mpsc::Sender<Vec<f64>>,
pcm_buffer: &mut VecDeque<Complex<f64>>,
) where
T: ToString + Sample + FromSample<f64> + std::fmt::Debug,
f64: FromSample<T>
{
// TODO: Obtain this information during the handshake
let fft_size = 320
pcm_buffer.extend(
pcm
.iter()
.map(|s| Complex { re: s.to_sample::<f64>(), im: 0.0f64 })
);
let mut fft_planner = FftPlanner::<f64>::new();
let fft_machine = fft_planner.plan_fft_forward(pcm.len());
fft_machine.process(&mut pcm_complex);
let fft_out = pcm_complex.iter().map(|n| n.norm()).collect::<Vec<_>>();
println!("{:?}",fft_out);
let fft_machine = fft_planner.plan_fft_forward(FFT_SIZE); // TODO: cfgable
while pcm_buffer.len() >= FFT_SIZE {
let mut fft_frame =
pcm_buffer.drain(..FFT_SIZE).collect::<Vec<Complex<f64>>>();
fft_machine.process(&mut fft_frame);
/*for (i, s) in fft_frame.iter().enumerate() {
let freq = sample_rate.0 as usize * i / FFT_SIZE;
let ampl = s.norm();
let confidence = ampl;
if ampl > 50.0 {
println!("{:?}: {:?}", freq, ampl);
}
// soon: confidence = ampl / |freq_target - freq_observed|
}*/
}
}

View file

@ -5,6 +5,8 @@ use cpal::{FromSample, Sample, SampleFormat};
use tracing::{info, trace, warn};
use std::collections::VecDeque;
mod input_dsp;
use self::input_dsp::take_input_pcm;
@ -16,78 +18,101 @@ pub fn audio_receiver_main(
let cpal_input_config = cpal_input.supported_input_configs()
.context("could not find a suitable audio input configuration. are you root, trying to use a normal user's audio stack? try setting the capability CAP_NET_ADMIN=ep on this binary, and running as the user who is running the audio stack.")?
.max_by_key(|cfg| {
match cfg.sample_format() {
SampleFormat::U8 => 10,
SampleFormat::I8 => 11,
SampleFormat::U16 => 20,
SampleFormat::I16 => 21,
SampleFormat::U32 => 30,
SampleFormat::I32 => 31,
SampleFormat::F32 => 40,
SampleFormat::F64 => 50,
SampleFormat::U64 => 60,
SampleFormat::I64 => 61,
x => { warn!("Backend offered unknown sample format {x}",); -999 }
}
if cfg.channels() > 1 { return -999; }
match cfg.sample_format() {
SampleFormat::U8 => 10,
SampleFormat::I8 => 11,
SampleFormat::U16 => 20,
SampleFormat::I16 => 21,
SampleFormat::U32 => 30,
SampleFormat::I32 => 31,
SampleFormat::F32 => 40,
SampleFormat::F64 => 50,
SampleFormat::U64 => 60,
SampleFormat::I64 => 61,
x => { warn!("Backend offered unknown sample format {x}",); -999 }
}
}).expect("input device has no supported configurations available")
.with_max_sample_rate();
//.with_sample_rate(cpal::SampleRate(8000));
let sample_rate = cpal_input_config.sample_rate();
info!(
"input samples are {} @ {}hz",
&cpal_input_config.sample_format(),
&cpal_input_config.sample_rate().0,
sample_rate.0,
);
let failed_pcm_take = move |e| {
warn!("dropped some PCM data on input stream?! {}", e);
};
let mut pcm_buf: VecDeque<rustfft::num_complex::Complex<f64>> =
vec![].into();
let input_stream = match cpal_input_config.sample_format() {
cpal::SampleFormat::U8 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<u8>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<u8>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::I8 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<i8>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<i8>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::I16 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<i16>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<i16>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::I32 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<i32>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<i32>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::F32 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<f32>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<f32>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::F64 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<f64>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<f64>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::U64 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<u64>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<u64>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,
cpal::SampleFormat::I64 => cpal_input.build_input_stream(
&cpal_input_config.into(),
move |pcm, _: &_| take_input_pcm::<i64>(pcm, &tx_for_demod),
move |pcm, _: &_| {
take_input_pcm::<i64>(pcm, sample_rate, &tx_for_demod, &mut pcm_buf)
},
failed_pcm_take,
None,
).context("failed to build input stream")?,

View file

@ -49,10 +49,12 @@ pub fn audio_transmitter_main(
warn!("dropped some PCM data on output stream?! {}", e);
};
// These are mathematically chosen to make things easier for now.
//
// TODO: from cli
let mut carrier = crate::dsp_common::carrier::TwoStateCarrier::new(
2400, // freq_low
2800, // freq_high
3200, // freq_high
cpal_output_config.sample_rate().0, // sample_rate
1200, // symbol_rate
);

File diff suppressed because one or more lines are too long