There are some helpful notes in the source code:
/* REGARDING THE MAX PEAK: This method assumes that the only important * sample in a look-ahead buffer would be the highest peak. As such, * instead of storing all samples in a look-ahead buffer, it only stores * the max peak, and compares all incoming samples to that one. * The max peak has a hold time equal to what the look-ahead buffer * would have been, which is tracked by a timer (counter). When this * timer expires, the sample would have exited from the buffer. Therefore, * a new sample must be assigned to the max peak. We assume that the next * highest sample in our theoretical buffer is the current input sample. * In reality, we know this is probably NOT the case, and that there has * been another sample, slightly lower than the one before it, that has * passed the input. If we do not account for this possibility, our gain * reduction could be insufficient, resulting in an "over" at the output. * To remedy this, we simply apply a suitably long release stage in the * envelope follower. */ /* REGARDING THE ATTACK: This limiter achieves "look-ahead" detection * by allowing the envelope follower to attack the max peak, which is * held for the duration of the attack phase -- unless a new, higher * peak is detected. The output signal is buffered so that the gain * reduction is applied in advance of the "offending" sample. */ /* NOTE: a DC offset is not necessary for the envelope follower, * as neither the max peak nor envelope should fall below the * threshold (which is assumed to be around 1.0 linear). */ /* REGARDING THE GAIN REDUCTION: Due to the logarithmic nature * of the attack phase, the sidechain will never achieve "full" * attack. (Actually, it is only guaranteed to achieve 99% of * the input value over the given time constant.) As such, the * limiter cannot achieve "brick-wall" limiting. There are 2 * workarounds: * * 1) Set the threshold slightly lower than the desired threshold. * i.e. 0.0dB -> -0.1dB or even -0.5dB * * 2) Clip the output at the threshold, as such: * * if ( in1 > thresh_ ) in1 = thresh_; * else if ( in1 < -thresh_ ) in1 = -thresh_; * * if ( in2 > thresh_ ) in2 = thresh_; * else if ( in2 < -thresh_ ) in2 = -thresh_; * * (... or replace with your favorite branchless clipper ...) */ }N