use f32 instead of f64 for filtering

This commit is contained in:
Weird Constructor 2021-07-15 06:28:44 +02:00
parent 7f7b8a0837
commit 7a46c38a00
2 changed files with 87 additions and 29 deletions

View file

@ -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;

View file

@ -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
});
},