use f32 instead of f64 for filtering
This commit is contained in:
parent
7f7b8a0837
commit
7a46c38a00
2 changed files with 87 additions and 29 deletions
|
@ -791,8 +791,8 @@ impl Comb {
|
|||
/// // ... do something with the result here.
|
||||
/// }
|
||||
///```
|
||||
pub fn process_1pole_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64) -> f64 {
|
||||
let b = (-std::f64::consts::TAU * freq * israte).exp();
|
||||
pub fn process_1pole_lowpass(input: f32, freq: f32, israte: f32, z: &mut f32) -> f32 {
|
||||
let b = (-std::f32::consts::TAU * freq * israte).exp();
|
||||
let a = 1.0 - b;
|
||||
*z = a * input + *z * b;
|
||||
*z
|
||||
|
@ -824,8 +824,8 @@ pub fn process_1pole_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64) ->
|
|||
/// // ... do something with the result here.
|
||||
/// }
|
||||
///```
|
||||
pub fn process_1pole_highpass(input: f64, freq: f64, israte: f64, z: &mut f64, y: &mut f64) -> f64 {
|
||||
let b = (-std::f64::consts::TAU * freq * israte).exp();
|
||||
pub fn process_1pole_highpass(input: f32, freq: f32, israte: f32, z: &mut f32, y: &mut f32) -> f32 {
|
||||
let b = (-std::f32::consts::TAU * freq * israte).exp();
|
||||
let a = (1.0 + b) / 2.0;
|
||||
|
||||
let v =
|
||||
|
@ -863,8 +863,8 @@ pub fn process_1pole_highpass(input: f64, freq: f64, israte: f64, z: &mut f64, y
|
|||
/// // ... do something with the result here.
|
||||
/// }
|
||||
///```
|
||||
pub fn process_1pole_tpt_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64) -> f64 {
|
||||
let g = (std::f64::consts::PI * freq * israte).tan();
|
||||
pub fn process_1pole_tpt_lowpass(input: f32, freq: f32, israte: f32, z: &mut f32) -> f32 {
|
||||
let g = (std::f32::consts::PI * freq * israte).tan();
|
||||
let a = g / (1.0 + g);
|
||||
|
||||
let v1 = a * (input - *z);
|
||||
|
@ -901,8 +901,8 @@ pub fn process_1pole_tpt_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64
|
|||
/// // ... do something with the result here.
|
||||
/// }
|
||||
///```
|
||||
pub fn process_1pole_tpt_highpass(input: f64, freq: f64, israte: f64, z: &mut f64) -> f64 {
|
||||
let g = (std::f64::consts::PI * freq * israte).tan();
|
||||
pub fn process_1pole_tpt_highpass(input: f32, freq: f32, israte: f32, z: &mut f32) -> f32 {
|
||||
let g = (std::f32::consts::PI * freq * israte).tan();
|
||||
let a1 = g / (1.0 + g);
|
||||
|
||||
let v1 = a1 * (input - *z);
|
||||
|
@ -952,11 +952,11 @@ const FILTER_OVERSAMPLE_HAL_CHAMBERLIN : usize = 2;
|
|||
///```
|
||||
#[inline]
|
||||
pub fn process_hal_chamberlin_svf(
|
||||
input: f64, freq: f64, res: f64, israte: f64, band: &mut f64, low: &mut f64)
|
||||
-> (f64, f64)
|
||||
input: f32, freq: f32, res: f32, israte: f32, band: &mut f32, low: &mut f32)
|
||||
-> (f32, f32)
|
||||
{
|
||||
let q = 1.0 - res;
|
||||
let cutoff = 2.0 * (std::f64::consts::PI * freq * 0.5 * israte).sin();
|
||||
let cutoff = 2.0 * (std::f32::consts::PI * freq * 0.5 * israte).sin();
|
||||
|
||||
let mut high = 0.0;
|
||||
let mut notch = 0.0;
|
||||
|
@ -1015,11 +1015,11 @@ pub fn process_hal_chamberlin_svf(
|
|||
// 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();
|
||||
input: f32, freq: f32, res: f32, israte: f32, ic1eq: &mut f32, ic2eq: &mut f32
|
||||
) -> (f32, f32, f32) {
|
||||
let g = (std::f32::consts::PI * freq * israte).tan();
|
||||
// XXX: the 1.989 were tuned by hand, so the resonance is more audible.
|
||||
let k = 2f64 - (1.989f64 * res);
|
||||
let k = 2f32 - (1.989f32 * res);
|
||||
|
||||
let a1 = 1.0 / (1.0 + (g * (g + k)));
|
||||
let a2 = g * a1;
|
||||
|
|
|
@ -38,9 +38,11 @@ macro_rules! fa_sfilter_type { ($formatter: expr, $v: expr, $denorm_v: expr) =>
|
|||
/// A simple amplifier
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SFilter {
|
||||
israte: f64,
|
||||
z: f64,
|
||||
y: f64,
|
||||
israte: f32,
|
||||
z: f32,
|
||||
y: f32,
|
||||
k: f32,
|
||||
h: f32,
|
||||
otype: i8,
|
||||
}
|
||||
|
||||
|
@ -50,6 +52,8 @@ impl SFilter {
|
|||
israte: 1.0 / 44100.0,
|
||||
z: 0.0,
|
||||
y: 0.0,
|
||||
k: 0.0,
|
||||
h: 0.0,
|
||||
otype: -1,
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +106,56 @@ The (Andrew) Simper state variable filter is a newer design.
|
|||
"#;
|
||||
}
|
||||
|
||||
macro_rules! process_filter_fun32 {
|
||||
($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);
|
||||
let $freq = denorm::SFilter::freq($freq, frame);
|
||||
let $freq = $freq.clamp($minfreq, $maxfreq);
|
||||
let $res = denorm::SFilter::res($res, frame);
|
||||
let $res = $res.clamp(0.0, 0.99);
|
||||
let s = $block;
|
||||
$out.write(frame, s);
|
||||
}
|
||||
} };
|
||||
($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);
|
||||
let $freq = denorm::SFilter::freq($freq, frame);
|
||||
let $freq = $freq.clamp(1.0, $maxfreq);
|
||||
let $res = denorm::SFilter::res($res, frame);
|
||||
let $res = $res.clamp(0.0, 0.99);
|
||||
let s = $block;
|
||||
$out.write(frame, s);
|
||||
}
|
||||
} };
|
||||
($nframes: expr, $inp: expr, $out: ident, $freq: ident, $res: ident,
|
||||
$maxres: expr, $input: ident, $maxfreq: expr, $block: block) => { {
|
||||
for frame in 0..$nframes {
|
||||
let $input = $inp.read(frame);
|
||||
let $freq = denorm::SFilter::freq($freq, frame);
|
||||
let $freq = $freq.clamp(1.0, $maxfreq);
|
||||
let $res = denorm::SFilter::res($res, frame);
|
||||
let $res = $res.clamp(0.0, $maxres);
|
||||
let s = $block;
|
||||
$out.write(frame, s);
|
||||
}
|
||||
} };
|
||||
($nframes: expr, $inp: expr, $out: ident, $freq: ident,
|
||||
$input: ident, $maxfreq: expr, $block: block) => { {
|
||||
for frame in 0..$nframes {
|
||||
let $input = $inp.read(frame);
|
||||
let $freq = denorm::SFilter::freq($freq, frame);
|
||||
let $freq = $freq.clamp(1.0, $maxfreq);
|
||||
let s = $block;
|
||||
$out.write(frame, s);
|
||||
}
|
||||
} }
|
||||
}
|
||||
|
||||
|
||||
macro_rules! process_filter_fun {
|
||||
($nframes: expr, $inp: expr, $out: ident, $freq: ident, $res: ident,
|
||||
$input: ident, $minfreq: expr, $maxfreq: expr, $block: block) => { {
|
||||
|
@ -155,11 +209,13 @@ impl DspNode for SFilter {
|
|||
fn outputs() -> usize { 1 }
|
||||
|
||||
fn set_sample_rate(&mut self, srate: f32) {
|
||||
self.israte = 1.0 / (srate as f64);
|
||||
self.israte = 1.0 / srate;
|
||||
}
|
||||
fn reset(&mut self) {
|
||||
self.z = 0.0;
|
||||
self.y = 0.0;
|
||||
self.k = 0.0;
|
||||
self.h = 0.0;
|
||||
self.otype = -1;
|
||||
}
|
||||
|
||||
|
@ -183,40 +239,42 @@ impl DspNode for SFilter {
|
|||
if ftype != self.otype {
|
||||
self.y = 0.0;
|
||||
self.z = 0.0;
|
||||
self.k = 0.0;
|
||||
self.h = 0.0;
|
||||
self.otype = ftype;
|
||||
}
|
||||
|
||||
match ftype {
|
||||
0 => { // Lowpass
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||
process_1pole_lowpass(
|
||||
input, freq, self.israte, &mut self.z)
|
||||
})
|
||||
},
|
||||
1 => { // Lowpass TPT
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||
process_1pole_tpt_lowpass(
|
||||
input, freq, self.israte, &mut self.z)
|
||||
})
|
||||
},
|
||||
2 => { // Highpass
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||
process_1pole_highpass(
|
||||
input, freq, self.israte, &mut self.z, &mut self.y)
|
||||
})
|
||||
},
|
||||
3 => { // Highpass TPT
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, input, 22000.0, {
|
||||
process_1pole_tpt_highpass(
|
||||
input, freq, self.israte, &mut self.z)
|
||||
})
|
||||
},
|
||||
4 => { // Low Pass Hal Chamberlin SVF
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, res, input, 2.0, 16000.0, {
|
||||
let (_high, _notch) =
|
||||
process_hal_chamberlin_svf(
|
||||
|
@ -226,7 +284,7 @@ impl DspNode for SFilter {
|
|||
});
|
||||
},
|
||||
5 => { // High Pass Hal Chamberlin SVF
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||
let (high, _notch) =
|
||||
process_hal_chamberlin_svf(
|
||||
|
@ -236,7 +294,7 @@ impl DspNode for SFilter {
|
|||
});
|
||||
},
|
||||
6 => { // Band Pass Hal Chamberlin SVF
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||
let (_high, _notch) =
|
||||
process_hal_chamberlin_svf(
|
||||
|
@ -246,7 +304,7 @@ impl DspNode for SFilter {
|
|||
});
|
||||
},
|
||||
7 => { // Notch Hal Chamberlin SVF
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, res, input, 16000.0, {
|
||||
let (_high, notch) =
|
||||
process_hal_chamberlin_svf(
|
||||
|
@ -256,12 +314,12 @@ impl DspNode for SFilter {
|
|||
});
|
||||
},
|
||||
8 => { // Simper SVF Low Pass
|
||||
process_filter_fun!(
|
||||
process_filter_fun32!(
|
||||
ctx.nframes(), inp, out, freq, res, 1.0, input, 22000.0, {
|
||||
let (low, _band, _high) =
|
||||
process_simper_svf(
|
||||
input, freq, res, self.israte,
|
||||
&mut self.z, &mut self.y);
|
||||
&mut self.k, &mut self.h);
|
||||
low
|
||||
});
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue