diff options
author | wm4 <wm4@nowhere> | 2017-04-26 21:45:50 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2017-04-26 21:45:55 +0200 |
commit | f1c4d20e6577f32018e20efc4ab9da7d4e1ab4ac (patch) | |
tree | b9c6c26faefce976496c527d524cd2e09a96b29f /player | |
parent | 010c7d499258c1064189b2d149ae6eca859d9ae1 (diff) | |
download | mpv-f1c4d20e6577f32018e20efc4ab9da7d4e1ab4ac.tar.bz2 mpv-f1c4d20e6577f32018e20efc4ab9da7d4e1ab4ac.tar.xz |
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.
Diffstat (limited to 'player')
-rw-r--r-- | player/audio.c | 49 | ||||
-rw-r--r-- | player/command.c | 8 |
2 files changed, 53 insertions, 4 deletions
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) |