From ac966ded11e22754ffa43b390e599e4242e29b37 Mon Sep 17 00:00:00 2001
From: wm4 <wm4@nowhere>
Date: Wed, 20 Jan 2016 17:14:04 +0100
Subject: [PATCH] audio: change downmix behavior, add --audio-normalize-downmix

This is probably the 3rd time the user-visible behavior changes. This
time, switch back because not normalizing seems to be the more expected
behavior from users.
---
 DOCS/interface-changes.rst     |  3 +++
 DOCS/man/options.rst           | 10 ++++++++++
 audio/filter/af.c              |  1 +
 audio/filter/af.h              |  1 +
 audio/filter/af_lavrresample.c | 12 ++++++++----
 options/options.c              |  1 +
 options/options.h              |  1 +
 7 files changed, 25 insertions(+), 4 deletions(-)

diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index d460572e72..fdfd05f961 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -22,6 +22,9 @@ Interface changes
  --- mpv 0.16.0 ---
     - change --audio-channels default to stereo (use --audio-channels=auto to
       get the old default)
+    - add --audio-normalize-downmix
+    - change the default downmix behavior (--audio-normalize-downmix=yes to get
+      the old default)
  --- mpv 0.15.0 ---
     - change "yadif" video filter defaults
  --- mpv 0.14.0 ---
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index c76559c3c0..ddc4f82979 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -1129,6 +1129,16 @@ Audio
         channel layout, random things can happen, such as dropping the
         additional channels, or adding noise.
 
+``--audio-normalize-downmix=<yes|no>``
+    Enable/disable normalization if surround audio is downmixed to stereo
+    (default: no). If this is disabled, downmix can cause clipping. If it's
+    enabled, the output might be too silent. It depends on the source audio.
+
+    Technically, this changes the ``normalize`` suboption of the
+    ``lavrresample`` audio filter, which performs the downmixing.
+
+    If downmix happens outside of mpv for some reason, this has no effect.
+
 ``--audio-display=<no|attachment>``
     Setting this option to ``attachment`` (default) will display image
     attachments (e.g. album cover art) when playing audio files. It will
diff --git a/audio/filter/af.c b/audio/filter/af.c
index 7ff3b49ae8..475016d2ea 100644
--- a/audio/filter/af.c
+++ b/audio/filter/af.c
@@ -166,6 +166,7 @@ static struct af_instance *af_create(struct af_stream *s, char *name,
         .info = desc.p,
         .data = talloc_zero(af, struct mp_audio),
         .log = mp_log_new(af, s->log, name),
+        .opts = s->opts,
         .replaygain_data = s->replaygain_data,
         .out_pool = mp_audio_pool_create(af),
     };
diff --git a/audio/filter/af.h b/audio/filter/af.h
index ba64379661..0e73693ac9 100644
--- a/audio/filter/af.h
+++ b/audio/filter/af.h
@@ -53,6 +53,7 @@ struct af_info {
 struct af_instance {
     const struct af_info *info;
     struct mp_log *log;
+    struct MPOpts *opts;
     struct replaygain_data *replaygain_data;
     int (*control)(struct af_instance *af, int cmd, void *arg);
     void (*uninit)(struct af_instance *af);
diff --git a/audio/filter/af_lavrresample.c b/audio/filter/af_lavrresample.c
index 477443cefc..0c175a42e4 100644
--- a/audio/filter/af_lavrresample.c
+++ b/audio/filter/af_lavrresample.c
@@ -261,10 +261,13 @@ static int configure_lavrr(struct af_instance *af, struct mp_audio *in,
 
     av_opt_set_double(s->avrctx, "cutoff",          s->opts.cutoff, 0);
 
+    int normalize = s->opts.normalize;
+    if (normalize < 0)
+        normalize = af->opts->audio_normalize;
 #if HAVE_LIBSWRESAMPLE
-    av_opt_set_double(s->avrctx, "rematrix_maxval", s->opts.normalize ? 1 : 1000, 0);
+    av_opt_set_double(s->avrctx, "rematrix_maxval", normalize ? 1 : 1000, 0);
 #else
-    av_opt_set_int(s->avrctx, "normalize_mix_level", s->opts.normalize, 0);
+    av_opt_set_int(s->avrctx, "normalize_mix_level", !!normalize, 0);
 #endif
 
     if (mp_set_avopts(af->log, s->avrctx, s->avopts) < 0)
@@ -616,7 +619,7 @@ const struct af_info af_info_lavrresample = {
             .filter_size = 16,
             .cutoff      = 0.0,
             .phase_shift = 10,
-            .normalize   = 1,
+            .normalize   = -1,
         },
         .playback_speed = 1.0,
         .allow_detach = 1,
@@ -627,7 +630,8 @@ const struct af_info af_info_lavrresample = {
         OPT_FLAG("linear", opts.linear, 0),
         OPT_DOUBLE("cutoff", opts.cutoff, M_OPT_RANGE, .min = 0, .max = 1),
         OPT_FLAG("detach", allow_detach, 0),
-        OPT_FLAG("normalize", opts.normalize, 0),
+        OPT_CHOICE("normalize", opts.normalize, 0,
+                   ({"no", 0}, {"yes", 1}, {"auto", -1})),
         OPT_KEYVALUELIST("o", avopts, 0),
         {0}
     },
diff --git a/options/options.c b/options/options.c
index 7d376d8f22..49c44cb189 100644
--- a/options/options.c
+++ b/options/options.c
@@ -274,6 +274,7 @@ const m_option_t mp_opts[] = {
     OPT_INTRANGE("audio-samplerate", force_srate, 0, 1000, 16*48000),
     OPT_CHMAP("audio-channels", audio_output_channels, CONF_MIN, .min = 0),
     OPT_AUDIOFORMAT("audio-format", audio_output_format, 0),
+    OPT_FLAG("audio-normalize-downmix", audio_normalize, 0),
     OPT_DOUBLE("speed", playback_speed, M_OPT_RANGE | M_OPT_FIXED,
                .min = 0.01, .max = 100.0),
 
diff --git a/options/options.h b/options/options.h
index ea3ee00b30..6ce4be472a 100644
--- a/options/options.h
+++ b/options/options.h
@@ -225,6 +225,7 @@ typedef struct MPOpts {
 
     struct mp_chmap audio_output_channels;
     int audio_output_format;
+    int audio_normalize;
     int force_srate;
     int dtshd;
     double playback_speed;