Dynamic Range Compression - Release???

DSP, Plugin and Host development discussion.
RELATED
PRODUCTS

Post

Hi,

I am trying to code up a basic dynamic range compressor in MATLAB and I am completely stumped on how the release parameter should be applied. I don't need to go into the ins and outs of envelope detectors, etc for the moment, just how the release parameter should be applied.

So, a dynamic compressor has a gain signal (calculated based on the level detection + gain computation). Once the input signal exceeds the chosen threshold, the compression will be applied as per the ratio, but the onset of the full compression ratio is delayed by the attack parameter.. ok, this makes sense to me.

Now, once the signal falls below the threshold, the compressor enters the release cycle.The input gain level drops below the threshold, the signal is still being compressed in the release cycle, but how is the initial amount of compression in the release cycle calculated? If the ratio is 2:1, what is this relative to in the release cycle?

Thanks
Ger

Post

There are many different approaches but most compressors are built around two basic topologies - "feed forward" and "feed back". In a typical "feed forward" compressor the envelope detector is usually completely separate from the threshold setting. The envelope detector follows the signal at all times and at all levels. The attack and decay times are usually with respect to the signal itself - i.e., the farther the signal rises or falls the faster it attacks/decays. When the level of the envelope exceeds the threshold, the "circuit" starts applying the difference between the control signal and the threshold level multiplied by the RATIO amount to the gain cell. The threshold is sort of a "gate" for the control signal.

In "feedback" compressors the control signal typically sits at a static level until the signal exceeds the threshold setting. When the output level of the compressor rises above the threshold setting the signal gets fed back into the level detector causing the gain to drop. The attack and decay times of this type of setup are usually with respect to the "zero" level - but not always. This type of compressor can sound very transparent but is not as straightforward mathematically as a feed forward compressor.

So, in short, there is no "typical way" that this works - there are many, MANY different approaches which is why there are so many comp/limiter designs available. It's an art, actually.

Post

Hi Fender19,

Thanks for your time and insights, but unfortunately I am none the wiser. I was already aware of all of what you have said here but I am just interested in how the release parameter is applied under the hood of a feed-forward dynamic compressor.

Could someone give me an example in pseudo-code or a basic formula, of how the release parameter could be applied to a feed-forward compressor once it enters its release cycle?

Lets take an example:

threshold = -15 dB
ratio = 2:1
attack = 10 ms
release = 100 ms

.
.
.
==============================================================================

This diagram from wikipedia for dynamic range compressors attempts to explain attack/release (not interested how correct wikipedia is, just the diagram here) http://en.wikipedia.org/wiki/Dynamic_ra ... ease-2.svg

In this example, I could understand how release is applied as the input signal drops instantaneously from +9 dB to 0 dB.. so the compressor output will also have to drop by 9 dB instantaneously and then ease back to 0 dB over the release period. But when the transition of the input signal from above to below threshold is not instantaneous, how is the level of compression calculated during the release cycle? Even if there are different approaches, could someone tell me about an approach they have seen/used/understand?

Post

I believe the fairly common method--

Threshold and ratio are decided/applied from the output of the envelope detector. That gain changing logic is not concerned with attack or release. The attack and release are properties of the envelope detector, and then the gain logic just works from the instantaneous current value of the envelope detector.

My envelope detectors usually work thusly--

-- Full wave rectifier on the audio, which in digital is just an abs(inputsample).
-- An if/then decision on the abs value
-- if the input is > the current envelope value, then the current env value is increased (first order filter in simplest case) using the attack time constant.
-- However, if the current abs value of the current sample is < the current envelope value, then the envelope value is decreased using the release time connstant.
-- So the same filter is applied to the abs value of each sample, but the attack TC is applied to increases, and the release TC is applied to decreases.
-- And then the gain changing logic will modulate the gain applied to the audio in whatever way makes sense to you, threshold, ratio, feed forward, feed back, whatever, basing its decisions on the current state of the envelope detector.

A hint which I find useful-- I often use a "pre detector" ahead of the main smoother which applies attack release smoothing. My pre-detector usually has instant attack and about 10 ms release. This gives a "solider signal" to drive the attack release envelope. This pre detector was fairly commonly seen in older analog compressors but dunno if they are still seen in modern analog comps.

In digital, feedforward topology is easiest to implement. Less strain on the brain.

In analog, feedback can often be easier to implement, because there is no ideal analog gain element, and feed back can sometimes make a better behaved compressor with less complicated control circuitry.

