use cpal::traits::HostTrait; use cpal::traits::DeviceTrait; use cpal::traits::StreamTrait; use eframe; use eframe::egui; use egui::plot::*; use std::io::Write; use std::time::{Duration, Instant}; use rustfft::num_complex::Complex32; use fftw::array::AlignedVec; use fftw::plan::*; use fftw::types::*; use std::f64::consts::PI; use std::time; use std::thread; use std::sync::mpsc; use std::fs::File; use std::path::Path; struct App { val: bool, it: u32, } impl Default for App { fn default() -> Self { Self { val: false, it: 0, } } } impl eframe::App for App { fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { egui::SidePanel::left("side_panel").show(ctx, |ui| { let sin: PlotPoints = (0..1000).map(|i| { let x = i as f64 * 0.01; [x, x.sin() * (self.it as f64 * 0.01).cos()] }).collect(); if self.val { ui.ctx().request_repaint(); self.it += 1; } let line = Line::new(sin); Plot::new("plot").view_aspect(2.0).center_y_axis(true).show(ui, |plui| plui.line(line)); ui.checkbox(&mut self.val, "Animate"); println!("{}", &self.val); // std::thread::sleep(std::time::Duration::from_millis(1)) }); egui::TopBottomPanel::top("top").show(ctx, |_ui| { _ui.label("lol"); }); } } struct SamplePacket { sample_rate: u32, data: Box<[Complex32]> } impl SamplePacket { fn new(sample_rate: u32, data: Box<[Complex32]>) -> Self { Self { sample_rate: sample_rate, data: data } } } trait Process { fn process(&mut self, src: SamplePacket) -> SamplePacket; } struct PipelineBuilder { input: mpsc::SyncSender, output: mpsc::Receiver } impl PipelineBuilder { fn new() -> Self { let (input, output) = mpsc::sync_channel(1); Self { input: input, output: output } } fn pipe(mut self, mut proc: T) -> Self where T: Process + Send + 'static { let (proc_out, output) = mpsc::sync_channel(1); let proc_in = std::mem::replace(&mut self.output, output); thread::spawn(move || { loop { let src = match proc_in.recv() { Ok(s) => s, Err(_) => break, }; let dst = proc.process(src); if proc_out.send(dst).is_err() { break; } } }); self } fn finish(self) -> (mpsc::SyncSender, mpsc::Receiver) { (self.input, self.output) } } struct Squarer; impl Process for Squarer { fn process(&mut self, mut src: SamplePacket) -> SamplePacket { for sample in src.data.iter_mut() { sample.re = (sample.re * 10.0) as i32 as f32 / 10.0; sample.im = (sample.im * 10.0) as i32 as f32 / 10.0; } src } } struct BandFilter { wrap_around: Box<[f32]>, window_filter: Box<[f32]>, test: usize, agc: f32, phase: f32 } impl BandFilter { fn new(window_size: usize) -> Self { let mut window_filter = vec![0.0f32; window_size].into_boxed_slice(); Self { wrap_around: vec![0.0f32; window_size - 1].into_boxed_slice(), window_filter: window_filter, test: 0, agc: 1.0, phase: 0.0 } } } impl Process for BandFilter { fn process(&mut self, mut src: SamplePacket) -> SamplePacket { if src.data.len() != 250000 { println!("smh {}", src.data.len()); return src; } use rustfft::{Fft, FftDirection, algorithm::Radix4}; use rustfft::num_complex::Complex32; let mut fft_planner = rustfft::FftPlannerAvx::new().unwrap(); let len = 250000; let fft = fft_planner.plan_fft_forward(len); let ifft = fft_planner.plan_fft_inverse(len); src.data.iter_mut().enumerate().for_each(|(i, c)| { let phase = i as f32 / len as f32 * 2.0 * 3.14159265359 * 0.0; *c *= Complex32 { re: phase.cos(), im: phase.sin() }; }); fft.process(&mut src.data); src.data[100000..len-100000].iter_mut().for_each(|c| *c = Complex32::default()); ifft.process(&mut src.data); src.data.iter_mut().enumerate().for_each(|(i, c)| { *c /= len as f32; //let (_, phase) = c.to_polar(); let (_, phase) = c.to_polar(); let mut diff = phase - self.phase; if diff > 3.141592 { diff -= 2.0 * 3.141592; } else if diff <= -3.141592 { diff += 2.0 * 3.141592; } let deriv = diff * 250000.0 / 1000000.0; self.phase = phase; c.re = deriv; c.im = 0.0; let bytes = unsafe { std::mem::transmute::(*c) }; // std::io::stdout().write(&bytes); }); src } } struct Resampler { output_rate: u32, } impl Resampler { fn new(output_rate: u32) -> Self { Self { output_rate: output_rate, } } } impl Process for Resampler { fn process(&mut self, src: SamplePacket) -> SamplePacket { if src.sample_rate == self.output_rate { return src; } let skip = src.sample_rate as f32 / self.output_rate as f32; let length = (src.data.len() as f32 / skip) as usize; let mut dst = vec![Complex32::default();length].into_boxed_slice(); //dst.copy_from_slice(&src.data); let mut idx = 0.0f32; let mut isrc = idx as usize; let mut idst = 0; while idst < dst.len() && isrc < src.data.len() { dst[idst] = src.data[isrc]; idx += skip; isrc = idx as usize; idst += 1; } SamplePacket::new(self.output_rate, dst) } } struct AudioSink { recv: mpsc::Receiver, buffer: Option, idx: usize } impl AudioSink { fn new(recv: mpsc::Receiver) -> Self { Self { recv: recv, buffer: None, idx: 0, } } fn pour(&mut self, mut dst: &mut [f32]) { loop { match self.buffer.as_ref() { Some(src) => { let src = &src.data; let src_new = &src[self.idx..]; let count = std::cmp::min(src_new.len(), dst.len()); let src_new = &src_new[..count]; let dst_new = &mut dst[..count]; dst_new.iter_mut().zip(src_new.iter()) .for_each(|(d, s)| *d = s.re); self.idx += count; if self.idx >= src.len() { self.buffer = None; self.idx = 0; } if dst.len() > count { dst = &mut dst[count..]; continue; } return; }, None => { self.buffer = Some(self.recv.recv().unwrap()); } }; } } } fn main() { eframe::run_native( "λ", eframe::NativeOptions::default(), Box::new(|_cc| Box::new(App::default())) ); let host = cpal::default_host(); let dev = host.default_output_device().expect("no audio device found"); let cfg: cpal::StreamConfig = dev.supported_output_configs() .expect("couldn't find configs") .next() .expect("bogus device") .with_max_sample_rate().into(); let sample_rate = cfg.sample_rate.0 * cfg.channels as u32; let denom = cfg.sample_rate.0 as f32 * cfg.channels as f32; //println!("sample_rate{}", sample_rate); let mut inp_file = File::open(Path::new("baseband_100100000Hz_19-35-33_03-11-2022.wav")).unwrap(); let (header, data) = wav::read(&mut inp_file).unwrap(); let data = match data { wav::BitDepth::ThirtyTwoFloat(d) => d, wav::BitDepth::TwentyFour(s) => s.into_iter().map(|m: i32| m as f32 / (1<<23) as f32).collect::>(), wav::BitDepth::Sixteen(s) => s.into_iter().map(|m: i16| m as f32 / i16::MAX as f32).collect::>(), _ => panic!("unsupported bit depth") }; let (send, recv) = PipelineBuilder::new() .pipe(BandFilter::new(1024)) .pipe(Resampler::new(sample_rate)) .finish(); let mut snk = AudioSink::new(recv); let mut snum: f32 = 0.0; let stream = dev.build_output_stream( &cfg, move |data: &mut [f32], _: &cpal::OutputCallbackInfo| { snk.pour(data); }, move |err| { println!("err: {}", err); } ).expect("could not build stream"); stream.play().unwrap(); let mut snum: usize = 0; //println!("{}", header.channel_count); let sampling_rate = header.sampling_rate as usize; let channel_count = header.channel_count as usize; let mut i = 0; while i + sampling_rate*channel_count < data.len() { let mut samples = vec![Complex32::default();sampling_rate].into_boxed_slice(); samples.iter_mut().zip(data[i..i + sampling_rate*channel_count].chunks(2)) .for_each(|(a, b)| *a = Complex32 { re: b[0], im: b[1] }); send.send(SamplePacket::new(header.sampling_rate, samples)).unwrap(); i += sampling_rate*channel_count; } }