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