mirror of https://github.com/mpv-player/mpv
audio: move replaygain control to top-level options
af_volume is deprecated, and so are its replaygain sub-options. To make it possible to use replaygain without deprecated options (and of course to make it available at all after af_volume is dropped), reintroduce them as top-level options. This also means that they are easily changeable at runtime by using them as properties. Change the "volume" property to use the new update mechanism as well. We don't actually bother sharing the implementation between new and deprecated mechanisms, as the deprecated one will simply be deleted. For the from_dB() functions, we mention anders' copyright, although I'm not sure if a mere formula is copyrightable. This will have to be determined later. This whole change is mostly untested. Our distributed human CI will take care of it.
This commit is contained in:
parent
010c7d4992
commit
f1c4d20e65
|
@ -22,6 +22,8 @@ Interface changes
|
|||
--- mpv 0.26.0 ---
|
||||
- remove remaining deprecated audio device options, like --alsa-device
|
||||
Some of them were removed in earlier releases.
|
||||
- introduce --replaygain... options, which replace the same functionality
|
||||
provided by the deprecated --af=volume:replaygain... mechanism.
|
||||
--- mpv 0.25.0 ---
|
||||
- remove opengl-cb dxva2 dummy hwdec interop
|
||||
(see git "vo_opengl: remove dxva2 dummy hwdec backend")
|
||||
|
|
|
@ -208,6 +208,9 @@ Available filters are:
|
|||
best to use the *Master* volume control of your sound card or the volume
|
||||
knob on your amplifier.
|
||||
|
||||
*WARNING*: This filter is deprecated. Use the top-level options like
|
||||
``--volume`` and ``--replaygain...`` instead.
|
||||
|
||||
*NOTE*: This filter is not reentrant and can therefore only be enabled
|
||||
once for every audio stream.
|
||||
|
||||
|
|
|
@ -1182,6 +1182,26 @@ Audio
|
|||
|
||||
Since mpv 0.18.1, this always controls the internal mixer (aka "softvol").
|
||||
|
||||
``--replaygain-track=<yes|no>``
|
||||
Adjust volume gain according to the track-gain replaygain value stored
|
||||
in the file metadata.
|
||||
|
||||
``--replaygain-album=<yes|no>``
|
||||
Like replaygain-track, but using the album-gain value instead.
|
||||
|
||||
``--replaygain-preamp=<db>``
|
||||
Pre-amplification gain in dB to apply to the selected replaygain gain
|
||||
(default: 0).
|
||||
|
||||
``--replaygain-clip=<yes|no>``
|
||||
Prevent clipping caused by replaygain by automatically lowering the
|
||||
gain (default). Use ``--replaygain-clip=no`` to disable this.
|
||||
|
||||
``--replaygain-fallback=<db>``
|
||||
Gain in dB to apply if the file has no replay gain tags. This option
|
||||
is always applied if the replaygain logic is somehow inactive. If this
|
||||
is applied, no other replaygain options are applied.
|
||||
|
||||
``--balance=<value>``
|
||||
How much left/right channels contribute to the audio. (The implementation
|
||||
of this feature is rather odd. It doesn't change the volumes of each
|
||||
|
|
|
@ -395,7 +395,8 @@ struct m_option {
|
|||
#define UPDATE_AUDIO (1 << 14) // --audio-channels etc.
|
||||
#define UPDATE_PRIORITY (1 << 15) // --priority (Windows-only)
|
||||
#define UPDATE_SCREENSAVER (1 << 16) // --stop-screensaver
|
||||
#define UPDATE_OPT_LAST (1 << 16)
|
||||
#define UPDATE_VOL (1 << 17) // softvol related options
|
||||
#define UPDATE_OPT_LAST (1 << 17)
|
||||
|
||||
// All bits between _FIRST and _LAST (inclusive)
|
||||
#define UPDATE_OPTS_MASK \
|
||||
|
|
|
@ -545,11 +545,16 @@ const m_option_t mp_opts[] = {
|
|||
"as if --softvol=yes is always set"),
|
||||
OPT_FLOATRANGE("volume-max", softvol_max, 0, 100, 1000),
|
||||
// values <0 for volume and mute are legacy and ignored
|
||||
OPT_FLOATRANGE("volume", softvol_volume, 0, -1, 1000),
|
||||
OPT_CHOICE("mute", softvol_mute, 0,
|
||||
OPT_FLOATRANGE("volume", softvol_volume, UPDATE_VOL, -1, 1000),
|
||||
OPT_CHOICE("mute", softvol_mute, UPDATE_VOL,
|
||||
({"no", 0},
|
||||
{"auto", 0},
|
||||
{"yes", 1})),
|
||||
OPT_FLAG("replaygain-track", rgain_track, UPDATE_VOL),
|
||||
OPT_FLAG("replaygain-album", rgain_album, UPDATE_VOL),
|
||||
OPT_FLOATRANGE("replaygain-preamp", rgain_preamp, UPDATE_VOL, -15, 15),
|
||||
OPT_FLAG("replaygain-clip", rgain_clip, UPDATE_VOL),
|
||||
OPT_FLOATRANGE("replaygain-fallback", rgain_fallback, UPDATE_VOL, -200, 60),
|
||||
OPT_CHOICE("gapless-audio", gapless_audio, 0,
|
||||
({"no", 0},
|
||||
{"yes", 1},
|
||||
|
|
|
@ -101,6 +101,11 @@ typedef struct MPOpts {
|
|||
int force_vo;
|
||||
int softvol;
|
||||
float softvol_volume;
|
||||
int rgain_track; // Enable/disable track based replaygain
|
||||
int rgain_album; // Enable/disable album based replaygain
|
||||
float rgain_preamp; // Set replaygain pre-amplification
|
||||
int rgain_clip; // Enable/disable clipping prevention
|
||||
float rgain_fallback;
|
||||
float balance;
|
||||
int softvol_mute;
|
||||
float softvol_max;
|
||||
|
|
|
@ -119,6 +119,54 @@ fail:
|
|||
mp_notify(mpctx, MP_EVENT_CHANGE_ALL, NULL);
|
||||
}
|
||||
|
||||
// Convert to gain value from dB. input <= -200dB will become 0 gain.
|
||||
// Copyright (C)2002 Anders Johansson
|
||||
static float from_dB(float in, float k, float mi, float ma)
|
||||
{
|
||||
if (in <= -200)
|
||||
return 0.0;
|
||||
return pow(10.0, MPCLAMP(in, mi, ma) / k);
|
||||
}
|
||||
|
||||
static float compute_replaygain(struct MPContext *mpctx)
|
||||
{
|
||||
struct MPOpts *opts = mpctx->opts;
|
||||
struct ao_chain *ao_c = mpctx->ao_chain;
|
||||
|
||||
float rgain = 1.0;
|
||||
|
||||
struct replaygain_data *rg = ao_c->af->replaygain_data;
|
||||
if ((opts->rgain_track || opts->rgain_album) && rg) {
|
||||
MP_VERBOSE(mpctx, "Replaygain: Track=%f/%f Album=%f/%f\n",
|
||||
rg->track_gain, rg->track_peak,
|
||||
rg->album_gain, rg->album_peak);
|
||||
|
||||
float gain, peak;
|
||||
if (opts->rgain_track) {
|
||||
gain = rg->track_gain;
|
||||
peak = rg->track_peak;
|
||||
} else {
|
||||
gain = rg->album_gain;
|
||||
peak = rg->album_peak;
|
||||
}
|
||||
|
||||
gain += opts->rgain_preamp;
|
||||
rgain = from_dB(gain, 20.0, -200.0, 60.0);
|
||||
|
||||
MP_VERBOSE(mpctx, "Applying replay-gain: %f\n", rgain);
|
||||
|
||||
if (!opts->rgain_clip) { // clipping prevention
|
||||
rgain = MPMIN(rgain, 1.0 / peak);
|
||||
MP_VERBOSE(mpctx, "...with clipping prevention: %f\n", rgain);
|
||||
}
|
||||
} else if (opts->rgain_fallback) {
|
||||
rgain = from_dB(opts->rgain_fallback, 20.0, -200.0, 60.0);
|
||||
MP_VERBOSE(mpctx, "Applying fallback gain: %f\n", rgain);
|
||||
}
|
||||
|
||||
return rgain;
|
||||
}
|
||||
|
||||
// Called when opts->softvol_volume or opts->softvol_mute were changed.
|
||||
void audio_update_volume(struct MPContext *mpctx)
|
||||
{
|
||||
|
@ -128,6 +176,7 @@ void audio_update_volume(struct MPContext *mpctx)
|
|||
return;
|
||||
|
||||
float gain = MPMAX(opts->softvol_volume / 100.0, 0);
|
||||
gain *= compute_replaygain(mpctx);
|
||||
if (opts->softvol_mute == 1)
|
||||
gain = 0.0;
|
||||
|
||||
|
|
|
@ -1820,10 +1820,7 @@ static int mp_property_volume(void *ctx, struct m_property *prop,
|
|||
return M_PROPERTY_OK;
|
||||
}
|
||||
|
||||
int r = mp_property_generic_option(mpctx, prop, action, arg);
|
||||
if (action == M_PROPERTY_SET)
|
||||
audio_update_volume(mpctx);
|
||||
return r;
|
||||
return mp_property_generic_option(mpctx, prop, action, arg);
|
||||
}
|
||||
|
||||
/// Mute (RW)
|
||||
|
@ -5798,6 +5795,9 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags)
|
|||
|
||||
if (flags & UPDATE_SCREENSAVER)
|
||||
update_screensaver_state(mpctx);
|
||||
|
||||
if (flags & UPDATE_VOL)
|
||||
audio_update_volume(mpctx);
|
||||
}
|
||||
|
||||
void mp_notify_property(struct MPContext *mpctx, const char *property)
|
||||
|
|
Loading…
Reference in New Issue