But "real precise" parameterized control of dynamics is easier achieved with feed forward IMO. Perhaps a feedback compressor could be made equally "scientifically precise" but it would require better insight into the process to make it precise.

Feedback compressors are easy to design and understand in principle and can operate in "musical" fashion, but the feedback makes the math more difficult to precisely predict and control if you want "fine control" of thresholds and ratios and such.

Post

g_loughnan wrote:Hi Fender19,

Thanks for your time and insights, but unfortunately I am none the wiser. I was already aware of all of what you have said here but I am just interested in how the release parameter is applied under the hood of a feed-forward dynamic compressor.

Could someone give me an example in pseudo-code or a basic formula, of how the release parameter could be applied to a feed-forward compressor once it enters its release cycle?

Lets take an example:

threshold = -15 dB
ratio = 2:1
attack = 10 ms
release = 100 ms

.
.
.
==============================================================================

This diagram from wikipedia for dynamic range compressors attempts to explain attack/release (not interested how correct wikipedia is, just the diagram here) http://en.wikipedia.org/wiki/Dynamic_ra ... ease-2.svg

In this example, I could understand how release is applied as the input signal drops instantaneously from +9 dB to 0 dB.. so the compressor output will also have to drop by 9 dB instantaneously and then ease back to 0 dB over the release period. But when the transition of the input signal from above to below threshold is not an instantaneous jump of a few dB above to a few dB below the threshold, how is the level of compression calculated during the release cycle? Even if there are different approaches, could someone tell me about an approach they have seen/used/understand?

Post

In order to generate smooth changes in gain reduction a compressor has to generate an envelope typically from the audio signal. The attack and release parameters dictate how quickly the envelope will rise or fall in value.

So if for example the input signal suddenly rises to a value of say 0 bB and the attack parameter is set to 30 ms it will take 30 ms for the envelope to reach 0 dB. Then if the signal falls to -80 dB and the release is set to 90ms then it would take 90 ms for the envelope to drop to -80 dB.

It is this envelope that is then compared to the transfer function to calculate the gain reduction.

Post

Often the envelope and the attack release are implemented using low pass filters. Here's a simple example.

Post

g_loughnan wrote:... how is the level of compression calculated during the release cycle? Even if there are different approaches, could someone tell me about an approach they have seen/used/understand?
OK, let's start with the most basic feed forward compressor.

You have two signal paths - one goes through the "gain cell" which is controlling the audio itself and a second path to the envelope detector. The envelope detector (in our simplest case) follows the input signal at all times. All you have to do is check to see if the most recent sample (absolute value) is bigger or smaller than the current envelope level.

If the new signal sample is bigger you "attack" by increasing the value via a filter of some type, (e.g., new value = previous value + 0.03 *new value) which would be a one pole low pass. "0.03" is just a number I threw in there but it must be <=1.0. This value sets the attack time constant and must be scaled to sample rate.

If the new sample value is smaller than the current envelope value you have a choice - you can start pulling the envelope down at a fixed rate (new envelope value -= some small value) which would give you a linear decay or you can pull it down using the "attack" process in reverse (new value = previous value - 0.0003*new value). Note that the decay "time constant" in any case must be slower than the attack time constant otherwise your control signal will simply ride the wave and not give you a smooth control (you will get distortion).

Then you take that control signal and compare it to your threshold setting. If the control signal is smaller than the threshold, do nothing. If the control signal is bigger than the threshold setting, subtract the threshold setting from the control value (to give you the DELTA, not the absolute control signal level) and then apply that signal multiplied by the ratio factor to the gain cell (i.e., output = audio input * control signal).

BTW - most feed forward compressors operate on DECIBELS which means you need to take the log10 of your input when forming the control signals then take the exponent 10 before applying that control signal to your gain cell. If you use the straight line decay approach that will give a constant decay rate in dB/sec. The attack time, using the filter approach, is "program dependent".

Post

matt42 wrote:Often the envelope and the attack release are implemented using low pass filters. Here's a simple example.
Just as a side-note, although this code is a nice way to illustrate the process, it's a recipe for big trouble sound wise. I'd even say that these pseudo-codes floating around are the main reason why most digital compressors sound like shit.

This particular implementation is a pure aliasing machine! The AR behavior is no more than a side-effect.

