AUTO-ADMIN: Non-MP3, WAV, OGG, SoundCloud, YouTube, Vimeo, Twitter and Facebook links in this post have been protected automatically. Once the member reaches 5 posts the links will function as normal.
Hey KVR & DSP People,I'm currently working on a dj eqalizer inspired by the https://playdifferently.org/ (https://playdifferently.org/) . For the lowpass/highpass i'm using 2 sequential svf with Q=1.0/sqrt(2.0) so a Linkwitz Riley 4.
Interestingly I'm getting weird artifacts when I'm lowpassing some tracks, sometimes it's subtle, sometimes quite noticeable.
I tried two SVF implementations, the one from faust (https://github.com/grame-cncm/faustlibr ... .lib#L2657 (https://github.com/grame-cncm/faustlibraries/blob/master/filters.lib#L2657)) and a slightly modified version with oversampling. But I get similar problems with both versions.
Might this be an expected problem with SVF? Is there any other Filter Circuit I could try?
Here a recording of the resulting broken audio: https://soundcloud.com/obsoleszenz/svfk ... 2429dacdcb
Here an interactive version in the FaustIDE where you can play around with the code and drag own music files in: https://t.ly/9rNL4 (https://t.ly/9rNL4) (sorry for the url shortener, kvr spam detection wasnt happy with the long url)
Maybe someone can help me out?
~obsoleszenz
Raw Code:
Code: Select all (#)
import("stdfaust.lib");
svf = environment {
// Internal implementation
svf(T,F,Q,G) = tick ~ (_,_) : !,!,si.dot(3, mix)
with {
tick(ic1eq, ic2eq, v0) =
ic1eq_1,
ic2eq_1,
v0, v1_0*0.5+v1_1*0.5, v2_0*0.5+v2_1*0.5
with {
a1 = 1/(1+g*(g+k));
a2 = g*a1;
a3 = g*a2;
v3_0 = v0 - ic2eq;
v1_0 = a1 * ic1eq + a2 * v3_0;
v2_0 = ic2eq + a2 * ic1eq + a3*v3_0;
ic1eq_0 = 2*v1_0 - ic1eq;
ic2eq_0 = 2*v2_0 - ic2eq;
v3_1 = v0 - ic2eq_0;
v1_1 = a1 * ic1eq_0 + a2 * v3_0;
v2_1 = ic2eq_0 + a2 * ic1eq_0 + a3*v3_0;
ic1eq_1 = 2*v1_1 - ic1eq_0;
ic2eq_1 = 2*v2_1 - ic2eq_0;
};
A = pow(10.0, G/40.0);
g = tan(F * ma.PI/(ma.SR*2)) : case {
(7) => /(sqrt(A));
(8) => *(sqrt(A));
(t) => _;
} (T);
k = case {
(6) => 1/(Q*A);
(t) => 1/Q;
} (T);
mix = case {
(0) => 0, 0, 1;
(1) => 0, 1, 0;
(2) => 1, -k, -1;
(3) => 1, -k, 0;
(4) => 1, -k, -2;
(5) => 1, -2*k, 0;
(6) => 1, k*(A*A-1), 0;
(7) => 1, k*(A-1), A*A-1;
(8) => A*A, k*(1-A)*A, 1-A*A;
} (T);
};
// External API
lp(f,q) = svf(0, f, q, 0);
bp(f,q) = svf(1, f, q, 0);
hp(f,q) = svf(2, f, q, 0);
notch(f,q) = svf(3, f, q, 0);
peak(f,q) = svf(4, f, q, 0);
ap(f,q) = svf(5, f, q, 0);
bell(f,q,g) = svf(6, f, q, g);
ls(f,q,g) = svf(7, f, q, g);
hs(f,q,g) = svf(8, f, q, g);
};
smooth_bypass(bpc, e) = _,_ : ba.bypass_fade(ma.BS * 8, bpc, e) : _,_;
//smooth_bypass(bpc, e) = e;
// Calculate a denormalized frequency in hz from offset to max_fq from a (normalized) 0.0-1.0 float value
denormalize_fq(fq, offset, max_fq) = (fq * fq) : * (max_fq - offset) + offset : int;
eq(hpf, lpf, sculpt_fq, sculpt_gain) =
_,_ : sculpt(sculpt_fq, sculpt_gain) : lp(lpf) : hp(hpf)
with {
sculpt_mono(fq, gain) =
_ : fi.svf.bell(denormalized_fq, q, denormalized_gain)
with {
denormalized_fq = denormalize_fq(fq, 70,7000);
centered_gain = (gain - 0.5) * 2;
denormalized_gain = select2(centered_gain <= 0, centered_gain * 8, centered_gain * 30);
q = octave_to_q(2);
octave_to_q(n) = sqrt(pow(2, n)) / (pow(2, n) - 1);
};
sculpt(fq, gain) = _,_ : par(i, 2, sculpt_mono(fq, gain));
highpass(cf) = _ <:
seq(i, 2, svf.hp(cf, 1.0 / sqrt(2.0)));
lowpass(cf) = _ <:
seq(i, 2, svf.lp(cf, 1.0 / sqrt(2.0)));
lp(fq) = _,_ : smooth_bypass((fq >= 0.999), par(i, 2, lowpass(denormalized_fq)))
with {
denormalized_fq = denormalize_fq(fq : si.smoo, 30, ma.SR/2-1) <: attach(_, hbargraph("lp fq", 0, 20000)) ;
};
hp(fq) = _,_ : smooth_bypass((fq <= 0.001), par(i, 2, highpass(denormalized_fq)))
with {
denormalized_fq = denormalize_fq(fq, 1, ma.SR/2-1) <: attach(_, hbargraph("hp fq", 0, 20000));
//hp(cf) = (Bessel2.hp(cf), Bessel4.hp(cf), Bessel6.hp(cf)) : ba.selectn(3, filter_type);
};
};
smoother(bs) = tick ~ (_)
with {
tick(z) = _ * b : + (z * a);
a = exp(-1 * ma.PI / bs);
b = 1.0 - a;
z = 0.0;
};
// Uncomment to test in https://faustide.grame.fr
declare options "[midi:on]";
low_cut = button("low_cut");
param_eq_hpf =hslider("hpf[midi:ctrl 16 1]", 0.0, 0, 1, 0.001) + low_cut * 0.33 : smoother(128);
param_eq_lpf = hslider("lpf[midi:ctrl 19 1] ", 1.0, 0, 1, 0.001) : smoother(128);
param_eq_sculpt_fq = hslider("sculpt_fq[midi:ctrl 18 1]", 0.0, 0, 1, 0.001) : smoother(128);
param_eq_sculpt_gain = hslider("sculpt_gain[midi:ctrl 17 1]", 0.5, 0, 1, 0.001) : smoother(128);
process = eq(param_eq_hpf, param_eq_lpf, param_eq_sculpt_fq, param_eq_sculpt_gain) : _,_;
