added high pass implementations too now.
This commit is contained in:
parent
d1f7cc9a4d
commit
ebb5dd3a9b
3 changed files with 65 additions and 31 deletions
|
@ -715,6 +715,23 @@ pub fn process_1pole_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64) ->
|
||||||
*z
|
*z
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one pole hp from valley rack free:
|
||||||
|
// https://github.com/ValleyAudio/ValleyRackFree/blob/v1.0/src/Common/DSP/OnePoleFilters.cpp
|
||||||
|
#[inline]
|
||||||
|
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();
|
||||||
|
let a = (1.0 + b) / 2.0;
|
||||||
|
let a1 = - a;
|
||||||
|
|
||||||
|
let v =
|
||||||
|
a * input
|
||||||
|
+ a1 * *z
|
||||||
|
+ b * *y;
|
||||||
|
*y = v;
|
||||||
|
*z = input;
|
||||||
|
v
|
||||||
|
}
|
||||||
|
|
||||||
// one pole from:
|
// one pole from:
|
||||||
// http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.pdf
|
// http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.pdf
|
||||||
// (page 5)
|
// (page 5)
|
||||||
|
@ -732,6 +749,21 @@ pub fn process_1pole_tpt_lowpass(input: f64, freq: f64, israte: f64, z: &mut f64
|
||||||
v2
|
v2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// one pole from:
|
||||||
|
// http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.pdf
|
||||||
|
// (page 5)
|
||||||
|
#[inline]
|
||||||
|
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();
|
||||||
|
let a1 = g / (1.0 + g);
|
||||||
|
|
||||||
|
let v1 = a1 * (input - *z);
|
||||||
|
let v2 = v1 + *z;
|
||||||
|
*z = v2 + v1;
|
||||||
|
|
||||||
|
input - 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
|
||||||
|
|
|
@ -4,16 +4,21 @@
|
||||||
|
|
||||||
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
use crate::nodes::{NodeAudioContext, NodeExecContext};
|
||||||
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
use crate::dsp::{NodeId, SAtom, ProcBuf, DspNode, LedPhaseVals, NodeContext};
|
||||||
use crate::dsp::helpers::{process_1pole_lowpass, process_1pole_tpt_lowpass};
|
use crate::dsp::helpers::{
|
||||||
|
process_1pole_lowpass,
|
||||||
|
process_1pole_highpass,
|
||||||
|
process_1pole_tpt_lowpass,
|
||||||
|
process_1pole_tpt_highpass,
|
||||||
|
};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! fa_sfilter_type { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
macro_rules! fa_sfilter_type { ($formatter: expr, $v: expr, $denorm_v: expr) => { {
|
||||||
let s =
|
let s =
|
||||||
match ($v.round() as usize) {
|
match ($v.round() as usize) {
|
||||||
0 => "LP(1p)",
|
0 => "LP(1p)",
|
||||||
1 => "LP(1p,TPT)",
|
1 => "LP(1pt)",
|
||||||
2 => "HP(1p)",
|
2 => "HP(1p)",
|
||||||
3 => "HP(1p,TPT)",
|
3 => "HP(1pt)",
|
||||||
_ => "?",
|
_ => "?",
|
||||||
};
|
};
|
||||||
write!($formatter, "{}", s)
|
write!($formatter, "{}", s)
|
||||||
|
@ -80,48 +85,46 @@ impl DspNode for SFilter {
|
||||||
let out = out::SFilter::sig(outputs);
|
let out = out::SFilter::sig(outputs);
|
||||||
|
|
||||||
match ftype.i() {
|
match ftype.i() {
|
||||||
// one pole lp from valley rack free:
|
|
||||||
// https://github.com/ValleyAudio/ValleyRackFree/blob/v1.0/src/Common/DSP/OnePoleFilters.cpp
|
|
||||||
0 => {
|
0 => {
|
||||||
for frame in 0..ctx.nframes() {
|
for frame in 0..ctx.nframes() {
|
||||||
let input = inp.read(frame) as f64;
|
let input = inp.read(frame) as f64;
|
||||||
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
||||||
out.write(frame,
|
out.write(frame,
|
||||||
process_1pole_lowpass(input, freq, self.israte, &mut self.z)
|
process_1pole_lowpass(
|
||||||
|
input, freq, self.israte, &mut self.z)
|
||||||
as f32);
|
as f32);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// one pole from:
|
|
||||||
// http://www.willpirkle.com/Downloads/AN-4VirtualAnalogFilters.pdf
|
|
||||||
// (page 5)
|
|
||||||
1 => {
|
1 => {
|
||||||
for frame in 0..ctx.nframes() {
|
for frame in 0..ctx.nframes() {
|
||||||
let input = inp.read(frame) as f64;
|
let input = inp.read(frame) as f64;
|
||||||
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
||||||
out.write(frame,
|
out.write(frame,
|
||||||
process_1pole_tpt_lowpass(input, freq, self.israte, &mut self.z)
|
process_1pole_tpt_lowpass(
|
||||||
|
input, freq, self.israte, &mut self.z)
|
||||||
|
as f32);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
2 => {
|
||||||
|
for frame in 0..ctx.nframes() {
|
||||||
|
let input = inp.read(frame) as f64;
|
||||||
|
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
||||||
|
out.write(frame,
|
||||||
|
process_1pole_highpass(
|
||||||
|
input, freq, self.israte, &mut self.z, &mut self.y)
|
||||||
|
as f32);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
3 => {
|
||||||
|
for frame in 0..ctx.nframes() {
|
||||||
|
let input = inp.read(frame) as f64;
|
||||||
|
let freq = (denorm::SFilter::freq(freq, frame) as f64);
|
||||||
|
out.write(frame,
|
||||||
|
process_1pole_tpt_highpass(
|
||||||
|
input, freq, self.israte, &mut self.z)
|
||||||
as f32);
|
as f32);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// // From https://en.wikipedia.org/wiki/RC_circuit
|
|
||||||
// // has the same output as the SVF variant, takes the same amount of time.
|
|
||||||
// 3 => {
|
|
||||||
// for frame in 0..ctx.nframes() {
|
|
||||||
// let input = inp.read(frame) as f64;
|
|
||||||
// let c =
|
|
||||||
// 2.0
|
|
||||||
// / (std::f64::consts::TAU
|
|
||||||
// * (denorm::SFilter::freq(freq, frame) as f64)
|
|
||||||
// * self.israte);
|
|
||||||
//
|
|
||||||
// let y = (input + self.z - self.y * (1.0 - c)) / (1.0 + c);
|
|
||||||
// self.z = input;
|
|
||||||
// self.y = y;
|
|
||||||
//
|
|
||||||
// // highpass: self.z - self.y
|
|
||||||
// out.write(frame, y as f32);
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ fn check_node_sfilter_compare() {
|
||||||
.out(None, None, noise.out("sig")));
|
.out(None, None, noise.out("sig")));
|
||||||
matrix.place(1, 2, Cell::empty(out)
|
matrix.place(1, 2, Cell::empty(out)
|
||||||
.input(out.inp("ch2"), None, None));
|
.input(out.inp("ch2"), None, None));
|
||||||
pset_d(&mut matrix, sf, "freq", 100.0);
|
pset_d(&mut matrix, sf, "freq", 440.0);
|
||||||
matrix.sync().unwrap();
|
matrix.sync().unwrap();
|
||||||
|
|
||||||
let ta = std::time::Instant::now();
|
let ta = std::time::Instant::now();
|
||||||
|
@ -44,7 +44,6 @@ fn check_node_sfilter_compare() {
|
||||||
let ta = std::time::Instant::now().duration_since(ta);
|
let ta = std::time::Instant::now().duration_since(ta);
|
||||||
println!("ta2 Elapsed: {:?}", ta);
|
println!("ta2 Elapsed: {:?}", ta);
|
||||||
|
|
||||||
|
|
||||||
pset_s(&mut matrix, sf, "ftype", 2);
|
pset_s(&mut matrix, sf, "ftype", 2);
|
||||||
|
|
||||||
let ta = std::time::Instant::now();
|
let ta = std::time::Instant::now();
|
||||||
|
|
Loading…
Reference in a new issue