begin correcting fft stuff. need to find a way to sync to signal
This commit is contained in:
parent
f050cec085
commit
3639b4ddfa
5 changed files with 98 additions and 34 deletions
7
run.sh
Executable file
7
run.sh
Executable 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"
|
|
@ -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|
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")?,
|
||||
|
|
|
@ -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
Loading…
Reference in a new issue