IIR rms envelope detector?
-
- KVRian
- 641 posts since 30 Aug, 2012
I am trying to model the "true rms" level detector as used in many famous electronic compressors like the dbx 160. An analog "IIR" style filter (not FIR/sliding window).
I have tried the "textbook" approach - square the input; run it through a single pole low pass filter, then take the square root - but the dynamic response is quite different than the dbx 160. The dbx 160 and the "textbook" rms detector both use a single, fixed time constant for attack and release yet the attack time of the "textbook" filter is much slower than dbx for the same release time. So something is not quite right with the square->LP->root approach - at least for audio compressor applications. It reacts "sloppy" whereas the dbx reacts "tight".
I have also tried modeling a "log domain" rms detector based on the Blackmer (dbx) electronic log/antilog approach - which sounds very close to dbx - but it requires feedback (infinite iterations within each sample) to compute. My attempt to derive an explicit equation so far has been only mildly successful - there must be an exact explicit solution that is perhaps far more direct.
RMS detection is a common audio DSP requirement so I feel there must be an IIR algorithm for it - but so far "Google" has failed me!
Any pointers (pun intended) appreciated.
I have tried the "textbook" approach - square the input; run it through a single pole low pass filter, then take the square root - but the dynamic response is quite different than the dbx 160. The dbx 160 and the "textbook" rms detector both use a single, fixed time constant for attack and release yet the attack time of the "textbook" filter is much slower than dbx for the same release time. So something is not quite right with the square->LP->root approach - at least for audio compressor applications. It reacts "sloppy" whereas the dbx reacts "tight".
I have also tried modeling a "log domain" rms detector based on the Blackmer (dbx) electronic log/antilog approach - which sounds very close to dbx - but it requires feedback (infinite iterations within each sample) to compute. My attempt to derive an explicit equation so far has been only mildly successful - there must be an exact explicit solution that is perhaps far more direct.
RMS detection is a common audio DSP requirement so I feel there must be an IIR algorithm for it - but so far "Google" has failed me!
Any pointers (pun intended) appreciated.
Last edited by Fender19 on Thu Dec 19, 2019 12:32 am, edited 1 time in total.
-
- KVRist
- 53 posts since 4 Sep, 2014
By log domain do you mean the exponential approach? That is,
Rms = rms * coeff + in*in*(1-coeff)
Out = sqrt(rms)
Where ms = millisecond attack
Coeff=exp(-1/(srate * 0.001 * ms))
Obviously in can be lowpass filtered etc
Rms = rms * coeff + in*in*(1-coeff)
Out = sqrt(rms)
Where ms = millisecond attack
Coeff=exp(-1/(srate * 0.001 * ms))
Obviously in can be lowpass filtered etc
-
- KVRian
- Topic Starter
- 641 posts since 30 Aug, 2012
Thank you for the code snippet. That seems to be an example of the "textbook" approach I was referring to but I will take a look.sault wrote: Wed Dec 18, 2019 9:42 pm By log domain do you mean the exponential approach? That is,
Rms = rms * coeff + in*in*(1-coeff)
Out = sqrt(rms)
Where ms = millisecond attack
Coeff=exp(-1/(srate * 0.001 * ms))
Obviously in can be lowpass filtered etc
The log domain is how most VCA-based analog compressors work. The control signal is processed entirely in the log10 domain (volts per decibel). It is easy to apply ratios, thresholds, etc., to log signals as simple sums and multiplications. They take the log10 of the input signal and filter it using a "log domain filter". The charging current into the logging capacitor is the antilog of the voltage difference between the log input and the capacitor. The "electronic" version looks something like this:
1) newsidechaininput = 2*log10(input)//---2x log10 of input performs x^2 function in log domain
2) rmsfilter = rmsfilter + tao * 10^(newsidechaininput - rmsfilter) - tao;//---rms averaging
3) vcadrive = 10^(rmsfilter/2)//---antilog of rmsfilter/2 takes square root and yields linear control voltage to VCA (skipped in most compressors as the VCAs themselves are antilog, db/volt).
The problem I have is with line #2. If the step size of the input is too big (>40dB) the antilog of it swamps the tao value and the detector overshoots. It works in electronic form because of the instantaneous feedback to the antiloging transistor. In digital form the duration of one sample causes it to overshoot - so it requires an iterative or explicit function to account for that. It's a feedback modeling situation that surely has an explicit solution - I just can't figure out what it is!
Whatever the case, both approaches SHOULD sound the same (rms is rms, right?) - but they don't. The "log domain" filter definitely has a different response shape/sound. But I will give your code a try!
Last edited by Fender19 on Wed Dec 18, 2019 11:14 pm, edited 4 times in total.
-
- KVRian
- Topic Starter
- 641 posts since 30 Aug, 2012
I just gave this a try and it is like the "square->LPF->root" approach I first tried. It allows some transient signals to blast through whereas the "log domain" detector (ala dbx) does not do that. It is a different result altogether that can be heard and seen on level meters and when graphed in tools like Plugin Doctor. The log domain detector has a much faster attack time for the same release time.
So, apparently, rms is not rms! Either that or what dbx calls "true rms" actually isn't.
-
- KVRist
- 53 posts since 4 Sep, 2014
By definition RMS is going to miss transients... a setting of even 20 ms is going to miss a 7 ms spike. One possible fix is to add predelay. If the detector is set at 5 ms it will take a good 10-15 ms to capture/fully respond to that signal change... so delay the input signal by 5 ms relative to the detector. Another option is to tweak coeff to exp(-2/...) or exp(-3/...). There’s also using different rms values when the wave is increasing vs decreasing...
I haven’t seen that type of detector, that’s really interesting to me, I’ll have to play around with it. When you say that one sample delay causes it to blow up then I immediately start wondering what happens if it is oversampled at 2x, 4x, etc?
The second thought I had... what about
... tao * 10^( tanh(c*(sidechain - rms))/c) - tao ?
If it blows up at 40 dB, in other words, then limit the difference that sidechain-rms can be. Pick the right value of c (0.8? 2?) and you keep it from blowing up. Use a function like arctan and it can even get really nonlinear.
Just brainstorming, I’ll have a think about it a little more.
I haven’t seen that type of detector, that’s really interesting to me, I’ll have to play around with it. When you say that one sample delay causes it to blow up then I immediately start wondering what happens if it is oversampled at 2x, 4x, etc?
The second thought I had... what about
... tao * 10^( tanh(c*(sidechain - rms))/c) - tao ?
If it blows up at 40 dB, in other words, then limit the difference that sidechain-rms can be. Pick the right value of c (0.8? 2?) and you keep it from blowing up. Use a function like arctan and it can even get really nonlinear.
Just brainstorming, I’ll have a think about it a little more.
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
You are confusing RMS with the compressor envelope processing.
1. compute "squared" RMS by squaring the input, then feeding it through a low-pass filter (in "linear" domain)
2. convert the (squared) smoothed RMS value into decibels (ie. 10/log(10)*log(rms2), since we have squared values)
3. process the envelope in the log-domain using whatever attack and release you want
4. exponentiate the processed envelope back into a gain multiplier.
Note that step 1 tries to estimate the input envelope and has nothing to do with attack and release (which are done in step 3). Squaring the signal gives you the sum and difference frequencies (of all pairs of partial, which is why this theory works "correctly" only for sinusoidal inputs, but the good news is that it works "reasonably" for anything). It's the difference frequencies that end up near DC and represent the actual envelope of the signal and your initial low-pass simply wants to separate these from the sum frequencies which we don't care for.
Essentially you want to keep the stuff below 20Hz or so (lower you put the cutoff, the more sluggish) and filter out anything above (and the higher you put the cutoff, the more "ripple" will bleed from low input frequencies). Note that since this is really just another frequency-domain filtering problem, you CAN use steeper filters rather than one-pole as well to improve performance (just be careful with how you handle overshoots).
Either way, the point I'm trying to make is that envelope detection (ie. computing the RMS) and envelope smoothing (ie. computing how the gain reduction varies) are two different things.
1. compute "squared" RMS by squaring the input, then feeding it through a low-pass filter (in "linear" domain)
2. convert the (squared) smoothed RMS value into decibels (ie. 10/log(10)*log(rms2), since we have squared values)
3. process the envelope in the log-domain using whatever attack and release you want
4. exponentiate the processed envelope back into a gain multiplier.
Note that step 1 tries to estimate the input envelope and has nothing to do with attack and release (which are done in step 3). Squaring the signal gives you the sum and difference frequencies (of all pairs of partial, which is why this theory works "correctly" only for sinusoidal inputs, but the good news is that it works "reasonably" for anything). It's the difference frequencies that end up near DC and represent the actual envelope of the signal and your initial low-pass simply wants to separate these from the sum frequencies which we don't care for.
Essentially you want to keep the stuff below 20Hz or so (lower you put the cutoff, the more sluggish) and filter out anything above (and the higher you put the cutoff, the more "ripple" will bleed from low input frequencies). Note that since this is really just another frequency-domain filtering problem, you CAN use steeper filters rather than one-pole as well to improve performance (just be careful with how you handle overshoots).
Either way, the point I'm trying to make is that envelope detection (ie. computing the RMS) and envelope smoothing (ie. computing how the gain reduction varies) are two different things.
-
- KVRian
- Topic Starter
- 641 posts since 30 Aug, 2012
I understand how it works. I designed and manufactured this guy - and bunch of others - 25 years ago:https://reverb.com/uk/item/4124812-rock ... -bus-blackmystran wrote: Thu Dec 19, 2019 12:32 pm You are confusing RMS with the compressor envelope processing.
Either way, the point I'm trying to make is that envelope detection (ie. computing the RMS) and envelope smoothing (ie. computing how the gain reduction varies) are two different things.
But now we're in the digital world and I'm trying to design in DSP.
The rms envelope computed in the dbx 160 hardware IS the control envelope - there is no other filtering of the control signal. It's done with a single stage "log domain" filter: https://books.google.com/books?id=lYvwB ... er&f=false
Now, it appears that my "log domain filter" DSP equation I derived from the analog schematics was missing a term. Instead of env += tao * 10^(new in - env) - tao it should be env += tao * log10 (10^(newin - env) - tao. The log10(x) and 10^(x) terms cancel which brings the whole thing back into the linear domain. It has the exact same response as the linear domain rms code that Sault posted. So, I made an error in the DSP algorithm. (not my first or likely my last!)
Yes, signals with a high crest factor WILL get through an rms detector with little effect on the computed rms level. Pre-delay (lookahead) doesn't change that - it only helps with initial attack steps.sault wrote: Thu Dec 19, 2019 5:39 am By definition RMS is going to miss transients... a setting of even 20 ms is going to miss a 7 ms spike. One possible fix is to add predelay.
What is baffling to me is that the "true rms" electronic dbx compressors catch transients better than this DSP rms filter with the same time constants. The dbx compressors sound "tight" whereas a compressor built with this DSP rms detector sounds (and shows on meters) as "sloppy". Why?
- KVRAF
- 8476 posts since 12 Feb, 2006 from Helsinki, Finland
You simply do not have an RMS signal until you filter a squared signal in linear domain, or something mathematically equivalent. As for DBX compressors, the schematics are available.Fender19 wrote: Thu Dec 19, 2019 9:04 pm The rms envelope computed in the dbx 160 hardware IS the control envelope - there is no other filtering of the control signal.
-
- KVRist
- 126 posts since 2 Nov, 2014
I think you fundamently don't understand the concept of RMS value of a signal.What is baffling to me is that the "true rms" electronic dbx compressors catch transients better than this DSP rms filter with the same time constants. The dbx compressors sound "tight" whereas a compressor built with this DSP rms detector sounds (and shows on meters) as "sloppy". Why?
You can measure RMS value of "across" let say 3 samples of an audio signal, or across 5 seconds(!) of an audio signal. You can even calculate RMS value of a whole full lenght song.
There is no one single RMS value of a signal. It depends on an "RMS window/time". Shorter, let's say 3-5ms RMS averaging time, will yield faster results, then let's say 120ms RMS.
RMS compressor with short 2ms RMS window and with fast attack and release time will sound tighter than, let's say peak compressor with really long attack and release times.
-
- KVRian
- Topic Starter
- 641 posts since 30 Aug, 2012
I understand rms. What I don't understand is why the dbx hardware compressors - that use "log domain" rms detectors - have faster transient response than the "textbook" definition of rms calculation with the same time constants (as obtained from the dbx datasheets).zenvoxpop wrote: Sat Dec 21, 2019 9:37 amI think you fundamently don't understand the concept of RMS value of a signal.What is baffling to me is that the "true rms" electronic dbx compressors catch transients better than this DSP rms filter with the same time constants. The dbx compressors sound "tight" whereas a compressor built with this DSP rms detector sounds (and shows on meters) as "sloppy". Why?
You can measure RMS value of "across" let say 3 samples of an audio signal, or across 5 seconds(!) of an audio signal. You can even calculate RMS value of a whole full lenght song.
There is no one single RMS value of a signal. It depends on an "RMS window/time". Shorter, let's say 3-5ms RMS averaging time, will yield faster results, then let's say 120ms RMS.
RMS compressor with short 2ms RMS window and with fast attack and release time will sound tighter than, let's say peak compressor with really long attack and release times.
![]()
One difference I've noted is that the Blackmer/dbx rms envelopes have linear decibel release slopes (10^1/t) whereas the "textbook" rms detectors discussed here have e^1/t release slopes. So right off the bat there appears to be a fundamental difference. Some of the dbx detectors also use dual rms sections in quadrature to reduce ripple at low frequencies (sin^2 + cos^2 = 1) which may contribute to that "tight" sound.
Anyhow, I have gone beyond the title of this thread. What I am looking for is more complicated than just "rms". Thank you, Sault, for the code you posted above. It helped me understand that the dbx-style "log domain" rms filter is something special that will require more work to model in DSP. The difference in sound is significant.
- KVRian
- 1091 posts since 8 Feb, 2012 from South - Africa
According to this the dbx definition of RMS is a bit loose, to say the least. https://www.uaudio.com/webzine/2008/march/index2.html There is also the long standing rumour (apparently from the designer himself) that the power supply is under-specced and causes some 'issues' when the passing the threshold.
-
- KVRian
- Topic Starter
- 641 posts since 30 Aug, 2012
Yes! Thank you for that link - that is exactly what I am talking about. Dbx literature has always referred to the 160 as "true RMS" but it is not the "textbook" RMS we know as the algorithm discussed above. The dbx true rms compressors have a tight response whereas the textbook true rms compressors sound "sloppy".Ichad.c wrote: Wed Jan 08, 2020 5:08 pm According to this the dbx definition of RMS is a bit loose, to say the least. https://www.uaudio.com/webzine/2008/march/index2.html
I have a version of DSP math worked out but I cannot get it into explicit form. It is a recursive exponential that gets very complicated very fast (emulating real time non-linear feedback). Any suggestions on how to boil it down? It cannot be iterated in real time as it would take thousands of iterations using CPU load-prohibitive exponential calculations. I don't have a grasp of the "modal DK method" of emulation but that is what is apparently required...
