Vixen
02b45cc4
csharp
public sealed class LimiterEffect

A 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 CeilingDb

    The loudest sample allowed out, in decibels. 0 dB is full scale.

  • public float LookAheadSeconds

    How far ahead it looks, and therefore how much latency it adds.

  • public float ReleaseSeconds

    How fast it lets go once the loud part has passed.

  • public bool Enabled

    Whether it does anything. A bypassed effect costs one branch a block.

  • public float GainReductionDb

    How much it is currently taking off, in decibels. Never positive.

  • public int LatencyFrames

    How much latency it is adding, in frames.

  • public IReadOnlyList<string> Properties

    The 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