
State Variable Filter (Double Sampled, Stable)
Type : 2 Pole Low, High, Band, Notch and Peaking References : Posted by Andrew Simper
Notes : Thanks to Laurent de Soras for the stability limit
and Steffan Diedrichsen for the correct notch output.
Code : input = input buffer;
output = output buffer;
fs = sampling frequency;
fc = cutoff frequency normally something like:
440.0*pow(2.0, (midi_note  69.0)/12.0);
res = resonance 0 to 1;
drive = internal distortion 0 to 0.1
freq = 2.0*sin(PI*MIN(0.25, fc/(fs*2))); // the fs*2 is because it's double sampled
damp = MIN(2.0*(1.0  pow(res, 0.25)), MIN(2.0, 2.0/freq  freq*0.5));
notch = notch output
low = low pass output
high = high pass output
band = band pass output
peak = peaking output = low  high

double sampled svf loop:
for (i=0; i
{
in = input[i];
notch = in  damp*band;
low = low + freq*band;
high = notch  low;
band = freq*high + band  drive*band*band*band;
out = 0.5*(notch or low or high or band or peak);
notch = in  damp*band;
low = low + freq*band;
high = notch  low;
band = freq*high + band  drive*band*band*band;
out += 0.5*(same out as above);
output[i] = out;
} 
Comments
Added on : 19/11/04 by didid[ AT ]skynet[ DOT ]be Comment : Correct me if I'm wrong, but the doublesampling here looks like doubling the input, which is a bad resampling introducing aliasing, followed by an averaging of the 2 outputs, thus filtering that aliasing.
It works, but I think it (the averaging) has the side effect of smoothing up the high freqs in the source material, thus with this filter you can't really fully open it and have the original signal.
At least, it's what seems to happen practically in my tests.
Problem is that this SVF indeed has a crap stability near nyquist, but I can't think of any better way to make it work better, unless you use a better but much more costy upsampling/downsampling.
Anyone confirms?
Added on : 26/11/04 by jm[ AT ]kampsax[ DOT ]dtu[ DOT ]dk Comment : Interesting that this question pops up right now. Lately I have been wondering about the same thing, not so much about the (possibly limited) frequency range, but about stability problems of the filter that I have had (even when using smoothed control signals). The nonlinearity introduced by the "drive*band*band*band" factor does not seem to be covered by the stability measurements.
In particular I would like to know, how the filter graphs in http://vellocet.com/dsp/svf/svfstability.html and http://www2.cs.cmu.edu/~eli/tmp/svf/stability.png were obtained? Would you like to post the code that generated the stability graph to the musicdsp archive?
For the doublesampling scheme, wouldn't it make more sense to zerostuff the input signal (that is interleave all input samples with zeros) instead of doubling the samples?
Added on : 26/11/04 by jm[ AT ]kampsax[ DOT ]dtu[ DOT ]dk Comment : Oh, just noticed that Eli's SVF stability measurement code has already been made available at http://www2.cs.cmu.edu/~eli/tmp/svf/
However, I think it is up to him to decide whether he wants to include it in the archive or not.
Added on : 13/12/07 by williamk[ AT ]wusik[ DOT ]com Comment : I was having problems with this filter when DRIVE is set to MAX and Rezonance is set to MIN. A quick way to fix it was to make DRIVE*REZO, so when there's no resonance, there's no need for DRIVE anyway. That fixed the problem.
Added on : 11/05/17 by ryjobil at gmail dot com Comment : Here is how I am handling the resampling. I know from trying this zero padding is nasty (terrible noise) without a good filter for downsampling back to base rate.
Below the input is linear interpolated input. This is a slight improvement on what Nigel Redmon suggests here: http://www.earlevel.com/main/2003/03/02/thedigitalstatevariablefilter/
Which is simply to tick the filter twice per sample with the same input. This is very similar to above code except that there should not be averaging of the two outputs. You just tick the filter twice with the same input and take the output. The state variables take care of the band limiting. Remember the aliased terms are multiples of the sample rate so they fall on 0 and nyquist frequencies, not really having more severe artefacts than what you get from running the filter at base sample rate.
For the low pass and bandpass outputs the filter itself performs the bandlimiting necessary for clean decimation. Intuitively the high pass output is due to a phase cancellation with the dualintegrator loop, so it should be about as clean as the LP and BP outputs. The dual integrator is bandlimiting in nature...just some thoughts.
// Here's the Code //
//x[i] = input
//x1 = x[i1] = last input
//Run 1 : Linear interpolate between x[n1] and x[i]
lpf = lpf + f* bpf;
hpf = 0.5 * g * (x[i] + x1)  lpf  q*bpf;
bpf = f* hpf + bpf;
//Run 2
lpf = lpf + f* bpf;
hpf = g * x[i]  lpf  q*bpf;
bpf = f* hpf + bpf;
x1 = x[i];
// Coefficients on each state variable
// allows for any filter response function possible
// with a biquad filter structure
x[i] = lmix*lpf + hmix*hpf + bmix*bpf;

Add your own comment
Comments are displayed in fixed width, no HTML code allowed! 



