some basic fft code based on rustfft crate
This commit is contained in:
parent
5a3eb18f5c
commit
4e2cb0dca4
4 changed files with 72 additions and 1 deletions
|
@ -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"
|
||||
|
|
|
@ -143,5 +143,7 @@ impl DspNode for SFilter {
|
|||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
ctx_vals[0].set(out.read(ctx.nframes() - 1));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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::<Vec<Complex<f32>>>();
|
||||
|
||||
let mut p = FftPlanner::<f32>::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
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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!(
|
||||
|
|
Loading…
Reference in a new issue