-
-
Save bczhc/39b1eec2c9476dd8be13701e8d798430 to your computer and use it in GitHub Desktop.
airspy r2 FM解调代码。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //! Use command: | |
| //! | |
| //! ```shell | |
| //! freq=88.6; airspy_rx -f $freq -a 10000000 -t 0 -h 10 -b 0 -r - \ | |
| //! | ~/code/radio-and-ham-tools/target/release/demo5 \ | |
| //! | ffmpeg -f f32le -ch_layout mono -ar 250000 -i pipe:0 \ | |
| //! -af "aemphasis=type=50fm:mode=reproduction,lowpass=f=15000:p=2,bandreject=f=19000:width_type=h:width=50" \ | |
| //! -ch_layout mono -ar 48000 -c:a pcm_f32le -f f32le - \ | |
| //! | pacat --format=float32le --channels=1 --rate=48000 | |
| //! ``` | |
| use byteorder::{WriteBytesExt, LE}; | |
| use num_complex::Complex64; | |
| use radio_and_ham_tools::ReadIq; | |
| use std::f64::consts::PI; | |
| use std::io::{stdin, stdout, BufReader, BufWriter}; | |
| use std::process::{Command, Stdio}; | |
| use std::thread::spawn; | |
| use crossbeam_channel::bounded; | |
| fn main() -> anyhow::Result<()> { | |
| // let iq_sample_rate = 768000; | |
| let iq_sample_rate = 10000000; | |
| let pcm_sample_rate = 48000; | |
| let vfo_bandwidth = 250_000; | |
| // let fc_offset = 200_000; | |
| let fc_offset = 0; | |
| let mut reader = stdin(); | |
| let mut writer = stdout(); | |
| let decimation_factor = iq_sample_rate / pcm_sample_rate; | |
| let ffmpeg_cmd = format!( | |
| "ffmpeg -hide_banner -f f32le -ar {iq_sample_rate} -ac 2 -i pipe:0 \ | |
| -af aresample=resampler=soxr \ | |
| -f f32le -ar {vfo_bandwidth} -ac 2 -" | |
| ); | |
| let program = shell_words::split(&ffmpeg_cmd).unwrap(); | |
| let mut command = Command::new(&program[0]) | |
| .args(&program[1..]) | |
| .stderr(Stdio::inherit()) | |
| .stdin(Stdio::piped()) | |
| .stdout(Stdio::piped()) | |
| .spawn() | |
| .unwrap(); | |
| let mut program_in = BufWriter::new(command.stdin.take().unwrap()); | |
| let mut program_out = BufReader::new(command.stdout.take().unwrap()); | |
| spawn(move || { | |
| std::io::copy(&mut reader, &mut program_in).unwrap(); | |
| drop(program_in); | |
| let status = command.wait().unwrap(); | |
| if !status.success() { | |
| panic!("ffmpeg exits with non-zero status: {}", status); | |
| } | |
| }); | |
| let dt = 1. / vfo_bandwidth as f64; | |
| let mut last_phase = 0.; | |
| loop { | |
| // this iq is down-sampled | |
| let mut iq = program_out.read_iq()?; | |
| let deviation = 100_000 /* WFM */; | |
| let phase = iq.arg(); | |
| let mut diff = phase - last_phase; | |
| if diff < -PI { | |
| diff += 2. * PI; | |
| } else if diff > PI { | |
| diff -= 2. * PI; | |
| } | |
| let signal = diff / dt / (2. * PI) / deviation as f64; | |
| // decimation | |
| // if n.is_multiple_of(100) { | |
| writer.write_f32::<LE>(signal.clamp(-1., 1.) as _)?; | |
| // } | |
| last_phase = phase; | |
| } | |
| Ok(()) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment