[music-dsp] 2nd order biquad for envelope detector?
Alex Raider
flashinc at mail.ru
Fri May 21 04:17:07 EDT 2004
Hi.
> I am exploring the possibility of using a 2nd order biquad for an envelope
> detector. After some testing, comparing results with poplular products, I'm
> just not getting the attack shape that I want from 1-pole low-pass filters.
> I've tried all sorts of stuff in the coefficient calculation, but nothing
> seems to work. So I've been toying with the idea of using a 2nd order biquad
> for the job, but haven't had time to implement it yet.
> Is this ever done in dynamics processors? I seem to remember a thread from
> the archives (which, of course, I can't find now) that mentioned an AES
> paper on using higher order filters (with low Q values, presumably) for
> smoother envelopes. Anyone remember this?
> Also, does anyone have any advice/opinion on the subject?
> == chunk
You on a wrong way, because you not need frequency domain filter.
Increasing filter order just gives you stronger rolloff (better
performance in frequency domain). "Biquad" just the name for
technique for analog IIR filter design.
To do envelope extracting, you need time domain processing.
Averaging filter is most suitable for that.
averager is perfect "smoother" - thats we looking for.
And this kind of processing is opposite to frequency domain processing.
The first order lowpass does perfect job.
You can, however try to averaging N points of input signal:
N/2
1/N * SUMM( x[n] )
-N/2
For those who looking for compressor...
Below is a hardknee compressor prototype,
with windowing RMS look-ahead envelope calculation,
adjustable attack/decay times.
DSP algo modelled in matlab.
RMS is a true way to estimate _musical_ signal energy,
our ears behaves in a same way.
I ripped off some pre-processing and post-processing stuff,
but envelope calculation and hard knee`d compressor
is correct and should work.
void compress
(
float* wav_in, // signal
int n, // N samples
double threshold, // threshold (percents)
double slope, // slope angle (percents)
int sr, // sample rate (smp/sec)
double tla, // lookahead (ms)
double twnd, // window time (ms)
double tatt, // attack time (ms)
double trel // release time (ms)
)
{
typedef float stereodata[2];
stereodata* wav = (stereodata*) wav_in; // our stereo signal
threshold *= 0.01; // threshold to unity (0...1)
slope *= 0.01; // slope to unity
tla *= 1e-3; // lookahead time to seconds
twnd *= 1e-3; // window time to seconds
tatt *= 1e-3; // attack time to seconds
trel *= 1e-3; // release time to seconds
// attack and release "per sample decay"
double att = (tatt == 0.0) ? (0.0) : exp (-1.0 / (sr * tatt));
double rel = (trel == 0.0) ? (0.0) : exp (-1.0 / (sr * trel));
// envelope
double env = 0.0;
// sample offset to lookahead wnd start
int lhsmp = (int) (sr * tla);
// samples count in lookahead window
int nrms = (int) (sr * twnd);
// for each sample...
for (int i = 0; i < n; ++i)
{
// now compute RMS
double summ = 0;
// for each sample in window
for (int j = 0; j < nrms; ++j)
{
int lki = i + j + lhsmp;
double smp;
// if we in bounds of signal?
// if so, convert to mono
if (lki < n)
smp = 0.5 * wav[lki][0] + 0.5 * wav[lki][1];
else
smp = 0.0; // if we out of bounds we just get zero in smp
summ += smp * smp; // square em..
}
double rms = sqrt (summ / nrms); // root-mean-square
// dynamic selection: attack or release?
double theta = rms > env ? att : rel;
// smoothing with capacitor, envelope extraction...
// here be aware of pIV denormal numbers glitch
env = (1.0 - theta) * rms + theta * env;
// the very easy hard knee 1:N compressor
double gain = 1.0;
if (env > threshold)
gain = gain - (env - threshold) * slope;
// result - two hard kneed compressed channels...
float leftchannel = wav[i][0] * gain;
float rightchannel = wav[i][1] * gain;
}
}
to making all it work,
try for first time:
threshold = 50%
slope = 50%
RMS window width = 1 ms
lookahead = 3 ms
attack time = 0.1 ms
release time = 300 ms
This code can be significantly improved in speed by
changing RMS calculation loop to 'running summ'
(keeping the summ in 'window' -
adding next newest sample and subtracting oldest on each step)
Alex Raider / Flash inc.
More information about the music-dsp
mailing list