<<home  <<previous  next>>

Quadrature Compander

(download Pure Data patches at page bottom)

In my live performance tool Instant Decomposer I use amplitude compression and limiting at several points in the signal flow. At the input side, it helps my voice to sound closer and more detailed. At other points it regulates submix levels. While I am doing amplitude regulation anyway, I take the opportunity to expand the lowest amplitude range and thereby attenuate background noise. The compander is an expander/compressor/limiter. This is all done with an experimental technique using an analytic signal, to which the title 'quadrature compander' refers.

Below is an example plot of input-output amplitude mapping with expansion, compression and limiting in one smooth curve, as compared to linear amplification.



At this point, it is important to define 'signal amplitude', the entity to be mapped from input to output with a non-linear curve. The regular way of computing amplitude of an arbitrary signal is by computing the root of mean of squared sample values (RMS) over a specified time interval. That time interval should match the lowest audio-frequencies in the signal, to avoid falsely recorded amplitude modulation.

There is also a method to compute instantaneous amplitudes, with help of an analytic signal. An analytic signal consists of two phases, the second of which is sometimes called quadrature phase. Hence the title quadrature compander. Apart from the popular frequency shifter, this was the first occasion where an analytic signal appeared to be of practical use for me. The advantage of instantaneous amplitudes is the fast detection of a sudden amplitude rise.

Methods to derive analytic signals are discussed on the page 'complexify a real signal'. For the quadrature compander (and anywhere else) I use the IIR all-pass filter method. Below is an example plot of amplitude computation done with the IIR method. The amplitude curve shows an overshoot effect at the attack, caused by the recursive filters:

amplitude with analytic signal

For comparison, here is the same signal, and it's amplitude now measured with the RMS method:

amplitude with RMS method

The RMS method cannot be precise in time, because it works with signal blocks. But with the analytic signal method, there is a delay in the measurement as well. That delay is frequency-dependant, caused by the IIR filter response. The amplitude peak seems to be delayed by half a cycle when I take a closer look:

amplitude with analytic signal

a brutal shortcut

Since the measurement delay with the analytic signal is frequency-dependant, there is no practical way to sync the amplitude curve with the original signal. To cut things short, I decided to use the analytic signal itself as the audio, by summing real and imaginary phases and reduce the resultant amplitude with factor 1/sqrt(2). Then, the measured amplitude will by definition always exactly match the processed signal.

This procedure will completely ruin the phase relations within the signal. A cardinal sin in dsp land. Will the summation of the real and imaginary phase not cause phase cancellations, and thereby reduce or even eliminate some frequencies? No, it will not, because real and imaginary phases are orthogonal, and thus complementary in the summation. Further down, I will discuss the implications in more detail. For the moment, I will just employ my brutal shortcut and continue with the amplitude compander.

periodic amplitude modulation

All compound signals, harmonic recipes included, display amplitude modulation. The amplitude compander must be made insensitive to periodic amplitude modulation. With the RMS method, this can be done simply by selecting the appropriate time interval: twice the period of the lowest harmonic tones in the signal. That can be quite long.

When using instantaneous amplitudes, periodic amplitude modulations are a real pain. They must somehow be ignored by the amplitude calculator. Both the problem and a solution are illustrated on the page 'Slicing Odd Beats', where I was doing attack detection. The trick is to use a peak envelope of the amplitude. The peak envelope of periodic amplitude modulation looks like this:


With the amplitude peak envelope, a sudden amplitude rise will be followed with precision, while periodic modulation will be smoothed to an extent of choice. The time constant in the enveloper sets the envelope decay ratio, and thus the smoothing effect. The amplitude envelope of even the freakiest signals can be approximated this way:


Next thing is the design of input-output amplitude mapping curves. As the example plot on top of page showed, noise suppression, signal compression and limiting can be done in one smooth curve. I want that curve to be calculated from a couple of parameters:

1. compander factor
2. rotation point

For ease of use, the signal is always limited to y = 1. Compander factor is the output gain factor at the limiter start point. Rotation point is the lower point where x = y, separating the attenuation range from the amplification range. Here is the earlier example plot once more, showing a compander factor 1 and rotation point at amplitude 0.18:


With these two parameters, it is very easy to set the curve in such a way that microphone noise is below the rotation point, and thus attenuated. However, the amount of attenuation is dependant on the compander factor, and so is the amount of amplification above the rotation point. Here is a more extreme setting with compander factor 2 and rotation point at amplitude 0.1:


