diff options
-rw-r--r-- | DOCS/interface-changes.rst | 2 | ||||
-rw-r--r-- | DOCS/man/af.rst | 3 | ||||
-rw-r--r-- | DOCS/man/options.rst | 20 | ||||
-rw-r--r-- | options/m_option.h | 3 | ||||
-rw-r--r-- | options/options.c | 9 | ||||
-rw-r--r-- | options/options.h | 5 | ||||
-rw-r--r-- | player/audio.c | 49 | ||||
-rw-r--r-- | player/command.c | 8 |
8 files changed, 92 insertions, 7 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst index 464435bcbe..aadbf159d0 100644 --- a/DOCS/interface-changes.rst +++ b/DOCS/interface-changes.rst @@ -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") diff --git a/DOCS/man/af.rst b/DOCS/man/af.rst index 9dff18ebbe..bc25a9f7b3 100644 --- a/DOCS/man/af.rst +++ b/DOCS/man/af.rst @@ -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. diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index 7d3070fda0..1f66b77225 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -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 diff --git a/options/m_option.h b/options/m_option.h index 064b7f83b1..d4a795a834 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -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 \ diff --git a/options/options.c b/options/options.c index 229f328af1..42c4828b56 100644 --- a/options/options.c +++ b/options/options.c @@ -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}, diff --git a/options/options.h b/options/options.h index 82f0c15aec..0d288be586 100644 --- a/options/options.h +++ b/options/options.h @@ -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; diff --git a/player/audio.c b/player/audio.c index b2e44c23dd..dd464614d9 100644 --- a/player/audio.c +++ b/player/audio.c @@ -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; diff --git a/player/command.c b/player/command.c index 73081e89f9..ad871e34b3 100644 --- a/player/command.c +++ b/player/command.c @@ -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) |