implemented Simper SVF and refactored node_sfilter.rs
This commit is contained in:
parent
647b3b6b6d
commit
53853d890e
4 changed files with 262 additions and 85 deletions
|
@ -927,6 +927,7 @@ const FILTER_OVERSAMPLE_HAL_CHAMBERLIN : usize = 2;
|
||||||
/// otherwise the filter becomes unstable.
|
/// otherwise the filter becomes unstable.
|
||||||
/// * `res` - Resonance from 0.0 to 0.99. Resonance of 1.0 is not recommended,
|
/// * `res` - Resonance from 0.0 to 0.99. Resonance of 1.0 is not recommended,
|
||||||
/// as the filter will then oscillate itself out of control.
|
/// as the filter will then oscillate itself out of control.
|
||||||
|
/// * `israte` - 1.0 divided by the sampling rate (eg. 1.0 / 44100.0).
|
||||||
/// * `band` - First state variable, containing the band pass result
|
/// * `band` - First state variable, containing the band pass result
|
||||||
/// after processing.
|
/// after processing.
|
||||||
/// * `low` - Second state variable, containing the low pass result
|
/// * `low` - Second state variable, containing the low pass result
|
||||||
|
@ -973,6 +974,73 @@ pub fn process_hal_chamberlin_svf(
|
||||||
(high, notch)
|
(high, notch)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This function processes a Simper SVF. It's a much newer algorithm
|
||||||
|
/// for filtering and provides easy to calculate multiple outputs.
|
||||||
|
///
|
||||||
|
/// * `input` - Input sample.
|
||||||
|
/// * `freq` - Frequency in Hz.
|
||||||
|
/// otherwise the filter becomes unstable.
|
||||||
|
/// * `res` - Resonance from 0.0 to 0.99. Resonance of 1.0 is not recommended,
|
||||||
|
/// as the filter will then oscillate itself out of control.
|
||||||
|
/// * `israte` - 1.0 divided by the sampling rate (eg. 1.0 / 44100.0).
|
||||||
|
/// * `band` - First state variable, containing the band pass result
|
||||||
|
/// after processing.
|
||||||
|
/// * `low` - Second state variable, containing the low pass result
|
||||||
|
/// after processing.
|
||||||
|
///
|
||||||
|
/// This function returns the low pass, band pass and high pass signal.
|
||||||
|
/// For a notch or peak filter signal, please consult the following example:
|
||||||
|
///
|
||||||
|
///```
|
||||||
|
/// use hexodsp::dsp::helpers::*;
|
||||||
|
///
|
||||||
|
/// let samples = vec![0.0; 44100];
|
||||||
|
/// let mut ic1eq = 0.0;
|
||||||
|
/// let mut ic2eq = 0.0;
|
||||||
|
/// let mut freq = 1000.0;
|
||||||
|
///
|
||||||
|
/// for s in samples.iter() {
|
||||||
|
/// let (low, band, high) =
|
||||||
|
/// process_simper_svf(
|
||||||
|
/// *s, freq, 0.5, 1.0 / 44100.0, &mut ic1eq, &mut ic2eq);
|
||||||
|
///
|
||||||
|
/// // You can easily calculate the notch and peak results too:
|
||||||
|
/// let notch = low + high;
|
||||||
|
/// let peak = low - high;
|
||||||
|
/// // ... do something with the result here.
|
||||||
|
/// }
|
||||||
|
///```
|
||||||
|
// Simper SVF taken from baseplug (Rust crate) example svf_simper.rs:
|
||||||
|
// implemented from https://cytomic.com/files/dsp/SvfLinearTrapOptimised2.pdf
|
||||||
|
// thanks, andy!
|
||||||
|
#[inline]
|
||||||
|
pub fn process_simper_svf(
|
||||||
|
input: f64, freq: f64, res: f64, israte: f64, ic1eq: &mut f64, ic2eq: &mut f64
|
||||||
|
) -> (f64, f64, f64) {
|
||||||
|
let g = (std::f64::consts::PI * freq * israte).tan();
|
||||||
|
let k = 2f64 - (1.9f64 * res);
|
||||||
|
|
||||||
|
let a1 = 1.0 / (1.0 + (g * (g + k)));
|
||||||
|
let a2 = g * a1;
|
||||||
|
let a3 = g * a2;
|
||||||
|
|
||||||
|
let v3 = input - *ic2eq;
|
||||||
|
let v1 = (a1 * *ic1eq) + (a2 * v3);
|
||||||
|
let v2 = *ic2eq + (a2 * *ic1eq) + (a3 * v3);
|
||||||
|
|
||||||
|
*ic1eq = (2.0 * v1) - *ic1eq;
|
||||||
|
*ic2eq = (2.0 * v2) - *ic2eq;
|
||||||
|
|
||||||
|
// low = v2
|
||||||
|
// band = v1
|
||||||
|
// high = input - k * v1 - v2
|
||||||
|
// notch = low + high = input - k * v1
|
||||||
|
// peak = low - high = 2 * v2 - input + k * v1
|
||||||
|
// all = low + high - k * band = input - 2 * k * v1
|
||||||
|
|
||||||
|
(v2, v1, input - k * v1 - v2)
|
||||||
|
}
|
||||||
|
|
||||||
// translated from Odin 2 Synthesizer Plugin
|
// translated from Odin 2 Synthesizer Plugin
|
||||||
// Copyright (C) 2020 TheWaveWarden
|
// Copyright (C) 2020 TheWaveWarden
|
||||||
// under GPLv3 or any later
|
// under GPLv3 or any later
|
||||||
|
|
|
@ -583,7 +583,7 @@ macro_rules! node_list {
|
||||||
(0 inp n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
(0 inp n_id d_id r_id f_def stp_d -1.0, 1.0, 0.0)
|
||||||
(1 freq n_pit d_pit r_fq f_freq stp_d -1.0, 0.5647131, 1000.0)
|
(1 freq n_pit d_pit r_fq f_freq stp_d -1.0, 0.5647131, 1000.0)
|
||||||
(2 res n_id d_id r_id f_def stp_d 0.0, 0.99, 0.5)
|
(2 res n_id d_id r_id f_def stp_d 0.0, 0.99, 0.5)
|
||||||
{3 0 ftype setting(0) fa_sfilter_type 0 7}
|
{3 0 ftype setting(8) fa_sfilter_type 0 12}
|
||||||
[0 sig],
|
[0 sig],
|
||||||
test => Test UIType::Generic UICategory::IOUtil
|
test => Test UIType::Generic UICategory::IOUtil
|
||||||
(0 f n_id d_id r_id f_def stp_d 0.0, 1.0, 0.5)
|
(0 f n_id d_id r_id f_def stp_d 0.0, 1.0, 0.5)
|
||||||
|
|
|
@ -10,6 +10,7 @@ use crate::dsp::helpers::{
|
||||||
process_1pole_tpt_lowpass,
|
process_1pole_tpt_lowpass,
|
||||||
process_1pole_tpt_highpass,
|
process_1pole_tpt_highpass,
|
||||||
process_hal_chamberlin_svf,
|
process_hal_chamberlin_svf,
|
||||||
|
process_simper_svf,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
|
@ -24,6 +25,11 @@ macro_rules! fa_sfilter_type { ($formatter: expr, $v: expr, $denorm_v: expr) =>
|
||||||
5 => "HP 12c",
|
5 => "HP 12c",
|
||||||
6 => "BP 12c",
|
6 => "BP 12c",
|
||||||
7 => "NO 12c",
|
7 => "NO 12c",
|
||||||
|
8 => "LP 12s",
|
||||||
|
9 => "HP 12s",
|
||||||
|
10 => "BP 12s",
|
||||||
|
11 => "NO 12s",
|
||||||
|
12 => "PK 12s",
|
||||||
_ => "?",
|
_ => "?",
|
||||||
};
|
};
|
||||||
write!($formatter, "{}", s)
|
write!($formatter, "{}", s)
|
||||||
|
@ -85,9 +91,54 @@ that is limited to max cutoff frequency of 16kHz.
|
||||||
HP 12c - High-pass Hal Chamberlin state variable filter (12dB)
|
HP 12c - High-pass Hal Chamberlin state variable filter (12dB)
|
||||||
BP 12c - Band-pass Hal Chamberlin state variable filter (12dB)
|
BP 12c - Band-pass Hal Chamberlin state variable filter (12dB)
|
||||||
NO 12c - Notch Hal Chamberlin state variable filter (12dB)
|
NO 12c - Notch Hal Chamberlin state variable filter (12dB)
|
||||||
|
|
||||||
|
The (Andrew) Simper state variable filter is a newer design.
|
||||||
|
|
||||||
|
LP 12s - Low-pass Simper state variable filter (12dB)
|
||||||
|
HP 12s - High-pass Simper state variable filter (12dB)
|
||||||
|
BP 12s - Band-pass Simper state variable filter (12dB)
|
||||||
|
NO 12s - Notch Simper state variable filter (12dB)
|
||||||
|
PK 12s - Peak Simper state variable filter (12dB)
|
||||||
"#;
|
"#;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
macro_rules! process_filter_fun {
|
||||||
|
($nframes: expr, $inp: expr, $out: ident, $freq: ident, $res: ident,
|
||||||
|
$input: ident, $minfreq: expr, $maxfreq: expr, $block: block) => { {
|
||||||
|
for frame in 0..$nframes {
|
||||||
|
let $input = $inp.read(frame) as f64;
|
||||||
|
let $freq = denorm::SFilter::freq($freq, frame) as f64;
|
||||||
|
let $freq = $freq.clamp($minfreq, $maxfreq);
|
||||||
|
let $res = denorm::SFilter::res($res, frame) as f64;
|
||||||
|
let $res = $res.clamp(0.0, 0.99);
|
||||||
|
let s = $block;
|
||||||
|
$out.write(frame, s as f32);
|
||||||
|
}
|
||||||
|
} };
|
||||||
|
($nframes: expr, $inp: expr, $out: ident, $freq: ident, $res: ident,
|
||||||
|
$input: ident, $maxfreq: expr, $block: block) => { {
|
||||||
|
for frame in 0..$nframes {
|
||||||
|
let $input = $inp.read(frame) as f64;
|
||||||
|
let $freq = denorm::SFilter::freq($freq, frame) as f64;
|
||||||
|
let $freq = $freq.clamp(1.0, $maxfreq);
|
||||||
|
let $res = denorm::SFilter::res($res, frame) as f64;
|
||||||
|
let $res = $res.clamp(0.0, 0.99);
|
||||||
|
let s = $block;
|
||||||
|
$out.write(frame, s as f32);
|
||||||
|
}
|
||||||
|
} };
|
||||||
|
($nframes: expr, $inp: expr, $out: ident, $freq: ident,
|
||||||
|
$input: ident, $maxfreq: expr, $block: block) => { {
|
||||||
|
for frame in 0..$nframes {
|
||||||
|
let $input = $inp.read(frame) as f64;
|
||||||
|
let $freq = denorm::SFilter::freq($freq, frame) as f64;
|
||||||
|
let $freq = $freq.clamp(1.0, $maxfreq);
|
||||||
|
let s = $block;
|
||||||
|
$out.write(frame, s as f32);
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
|
||||||
impl DspNode for SFilter {
|
impl DspNode for SFilter {
|
||||||
fn outputs() -> usize { 1 }
|
fn outputs() -> usize { 1 }
|
||||||
|
|
||||||
|
@ -125,112 +176,82 @@ impl DspNode for SFilter {
|
||||||
|
|
||||||
match ftype {
|
match ftype {
|
||||||
0 => { // Lowpass
|
0 => { // Lowpass
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 22000.0);
|
|
||||||
out.write(frame,
|
|
||||||
process_1pole_lowpass(
|
process_1pole_lowpass(
|
||||||
input, freq, self.israte, &mut self.z)
|
input, freq, self.israte, &mut self.z)
|
||||||
as f32);
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
1 => { // Lowpass TPT
|
1 => { // Lowpass TPT
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 22000.0);
|
|
||||||
out.write(frame,
|
|
||||||
process_1pole_tpt_lowpass(
|
process_1pole_tpt_lowpass(
|
||||||
input, freq, self.israte, &mut self.z)
|
input, freq, self.israte, &mut self.z)
|
||||||
as f32);
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
2 => { // Highpass
|
2 => { // Highpass
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 22000.0);
|
|
||||||
out.write(frame,
|
|
||||||
process_1pole_highpass(
|
process_1pole_highpass(
|
||||||
input, freq, self.israte, &mut self.z, &mut self.y)
|
input, freq, self.israte, &mut self.z, &mut self.y)
|
||||||
as f32);
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
3 => { // Highpass TPT
|
3 => { // Highpass TPT
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 22000.0);
|
|
||||||
out.write(frame,
|
|
||||||
process_1pole_tpt_highpass(
|
process_1pole_tpt_highpass(
|
||||||
input, freq, self.israte, &mut self.z)
|
input, freq, self.israte, &mut self.z)
|
||||||
as f32);
|
})
|
||||||
}
|
|
||||||
},
|
},
|
||||||
4 => { // Low Pass Hal Chamberlin SVF
|
4 => { // Low Pass Hal Chamberlin SVF
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, res, input, 2.0, 16000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(2.0, 16000.0);
|
|
||||||
let res = denorm::SFilter::res(res, frame) as f64;
|
|
||||||
let res = res.clamp(0.0, 0.99);
|
|
||||||
|
|
||||||
let (_high, _notch) =
|
let (_high, _notch) =
|
||||||
process_hal_chamberlin_svf(
|
process_hal_chamberlin_svf(
|
||||||
input, freq, res, self.israte,
|
input, freq, res, self.israte,
|
||||||
&mut self.z, &mut self.y);
|
&mut self.z, &mut self.y);
|
||||||
|
self.y
|
||||||
out.write(frame, self.y as f32);
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
5 => { // High Pass Hal Chamberlin SVF
|
5 => { // High Pass Hal Chamberlin SVF
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 16000.0);
|
|
||||||
let res = denorm::SFilter::res(res, frame) as f64;
|
|
||||||
let res = res.clamp(0.0, 0.99);
|
|
||||||
|
|
||||||
let (high, _notch) =
|
let (high, _notch) =
|
||||||
process_hal_chamberlin_svf(
|
process_hal_chamberlin_svf(
|
||||||
input, freq, res, self.israte,
|
input, freq, res, self.israte,
|
||||||
&mut self.z, &mut self.y);
|
&mut self.z, &mut self.y);
|
||||||
|
high
|
||||||
out.write(frame, high as f32);
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
6 => { // Band Pass Hal Chamberlin SVF
|
6 => { // Band Pass Hal Chamberlin SVF
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 16000.0);
|
|
||||||
let res = denorm::SFilter::res(res, frame) as f64;
|
|
||||||
let res = res.clamp(0.0, 0.99);
|
|
||||||
|
|
||||||
let (_high, _notch) =
|
let (_high, _notch) =
|
||||||
process_hal_chamberlin_svf(
|
process_hal_chamberlin_svf(
|
||||||
input, freq, res, self.israte,
|
input, freq, res, self.israte,
|
||||||
&mut self.z, &mut self.y);
|
&mut self.z, &mut self.y);
|
||||||
|
self.z
|
||||||
out.write(frame, self.z as f32);
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
7 => { // Notch Hal Chamberlin SVF
|
7 => { // Notch Hal Chamberlin SVF
|
||||||
for frame in 0..ctx.nframes() {
|
process_filter_fun!(
|
||||||
let input = inp.read(frame) as f64;
|
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||||
let freq = denorm::SFilter::freq(freq, frame) as f64;
|
|
||||||
let freq = freq.clamp(1.0, 16000.0);
|
|
||||||
let res = denorm::SFilter::res(res, frame) as f64;
|
|
||||||
let res = res.clamp(0.0, 0.99);
|
|
||||||
|
|
||||||
let (_high, notch) =
|
let (_high, notch) =
|
||||||
process_hal_chamberlin_svf(
|
process_hal_chamberlin_svf(
|
||||||
input, freq, res, self.israte,
|
input, freq, res, self.israte,
|
||||||
&mut self.z, &mut self.y);
|
&mut self.z, &mut self.y);
|
||||||
|
notch
|
||||||
out.write(frame, notch as f32);
|
});
|
||||||
}
|
},
|
||||||
|
8 => { // Simper SVF Low Pass
|
||||||
|
process_filter_fun!(
|
||||||
|
ctx.nframes(), inp, out, freq, res, input, 22000.0, {
|
||||||
|
let (low, _band, _high) =
|
||||||
|
process_simper_svf(
|
||||||
|
input, freq, res, self.israte,
|
||||||
|
&mut self.z, &mut self.y);
|
||||||
|
low
|
||||||
|
});
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -552,3 +552,91 @@ fn check_node_sfilter_halsvf_notch() {
|
||||||
(0, 20), (10, 32), (100, 16), (1000, 20), (4000, 16), (12000, 20)
|
(0, 20), (10, 32), (100, 16), (1000, 20), (4000, 16), (12000, 20)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_node_sfilter_simpersvf_lowpass() {
|
||||||
|
let (mut matrix, mut node_exec) = setup_sfilter_matrix();
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 1000Hz RES=1.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 1000.0, 1.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(10.0, &[
|
||||||
|
500, 700, 900, 1000, 1500, 2000, 3000, 4000, 12000
|
||||||
|
], &fft[..]), vec![
|
||||||
|
(0, 20), (500, 20), (700, 50), (900, 110), (1000, 40),
|
||||||
|
(1500, 10), (2000, 0), (3000, 0), (4000, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 1000Hz RES=0.5
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 1000.0, 0.5);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(10.0, &[
|
||||||
|
500, 700, 900, 1000, 1500, 2000, 3000, 4000, 12000
|
||||||
|
], &fft[..]), vec![
|
||||||
|
(0, 10), (500, 10), (700, 20), (900, 10), (1000, 10),
|
||||||
|
(1500, 0), (2000, 0), (3000, 0), (4000, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 1000Hz RES=0.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 1000.0, 0.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(10.0, &[
|
||||||
|
500, 700, 900, 1000, 1500, 2000, 3000, 4000, 12000
|
||||||
|
], &fft[..]), vec![
|
||||||
|
(0, 10), (500, 10), (700, 10), (900, 0), (1000, 0),
|
||||||
|
(1500, 0), (2000, 0), (3000, 0), (4000, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 4000Hz RES=1.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 4000.0, 1.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(4.0, &[
|
||||||
|
100, 500, 1000, 2000, 3500, 4000, 5000, 6000, 8000, 12000
|
||||||
|
], &fft[..]), vec![
|
||||||
|
(0, 24), (100, 16), (500, 20), (1000, 20), (2000, 36), (3500, 132),
|
||||||
|
(4000, 80), (5000, 20), (6000, 8), (8000, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 4000Hz RES=0.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 4000.0, 0.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(4.0, &[
|
||||||
|
100, 500, 1000, 2000, 3500, 4000, 5000, 6000, 8000, 12000
|
||||||
|
], &fft[..]), vec![
|
||||||
|
(0, 20), (100, 12), (500, 16), (1000, 16), (2000, 12), (3500, 8),
|
||||||
|
(4000, 8), (5000, 4), (6000, 4), (8000, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 22050Hz RES=0.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 22050.0, 0.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(8.0, &[100, 1000, 4000, 12000, 16000, 20000, 22050, 22051], &fft[..]), vec![
|
||||||
|
(0, 16), (100, 16), (1000, 16), (4000, 16), (12000, 16),
|
||||||
|
(16000, 16), (20000, 16), (22050, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 22050Hz RES=1.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 22050.0, 1.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(8.0, &[100, 1000, 4000, 12000, 16000, 20000, 22050, 22051], &fft[..]), vec![
|
||||||
|
(0, 8), (100, 16), (1000, 16), (4000, 16), (12000, 16),
|
||||||
|
(16000, 16), (20000, 16), (22050, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 0Hz RES=0.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 0.0, 0.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(4.0, &[10, 100, 1000, 4000, 12000, 22050, 22051], &fft[..]), vec![
|
||||||
|
(0, 0), (10, 0), (100, 0), (1000, 0), (4000, 0), (12000, 0),
|
||||||
|
(22050, 0)
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Low Pass Simper SVF @ 0Hz RES=1.0
|
||||||
|
let fft = fft_with_freq_res_type(&mut matrix, &mut node_exec, 8, 0.0, 1.0);
|
||||||
|
assert_eq!(
|
||||||
|
avg_fft_freqs(4.0, &[1, 5, 10, 100, 1000, 4000, 12000, 22050, 22051], &fft[..]), vec![
|
||||||
|
(0, 56), (1, 0), (5, 0), (10, 0), (100, 0), (1000, 0),
|
||||||
|
(4000, 0), (12000, 0), (22050, 0)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue