summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst2
-rw-r--r--DOCS/man/af.rst3
-rw-r--r--DOCS/man/options.rst20
-rw-r--r--options/m_option.h3
-rw-r--r--options/options.c9
-rw-r--r--options/options.h5
-rw-r--r--player/audio.c49
-rw-r--r--player/command.c8
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)