diff --git a/Cargo.toml b/Cargo.toml index f01e9cc..58655fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ hound = "3.4.0" microfft = "0.3.1" num-complex = "0.2" jack = "0.6.6" +rustfft = "6.0.0" [lib] path = "src/lib.rs" diff --git a/src/dsp/node_sfilter.rs b/src/dsp/node_sfilter.rs index e3d5cb4..a81ed7f 100644 --- a/src/dsp/node_sfilter.rs +++ b/src/dsp/node_sfilter.rs @@ -143,5 +143,7 @@ impl DspNode for SFilter { }, _ => {}, } + + ctx_vals[0].set(out.read(ctx.nframes() - 1)); } } diff --git a/tests/common/mod.rs b/tests/common/mod.rs index 5c92124..16166b9 100644 --- a/tests/common/mod.rs +++ b/tests/common/mod.rs @@ -422,6 +422,18 @@ pub fn run_and_get_fft4096( fft_thres_at_ms(&mut out_l[..], FFT::F4096, thres, offs_ms) } +#[allow(unused)] +pub fn run_and_get_fft4096_2( + node_exec: &mut hexodsp::nodes::NodeExecutor, + thres: u32) -> Vec<(u16, u32)> +{ + let min_samples_for_fft = 4096.0; + let min_len_samples = 2.0 * min_samples_for_fft; + let run_len_s = min_len_samples / SAMPLE_RATE; + let (mut out_l, _out_r) = run_no_input(node_exec, run_len_s); + fft_16k(&mut out_l[..], 4096, thres) +} + #[allow(unused)] pub fn calc_exp_avg_buckets4096(fft: &[(u16, u32)]) -> Vec<(u16, u32)> { let mut avg = vec![]; @@ -592,3 +604,49 @@ pub fn fft_thres_at_ms(buf: &mut [f32], size: FFT, amp_thres: u32, ms_idx: f32) res } +pub fn fft_16k(buf: &mut [f32], len: usize, amp_thres: u32) -> Vec<(u16, u32)> { + let mut res = vec![]; + + if len > buf.len() { + return res; + } + + // Hann window: + for (i, s) in buf[0..len].iter_mut().enumerate() { + let w = + 0.5 + * (1.0 + - ((2.0 * std::f32::consts::PI * i as f32) + / (len as f32 - 1.0)) + .cos()); + *s *= w; + } + + use rustfft::{FftPlanner, num_complex::Complex}; + + let mut complex_buf = + buf.iter() + .map(|s| Complex { re: *s, im: 0.0 }) + .collect::>>(); + + let mut p = FftPlanner::::new(); + let fft = p.plan_fft_forward(len); + + fft.process(&mut complex_buf[0..len]); + + let amplitudes: Vec<_> = + complex_buf[0..len].iter().map(|c| c.norm() as u32).collect(); + println!("fft: {:?}", &complex_buf[0..len]); + + for (i, amp) in amplitudes.iter().enumerate() { + if *amp >= amp_thres { + let freq = (i as f32 * SAMPLE_RATE) / len as f32; + println!("{:6.0} {}", freq, *amp); + res.push((freq.round() as u16, *amp)); + } + } + + res +} + + diff --git a/tests/node_sfilter.rs b/tests/node_sfilter.rs index 43dfa45..f67b84a 100644 --- a/tests/node_sfilter.rs +++ b/tests/node_sfilter.rs @@ -2,7 +2,7 @@ mod common; use common::*; fn setup_sfilter_matrix() -> (Matrix, NodeExecutor) { - let (node_conf, mut node_exec) = new_node_engine(); + let (node_conf, node_exec) = new_node_engine(); let mut matrix = Matrix::new(node_conf, 3, 3); let noise = NodeId::Noise(0); @@ -50,6 +50,16 @@ fn check_node_sfilter_lowpass() { (1500, 8), (2000, 4), (3000, 4), (4000, 0), (8000, 0), (12000, 0), ]); +// let v = run_and_get_fft4096_2(&mut node_exec, 1); +// assert_eq!( +// avg_fft_freqs(4.0, &[ +// 100, 250, 500, 750, 1000, 1500, 2000, 3000, 4000, 8000, 12000, 16000, +// ], &v[..]), vec![ +// (0, 16), (100, 24), (250, 16), (500, 12), (750, 12), (1000, 12), +// (1500, 8), (2000, 4), (3000, 4), (4000, 0), (8000, 0), (12000, 0), +// ]); +// assert!(false); + // Low Pass @ 4000Hz let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 0, 4000.0, 0.0); assert_eq!(