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 labelled — EQUALIZER_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 = 1makes 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:
Rockafter its −4.8 dB pre-amp still has +4.9 dB of worst-case peak gain, andBass 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.