Skip to main content

Interface: EqualizerPresetChainOptions

Defined in: packages/player/src/equalizer-presets.ts:351

Options for equalizerPresetChain.

Properties

bandwidthOctaves?

readonly optional bandwidthOctaves?: number;

Defined in: packages/player/src/equalizer-presets.ts:398

Bell width per band, in octaves. Defaults to 1 — one octave, which is the spacing of EQUALIZER_BANDS, so the bells tile the spectrum evenly. Narrower is more surgical and more audible as "EQ"; wider is smoother.


editable?

readonly optional editable?: boolean;

Defined in: packages/player/src/equalizer-presets.ts:426

Compile a chain whose gains can be changed while it plays. Defaults to false. This is what a slider bank wants; useEqualizer turns it on.

Rewriting af is how a chain is normally changed, and it is the wrong tool for a drag: mpv destroys and recreates every entry whose arguments differ (filters/f_output_chain.c:554-561), so dozens of writes a second means dozens of filter rebuilds a second. Player.setAudioFilterParam avoids that by pushing one number into the running filter — but it can only do so when the entry carries a label, and only when the rest of the chain has not moved.

So this option changes two things, both in service of that:

  • Every entry is labelledEQUALIZER_PREAMP_LABEL, equalizerBandLabel per band, EQUALIZER_LIMITER_LABEL.
  • The shape stops depending on the gains. All ten bands are emitted even at 0 dB, and the pre-amp is emitted even at 0 dB, so moving a band through zero does not add or remove an entry. (A band at 0 dB is an exact identity biquad — A = 1 makes the RBJ numerator and denominator equal — so the ten always-present bands change nothing but the CPU bill, which is ten biquads.)

What does not change: a completely flat curve still compiles to an empty chain. An equaliser nobody has touched costs nothing either way, and the flat ↔ touched transition is the one rebuild a drag can still cause.


limiter?

readonly optional limiter?: boolean;

Defined in: packages/player/src/equalizer-presets.ts:392

Append a brickwall limiter (alimiter) as the last EQ stage. Defaults to true, and is on for every curve that is not flat — including a curve that only cuts, and including a single band at +0.1 dB.

That sounds like overkill and is not, because the pre-amp and the limiter bound different things:

  • The pre-amp is a frequency-domain bound. peakResponseDb is max |H(f)|, so after attenuation no steady sine can leave the chain above unity.
  • Clipping is a time-domain event, and the tight bound on a filter's sample-peak gain is the L1 norm of its impulse response, which is strictly larger. Measured over these curves at 48 kHz: Rock after its −4.8 dB pre-amp still has +4.9 dB of worst-case peak gain, and Bass Reducer — pure cuts, so no pre-amp at all, by construction — has +5.7 dB. Even one band at +0.1 dB has +0.03 dB. A phase shift moves energy in time, and modern masters arrive at 0 dBFS with nowhere to put it.

So the honest predicate for "this curve cannot clip" is ‖h‖₁ ≤ 1, and that is false for every non-flat curve — which is exactly the condition this option already keys on. A flat curve compiles to no chain, so it gets no limiter either.

The limiter is not a tone control: below full scale it is sample-identical (see AudioFilters.limiter, which also documents the one thing it does cost — 5 ms of uncompensated look-ahead). Turn it off only if something later in your chain already limits, or if you are handing the output somewhere with real headroom.


preampDb?

readonly optional preampDb?: number;

Defined in: packages/player/src/equalizer-presets.ts:360

Extra gain in dB applied on top of the automatic headroom pre-amp.

The automatic part is neither optional nor configurable: the chain always attenuates by the preset's largest positive band gain, which is exactly what stops a boost from clipping. This is for taste on top of that. Defaults to 0.