Here is how these curves are computed. All y values for x above the limiter start point are just set to 1. The limiter start point is at x = 1 / compander factor. In the plot above it is at x = 0.5. The smooth curve proper is a quarter of a sine cycle (with angle 0.5 * pi * compander factor, in radians) raised to a power. The exponent is a function of both rotation point and compander factor. All taken together:

y = sin(companderfactor*0.5*pi*x)^exponent for x <= 1/companderfactor
y = 1 for x > 1/companderfactor
exponent = log(rotationpoint)/log(sin(companderfactor*rotationpoint*0.5*pi))

punch and suck

One disadvantage of fast compression/limiting can be the muffling of transients. Compressed percussion may sound less powerful. Therefore it is sometimes opportune to deliberately slow down the compander response a bit, and let transients pass with their full strength. For similar reason, compressor release time can be slowed down. Transient peaks are then followed by an amplitude depression, making the peaks stand out. Such producer tricks make sounds interact with each other, and even a limited set of sounds can result in lively music.

My quadrature compander has no separate attack and release settings. But I can slow down response time by using a lo-pass filter on the amplitude peak envelope. The result is a clearly defined attack in percussive sounds. In the example below, I have clipped the attack to create a punch effect:


punch in the output

The recovery time of the quadrature compander can be extended by setting a high value for the peak envelope time constant. Combined with high compander factor, this setting will result in a 'suck' effect like plotted here:



With only four user parameters the quadrature compander is complete. I have implemented the scheme as a Pure Data abstraction [qompander~]. It's use is straightforward. The rotation point parameter is called compander point and for ease of use it is set in deciBel with a range of -96 till -20 dB.


Here is the inside of the [qompander~] abstraction:

[qompander~] abstraction

The patch contains some subroutines, of which [pd exponent] and [pd mapping] are shown below. The subroutine [pd pyth] does pythagoras to find the amplitude.

subroutine [pd exponent]
subroutine [pd mapping]

[pd olli~] is my Pd implementation of Olli Niemitalo's quadrature transformer, using biquads. This could be done much more efficient in a specialised Pd class but I have not done that yet.

subroutine [pd olli~]

You can download [qompander~] and a help patch from the page bottom and use it if you have Pure Data installed.

summing analytic signal phases

Higher up I mentioned my brutal shortcut which came in handy for the quadrature compander: summing the phases of an analytic signal and using this as the audio. Phase relations within the signal will be heavily distorted by this action, which is reflected in an altered waveform. It is funny that I have never heard a difference though. Let's see what is going on.

Below is an example of a signal with two harmonic frequency components which I ran through the quadrature summator.

280 + 560 Hz signal with phase rotations

Input and output sound completely identical, although their waveshapes differ. The frequency content has not changed. I know that the ears and brains are not sensitive to static phase information, but then why are dsp engineers always so zealous when it comes to linear phase filtering? Well, it is clear that you cannot recombine the output with the original. There will be phase cancellation effects, and thus unintended filtering. That is one thing. You must not use the original signal and the quadrature compander output in parallel.

Further I noticed that the onset of a sound has a different character, at least visually. Here is again a sinewave resonator starting neatly from 0 radians, and it's phase rotated version:

60 Hz sinewave resonator with phase rotation

When I compare these sounds in ideal listening conditions, I notice a subtile increase in high frequency content at the attack, caused by the tiny blob that arose from the phase rotation. This effect is so minute, that I can not perceive it in normal music listening situations. But when the signal is heavily compressed, such artefacts become noticeable.

parallel compression

If you want to do 'parallel compression' with the quadrature compander, an extra action is required. Just like you would normally account for the latency of a compressor, by adding equivalent delay to the original signal, you would now add the analytic summator routine to the original signal. Or else you could run the original signal through a second quadrature compander with moderate settings.

I am quite satisfied with the quadrature compander, particularly because of it's fast response. Therefore I will put up with the inconvenience of phase rotations and use an extra compander in case of parallel processing.

Download Pure Data patches here:

qompander.zip, 4 KB, contains qompander~.pd and qompander~-help.pd

works with Pd extended

vcompander.zip, 4KB, contains vcompander~.pd and vqompander~-help.pd

works with vanilla Pd but is more CPU intensive than [qompander~] for Pd extended