I've got a PM asking
modulatable bandpass filters. Here we go. Instead of calculating the five IIR BiQuad coefficients using Ruby, we do it using Blue (DSP code) taking advantage of the sin1 and cos1 functions. Need to pay attention to the arguments of sin1 and cos1. In Blue (DSP code), sin1 and cos1 need the argument to be in Radians. The argument doesn't need to be multipied by (2 * Pi).
Here is the DSP code for calculating generalized IIR BiQuad coefficients basing on the Bilinear Transform. This is a "generalized" BiQuad as it features a single output delivering any combination of lowpass, bandpass and highpass.
For getting a pure lowpass with a gain of 0 dB, you specify lp=1.0, bp=0.0, hp=0.0.
For getting a notch, you specify lp=1.0, bp=0.0, hp=1.0.
- Code: Select all
streamin fr;
streamin q; // will crash if Q=0
streamin lp;
streamin bp;
streamin hp;
streamout a0;
streamout a1;
streamout a2;
streamout b1;
streamout b2;
float alpha;
float x0, x1, x2;
float lpf0, lpf1, lpf2;
float bpf0, bpf1, bpf2;
float hpf0, hpf1, hpf2;
alpha = (sin1(fr)) * 0.5 / q;
x0 = 1.0 + alpha;
x1 = -2.0 * cos1(fr);
x2 = 1.0 - alpha;
b1 = x1 / x0;
b2 = x2 / x0;
lpf0 = ((1.0 - cos1(fr)) * 0.5) / x0;
lpf1 = lpf0 * 2.0;
lpf2 = lpf0;
bpf0 = (sin1(fr) * 0.5) / (x0 * q);
bpf1 = 0;
bpf2 = -1.0 * bpf0;
hpf0 = ((1.0 + cos1(fr)) * 0.5) / x0;
hpf1 = -2.0 * hpf0;
hpf2 = hpf0;
a0 = lpf0*lp + bpf0*bp + hpf0*hp;
a1 = lpf1*lp + bpf1*bp + hpf1*hp;
a2 = lpf2*lp + bpf2*bp + hpf2*hp;
Here is the DSP code for calculating bandpass IIR BiQuad coefficients using the Bilinear Transform. This is a simplification of the Generalized BiQuad IIR filter.
- Code: Select all
streamin fr;
streamout a0;
streamout a1;
streamout a2;
streamout b1;
streamout b2;
float alpha;
float x0, x1, x2;
float q = 0.900;
alpha = (sin1(fr)) * 0.5 / q;
x0 = 1.0 + alpha;
x1 = -2.0 * cos1(fr);
x2 = 1.0 - alpha;
b1 = x1 / x0;
b2 = x2 / x0;
a0 = (sin1(fr) * 0.5) / (x0 * q);
a1 = 0;
a2 = -1.0 * a0;
Fr is the central frequency of the bandpass, relative to the sampling frequency Fs (usually 44,100 Hz).
Q gets hard coded as constant in the DSP code.
This is all about coefficients.
Where do we manipulate audio samples for actually implementing the BiQuad IIR filter?
Actually, we are relying on the 2P2Z Flowstone primitive. Such primitive needs five coefficients as input, the five coefficients that we just computed : a0, a1, a2, b1, b2.
For making up a 1/3 octave bandpass filter, three such bandpass filters are put in series with different values for Q and for Fr.
On the attached .fsm, Fr gets generated in a static way using a knob delivering a Float in the range (0.0 ... 0.5).
What's a "modulatable" filter ?
Actually, the Fc input of the bandpass filter is a stream (Blue). This is the reason why the IIR coefficients need to be calculated using Blue (DSP) code.
The Fc input can thus serve as modulation input, synchronously sampled at Fs just like audio is, making the bandpass filter a "modulatable" one. In such context, Fc is usually coming from a very low frequency oscillator (say 10 Hz maximum), or any other slow-varying continuous waveform generator sampled at Fs, considered as Blue audio stream. The bandpass filter becomes thus a realtime variable one, the centre frequency is now continuously changing over time, and there can't be artifacts because everything (the modulating wave and the signal output wave) remains synchronously sampled at Fs (usually 44,100 Hz).
Say you need to override the slow-varying and continuously-varying Fc value using a manual knob. Fc will endure abrupt changes. Depending on the user input, the feedback part of the IIR BiQuad filter may tend to instability. This generates audible artifacts sounding like zipping or unzipping a coat or a jacket. Up to you to provide a "de-zipper", kind of lowpass filter, smoothing transitions between subsequent Float values. There are two Flowstone primitives available, taking care of this.
In the early eighties, DSP hardware was powerful enough for handling all 16-bit audio samples arriving at 44,100 Hz (say a 16-channel digital mixing console), but barely powerful enough or lacking memory and/or programming ease for managing de-zipping also at 44,100 Hz. Those early systems had a kind of de-zipping running at 100 Hz or so, in a lightweight Round-Robin sequencer, one knob after the other. Some generated audible artifacts in case the user was harsh with the controls. Most sound engineers mistrusted digital mixing consoles, back in those pioneering times - and they were right.
Back in 1993, ten years after the arrival of the CD, I remember how we managed to "measure" zipping noise possibly generated by our experimental digital mixing desk based on the Analog Device SHARC (DSP) and Crystal Semiconductor DACs. We used to play the "On Every Street" CD from Dire Straits on a Tannoy Canterbury "Dual Concentric" loudspeaker, loudly, our ears close to the speaker, with some colleague exercising the "monkey test" on the console knobs.
Back in 1993, if you were telling your boss that a true de-zipping was maybe feasible at Fs, using a 6th order Taylor approximation for the sinus and cosinus calculation of the IIR coefficients, along with two divisions, he was telling "you are mad, this is pure waste, how dare you asking the precious DSP to compute something else than audio samples, at Fs".
Back in 1993, a typical de-zipping scheme consisted of exploiting a sinus and cosinus table in ROM (quite short because of memory size constraint), and interpolating into it, not at Fs but at a slower frequency like Fs/256 for each knob, this way you could manage 256 knobs without overloading the DSP, without over-complicating the main do_loop.
Now the battle is over. Using Flowstone, any decent PC is able to execute the de-zipping at the audio sampling frequency, and if you do so, in theory there can't be audible zipping artifacts.
Steph