public sealed class LimiterEffectA ceiling nothing gets past, without the distortion of a clamp.
No guide page documents this yet — the page shows what the code says about itself.
Remarks
What this replaces. The master used to end in Math.Clamp(x, -1, 1). That is a brickwall in the sense that nothing above one comes out, and it is also hard clipping: every sample above the rail becomes a flat top, which is audible as buzz the moment a scene gets busy. The clamp is still there behind this, demoted to what it should always have been — a guard against a NaN or an overshoot nothing caught, not a level control.
Look-ahead is what makes it transparent. The signal is delayed by a couple of milliseconds and the gain is decided from what is about to come out. So the gain has already come down by the time a transient arrives, and the step that brings it down happens during the quiet part before it, where nobody can hear it. Without look-ahead a limiter has to choose between reacting late — letting the peak through — and reacting instantly, which is a step in the middle of the waveform and is itself a click.
The detector is a sliding-window maximum, and that is what makes the ceiling a guarantee. A one-pole envelope, which is what a compressor uses, only approaches the peak — so a fast enough transient escapes it. Taking the true maximum over exactly the look-ahead window means the gain applied to a sample was computed from a window that contains that sample. The window maximum is kept in a monotonic deque, so it costs amortised constant time per sample rather than a scan.
The cost is latency: LookAheadSeconds of it, two milliseconds by default. That is a fifth of one 480-frame block and is well below what anybody notices, but it is real and it is why this is a master-bus effect rather than something to put on six buses.
Fields and properties (7)
public float CeilingDbThe loudest sample allowed out, in decibels. 0 dB is full scale.
public float LookAheadSecondsHow far ahead it looks, and therefore how much latency it adds.
public float ReleaseSecondsHow fast it lets go once the loud part has passed.
public bool EnabledWhether it does anything. A bypassed effect costs one branch a block.
public float GainReductionDbHow much it is currently taking off, in decibels. Never positive.
public int LatencyFramesHow much latency it is adding, in frames.
public IReadOnlyList<string> PropertiesThe knobs this effect will answer to, by name.
Methods (5)
public void Prepare(in AudioFormat format, int maxFrames)Sizes and clears every buffer the effect needs.
public void Process(Span<float> buffer, int frameCount, int channels)Processes a block in place.
public void Reset()Throws away everything the effect remembers about what came before.
public bool TrySetProperty(string name, float value)Sets one of the effect's knobs by name, for automation.
public bool TryGetProperty(string name, out float value)Reads one of the effect's knobs by name.
Used by (5)
- AudioEngineVixen.Audio
- DynamicsTestsVixen.Audio.Tests
- LimiterEffectAssetVixen.Audio
- MixControlTestsVixen.Audio.Tests
- MixerAssetTestsVixen.Audio.Tests