This discontinuity will create a signal of infinite bandwidth, resulting is strong aliases in the control (and thus audio) path. Same is true with the naive idea to use abs() as rectifier. These are seriously misleading starting points.

In fact, "attack release are implemented using low pass filters" is not really correct. This is most of all one (heavily) non-linear filter. One single filter which changes its coefficient depending on the change rate polarity. That's a much better starting point, because you'll have to bandlimit the nonlinearity: You simply can't do that with direct branching (at least for the average case).

Finally, a PCM dynamics compressor is not a music dynamics compressor! Not even close.
Fabien from Tokyo Dawn Records

Check out my audio processors over at the Tokyo Dawn Labs!

Post

Well, compression is a nonlinear process and can be set in such ways as to sound very bad.

I'd love to read suggestions on how to do it right, rather than a simple declaration that "if/then conditional on abs(input)" is wrong.

I am criminally ignorant and get more so every day, and honestly would like to know the superior method. Variations on "if/then conditional on abs(input)" seem to be the exact same thing seen in so many analog compessors whose envelopes are based on steering diodes?

Am not denying there may be better methods, but whatever warts in that simple method are directly inherited from analog compressors which are presmably at least somewhat musical? Otherwise people wouldn't have used analog compressors, and paid so much money for them, over previous decades?

Post

Have a closer look a diode's behaviour, it's in no way equivalent to an "if". The argumentation and conclusion in your last paragraph is confusing. Forget the analogue thing for a second.

The main issue is the requirement for bandlimiting (Nyquist). The "if"s in the example code above extend the bandwidth to infinity in at least 3 cases. This means: plenty aliasing + plenty aliasing + plenty aliasing. In short, a pile of garbage.

There's no proper way of bandlimiting a branch, it's a dead end. You can't really make an "if" less "branchy". I explained above how the AR "if" can be eliminated.

The code doesn't handle the potential bandwidth extension introduced by the central gain multiplication => it generates even more aliasing, in a highly reliable and reproducible manner.

And finally, an audio compressor needs to know about the true waveform in order to control it properly. Obvious. Try to drive a car lights off, only with google maps on your phone! Funny, but this is exactly what this piece of code does! That's not how you learn to drive. :)

The code above really just controls the PCM data in a super crude geometric manner. It's an aliasing machine.


There's no "superior" method (except maybe NOT using branches near the audio path). The only relevant reference is the Nyquist theorem, no voodoo at all.
Fabien from Tokyo Dawn Records

Check out my audio processors over at the Tokyo Dawn Labs!

Post

FabienTDR wrote:Just as a side-note, although this code is a nice way to illustrate the process, it's a recipe for big trouble sound wise. I'd even say that these pseudo-codes floating around are the main reason why most digital compressors sound like shit.
Well that was the point really, just illustrating the process.

Of course anyone directly implementing this should instantly realize that it sounds like shit on hearing the results - then they can start to figure out why it sounds so shit and think about how to improve the design.

Post

JCJR wrote: I'd love to read suggestions on how to do it right, rather than a simple declaration that "if/then conditional on abs(input)" is wrong.
Not anything uber-special, but has helped me alot:

Code: Select all

float smoothABS ( float a, float smoothness )
{
 return (sqrtf((a*a)+ smoothness))- sqrtf(smoothness);
}
Once you have a decent abs, you can make your own min/max/clip, and then go from there.

Regards
Andrew

Post

Hi guys,

Thanks for your response. I haven't had too much time to look into it since, hence the delayed reply.
matt42 wrote:So if for example the input signal suddenly rises to a value of say 0 bB and the attack parameter is set to 30 ms it will take 30 ms for the envelope to reach 0 dB. Then if the signal falls to -80 dB and the release is set to 90ms then it would take 90 ms for the envelope to drop to -80 dB.
That makes perfect sense to me, but how does threshold fit into this scheme? If the threshold is set to, say, -15 dB, signal level rises from -80 dB to 0 dB, I thought the attack time only comes into effect once the signal (or envelope?) exceeds -15 dB? And the same for release time, once signal drops below -15 dB, the compression is phased out once the signal drops below 15 dB?

Post

Please take a look at the example code I linked to.

The attack and release parameters relate to the envelope. In other words the envelope signal rises and falls at a rate dictated by the attack and release parameters.

If the envelope signal level is lower than the threshold then there is no gain reduction. If the envelope signal exceeds the threshold then there will be gain reduction.

Post Reply

Return to “DSP and Plugin Development”