[pulseaudio-commits] Branch 'next' - 4 commits - man/pulse-daemon.conf.5.xml.in src/daemon src/pulsecore src/tests

Tanu Kaskinen tanuk at kemper.freedesktop.org
Sun Jan 8 20:57:52 UTC 2017


 man/pulse-daemon.conf.5.xml.in |    8 ++++
 src/daemon/daemon-conf.c       |    4 ++
 src/daemon/daemon-conf.h       |    1 
 src/daemon/daemon.conf.in      |    1 
 src/daemon/main.c              |    1 
 src/pulsecore/core.c           |    1 
 src/pulsecore/core.h           |    1 
 src/pulsecore/resampler.c      |   82 ++++++++++++++++++++++++++++++++++++-----
 src/pulsecore/resampler.h      |    3 +
 src/pulsecore/sink-input.c     |    2 +
 src/pulsecore/source-output.c  |    2 +
 src/tests/remix-test.c         |   39 ++++++++++++++++---
 12 files changed, 128 insertions(+), 17 deletions(-)

New commits:
commit f02a9a463f3b71cb593f876a5d5e7d909894fda0
Author: David Mandelberg <dseomn at google.com>
Date:   Wed Jan 4 11:55:49 2017 -0500

    daemon-conf: add remixing-use-all-sink-channels option
    
    This option controls the PA_RESAMPLER_NO_FILL_SINK flag added in a
    previous commit.
    
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=62588
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=94563

diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index ff5a293..883c4ea 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -130,6 +130,14 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
     </option>
 
     <option>
+      <p><opt>remixing-use-all-sink-channels=</opt> If enabled, use
+      all sink channels when remixing. Otherwise, remix to the minimal
+      set of sink channels needed to reproduce all of the source
+      channels. (This has no effect on LFE remixing.) Defaults to
+      <opt>yes</opt>.</p>
+    </option>
+
+    <option>
       <p><opt>enable-lfe-remixing=</opt> If disabled when upmixing or
       downmixing ignore LFE channels. When this option is disabled the
       output LFE channel will only get a signal when an input LFE
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index f0ed0b4..31e4b14 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -82,6 +82,7 @@ static const pa_daemon_conf default_conf = {
     .log_time = false,
     .resample_method = PA_RESAMPLER_AUTO,
     .disable_remixing = false,
+    .remixing_use_all_sink_channels = true,
     .disable_lfe_remixing = true,
     .lfe_crossover_freq = 0,
     .config_file = NULL,
@@ -554,6 +555,8 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
         { "nice-level",                 parse_nice_level,         c, NULL },
         { "disable-remixing",           pa_config_parse_bool,     &c->disable_remixing, NULL },
         { "enable-remixing",            pa_config_parse_not_bool, &c->disable_remixing, NULL },
+        { "remixing-use-all-sink-channels",
+                                        pa_config_parse_bool,     &c->remixing_use_all_sink_channels, NULL },
         { "disable-lfe-remixing",       pa_config_parse_bool,     &c->disable_lfe_remixing, NULL },
         { "enable-lfe-remixing",        pa_config_parse_not_bool, &c->disable_lfe_remixing, NULL },
         { "lfe-crossover-freq",         pa_config_parse_unsigned, &c->lfe_crossover_freq, NULL },
@@ -748,6 +751,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
     pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
     pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
     pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
+    pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
     pa_strbuf_printf(s, "enable-lfe-remixing = %s\n", pa_yes_no(!c->disable_lfe_remixing));
     pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
     pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
index 82b619f..e61f67f 100644
--- a/src/daemon/daemon-conf.h
+++ b/src/daemon/daemon-conf.h
@@ -68,6 +68,7 @@ typedef struct pa_daemon_conf {
         disable_shm,
         disable_memfd,
         disable_remixing,
+        remixing_use_all_sink_channels,
         disable_lfe_remixing,
         load_default_script_file,
         disallow_exit,
diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
index f3a1cc3..2d74afa 100644
--- a/src/daemon/daemon.conf.in
+++ b/src/daemon/daemon.conf.in
@@ -55,6 +55,7 @@ ifelse(@HAVE_DBUS@, 1, [dnl
 
 ; resample-method = speex-float-1
 ; enable-remixing = yes
+; remixing-use-all-sink-channels = yes
 ; enable-lfe-remixing = no
 ; lfe-crossover-freq = 0
 
diff --git a/src/daemon/main.c b/src/daemon/main.c
index dc5e5bc..280252a 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -1037,6 +1037,7 @@ int main(int argc, char *argv[]) {
     c->realtime_priority = conf->realtime_priority;
     c->realtime_scheduling = conf->realtime_scheduling;
     c->disable_remixing = conf->disable_remixing;
+    c->remixing_use_all_sink_channels = conf->remixing_use_all_sink_channels;
     c->disable_lfe_remixing = conf->disable_lfe_remixing;
     c->deferred_volume = conf->deferred_volume;
     c->running_as_daemon = conf->daemonize;
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 2a96dfa..afdb0a4 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -142,6 +142,7 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t
     c->realtime_scheduling = false;
     c->realtime_priority = 5;
     c->disable_remixing = false;
+    c->remixing_use_all_sink_channels = true;
     c->disable_lfe_remixing = true;
     c->lfe_crossover_freq = 0;
     c->deferred_volume = true;
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 802111b..d2fe887 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -200,6 +200,7 @@ struct pa_core {
     bool running_as_daemon:1;
     bool realtime_scheduling:1;
     bool disable_remixing:1;
+    bool remixing_use_all_sink_channels:1;
     bool disable_lfe_remixing:1;
     bool deferred_volume:1;
 
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 0dda204..d988310 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -456,6 +456,7 @@ int pa_sink_input_new(
                           ((data->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                           ((data->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
                           (core->disable_remixing || (data->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                          (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
                           (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
                 pa_log_warn("Unsupported resampling operation.");
                 return -PA_ERR_NOTSUPPORTED;
@@ -2259,6 +2260,7 @@ int pa_sink_input_update_rate(pa_sink_input *i) {
                                      ((i->flags & PA_SINK_INPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                                      ((i->flags & PA_SINK_INPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
                                      (i->core->disable_remixing || (i->flags & PA_SINK_INPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                                     (i->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
                                      (i->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0));
 
         if (!new_resampler) {
diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c
index 35ef1c5..351c399 100644
--- a/src/pulsecore/source-output.c
+++ b/src/pulsecore/source-output.c
@@ -401,6 +401,7 @@ int pa_source_output_new(
                         ((data->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                         ((data->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
                         (core->disable_remixing || (data->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                        (core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
                         (core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0)))) {
                 pa_log_warn("Unsupported resampling operation.");
                 return -PA_ERR_NOTSUPPORTED;
@@ -1714,6 +1715,7 @@ int pa_source_output_update_rate(pa_source_output *o) {
                                      ((o->flags & PA_SOURCE_OUTPUT_VARIABLE_RATE) ? PA_RESAMPLER_VARIABLE_RATE : 0) |
                                      ((o->flags & PA_SOURCE_OUTPUT_NO_REMAP) ? PA_RESAMPLER_NO_REMAP : 0) |
                                      (o->core->disable_remixing || (o->flags & PA_SOURCE_OUTPUT_NO_REMIX) ? PA_RESAMPLER_NO_REMIX : 0) |
+                                     (o->core->remixing_use_all_sink_channels ? 0 : PA_RESAMPLER_NO_FILL_SINK) |
                                      (o->core->disable_lfe_remixing ? PA_RESAMPLER_NO_LFE : 0));
 
         if (!new_resampler) {

commit 1c7d3e60ccd17bf9a8e82651f86a269fc2f23433
Author: David Mandelberg <dseomn at google.com>
Date:   Wed Jan 4 11:55:48 2017 -0500

    remix-test: test the remixer with PA_RESAMPLER_NO_FILL_SINK set

diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c
index 5b0c677..0dcc2f1 100644
--- a/src/tests/remix-test.c
+++ b/src/tests/remix-test.c
@@ -61,6 +61,8 @@ int main(int argc, char *argv[]) {
         RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMAP),
         RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMIX),
         RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE),
+        RESAMPLE_FLAGS(PA_RESAMPLER_NO_FILL_SINK),
+        RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE | PA_RESAMPLER_NO_FILL_SINK),
         { .str = NULL, .value = 0 },
     };
 

commit 32291eaca21a2a1f5df9bca69a5fbd83d7d7c624
Author: David Mandelberg <dseomn at google.com>
Date:   Wed Jan 4 11:55:47 2017 -0500

    resampler: Flag for remixing to all sink channels.
    
    Add a flag PA_RESAMPLER_NO_FILL_SINK, which controls whether remixing
    should attempt to use all sink channels, versus only the ones needed
    to reproduce the source audio.
    
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=62588
    BugLink: https://bugs.freedesktop.org/show_bug.cgi?id=94563
    
    Suggested-by: Alexander E. Patrakov <patrakov at gmail.com>

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index ea22cd2..063c4c5 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -796,6 +796,64 @@ static int front_rear_side(pa_channel_position_t p) {
     return ON_OTHER;
 }
 
+/* Fill a map of which output channels should get mono from input, not including
+ * LFE output channels. (The LFE output channels are mapped separately.)
+ */
+static void setup_oc_mono_map(const pa_resampler *r, float *oc_mono_map) {
+    unsigned oc;
+    unsigned n_oc;
+    bool found_oc_for_mono = false;
+
+    pa_assert(r);
+    pa_assert(oc_mono_map);
+
+    n_oc = r->o_ss.channels;
+
+    if (!(r->flags & PA_RESAMPLER_NO_FILL_SINK)) {
+        /* Mono goes to all non-LFE output channels and we're done. */
+        for (oc = 0; oc < n_oc; oc++)
+            oc_mono_map[oc] = on_lfe(r->o_cm.map[oc]) ? 0.0f : 1.0f;
+        return;
+    } else {
+        /* Initialize to all zero so we can select individual channels below. */
+        for (oc = 0; oc < n_oc; oc++)
+            oc_mono_map[oc] = 0.0f;
+    }
+
+    for (oc = 0; oc < n_oc; oc++) {
+        if (r->o_cm.map[oc] == PA_CHANNEL_POSITION_MONO) {
+            oc_mono_map[oc] = 1.0f;
+            found_oc_for_mono = true;
+        }
+    }
+    if (found_oc_for_mono)
+        return;
+
+    for (oc = 0; oc < n_oc; oc++) {
+        if (r->o_cm.map[oc] == PA_CHANNEL_POSITION_FRONT_CENTER) {
+            oc_mono_map[oc] = 1.0f;
+            found_oc_for_mono = true;
+        }
+    }
+    if (found_oc_for_mono)
+        return;
+
+    for (oc = 0; oc < n_oc; oc++) {
+        if (r->o_cm.map[oc] == PA_CHANNEL_POSITION_FRONT_LEFT || r->o_cm.map[oc] == PA_CHANNEL_POSITION_FRONT_RIGHT) {
+            oc_mono_map[oc] = 1.0f;
+            found_oc_for_mono = true;
+        }
+    }
+    if (found_oc_for_mono)
+        return;
+
+    /* Give up on finding a suitable map for mono, and just send it to all
+     * non-LFE output channels.
+     */
+    for (oc = 0; oc < n_oc; oc++)
+        oc_mono_map[oc] = on_lfe(r->o_cm.map[oc]) ? 0.0f : 1.0f;
+}
+
 static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed) {
     unsigned oc, ic;
     unsigned n_oc, n_ic;
@@ -858,14 +916,14 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
          * 1) Connect all channels with matching names.
          *
          * 2) Mono Handling:
-         *    S:Mono: Copy into all D:channels
+         *    S:Mono: See setup_oc_mono_map().
          *    D:Mono: Avg all S:channels
          *
-         * 3) Mix D:Left, D:Right:
+         * 3) Mix D:Left, D:Right (if PA_RESAMPLER_NO_FILL_SINK is clear):
          *    D:Left: If not connected, avg all S:Left
          *    D:Right: If not connected, avg all S:Right
          *
-         * 4) Mix D:Center
+         * 4) Mix D:Center (if PA_RESAMPLER_NO_FILL_SINK is clear):
          *    If not connected, avg all S:Center
          *    If still not connected, avg all S:Left, S:Right
          *
@@ -908,6 +966,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
             ic_unconnected_center = 0,
             ic_unconnected_lfe = 0;
         bool ic_unconnected_center_mixed_in = 0;
+        float oc_mono_map[PA_CHANNELS_MAX];
 
         for (ic = 0; ic < n_ic; ic++) {
             if (on_left(r->i_cm.map[ic]))
@@ -918,6 +977,8 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
                 ic_center++;
         }
 
+        setup_oc_mono_map(r, oc_mono_map);
+
         for (oc = 0; oc < n_oc; oc++) {
             bool oc_connected = false;
             pa_channel_position_t b = r->o_cm.map[oc];
@@ -925,14 +986,17 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
             for (ic = 0; ic < n_ic; ic++) {
                 pa_channel_position_t a = r->i_cm.map[ic];
 
-                if (a == b || a == PA_CHANNEL_POSITION_MONO) {
+                if (a == b) {
                     m->map_table_f[oc][ic] = 1.0f;
 
                     oc_connected = true;
                     ic_connected[ic] = true;
+                }
+                else if (a == PA_CHANNEL_POSITION_MONO && oc_mono_map[oc] > 0.0f) {
+                    m->map_table_f[oc][ic] = oc_mono_map[oc];
 
-                    if (a == PA_CHANNEL_POSITION_MONO && on_lfe(b) && !(r->flags & PA_RESAMPLER_NO_LFE))
-                        *lfe_remixed = true;
+                    oc_connected = true;
+                    ic_connected[ic] = true;
                 }
                 else if (b == PA_CHANNEL_POSITION_MONO) {
                     m->map_table_f[oc][ic] = 1.0f / (float) n_ic;
@@ -945,7 +1009,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
             if (!oc_connected) {
                 /* Try to find matching input ports for this output port */
 
-                if (on_left(b)) {
+                if (on_left(b) && !(r->flags & PA_RESAMPLER_NO_FILL_SINK)) {
 
                     /* We are not connected and on the left side, let's
                      * average all left side input channels. */
@@ -960,7 +1024,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
                     /* We ignore the case where there is no left input channel.
                      * Something is really wrong in this case anyway. */
 
-                } else if (on_right(b)) {
+                } else if (on_right(b) && !(r->flags & PA_RESAMPLER_NO_FILL_SINK)) {
 
                     /* We are not connected and on the right side, let's
                      * average all right side input channels. */
@@ -976,7 +1040,7 @@ static void setup_remap(const pa_resampler *r, pa_remap_t *m, bool *lfe_remixed)
                      * channel. Something is really wrong in this case anyway.
                      * */
 
-                } else if (on_center(b)) {
+                } else if (on_center(b) && !(r->flags & PA_RESAMPLER_NO_FILL_SINK)) {
 
                     if (ic_center > 0) {
 
diff --git a/src/pulsecore/resampler.h b/src/pulsecore/resampler.h
index 4469022..5d3171f 100644
--- a/src/pulsecore/resampler.h
+++ b/src/pulsecore/resampler.h
@@ -68,7 +68,8 @@ typedef enum pa_resample_flags {
     PA_RESAMPLER_VARIABLE_RATE = 0x0001U,
     PA_RESAMPLER_NO_REMAP      = 0x0002U,  /* implies NO_REMIX */
     PA_RESAMPLER_NO_REMIX      = 0x0004U,
-    PA_RESAMPLER_NO_LFE        = 0x0008U
+    PA_RESAMPLER_NO_LFE        = 0x0008U,
+    PA_RESAMPLER_NO_FILL_SINK  = 0x0010U,
 } pa_resample_flags_t;
 
 struct pa_resampler {

commit bc77676ca0766951581f50c0b9863dc07d562e5e
Author: David Mandelberg <dseomn at google.com>
Date:   Wed Jan 4 11:55:46 2017 -0500

    remix-test: test the remixer using different flags
    
    This will make it easier to see how the following commit affects the
    remixer.

diff --git a/src/tests/remix-test.c b/src/tests/remix-test.c
index 1e58418..5b0c677 100644
--- a/src/tests/remix-test.c
+++ b/src/tests/remix-test.c
@@ -27,6 +27,17 @@
 #include <pulsecore/macro.h>
 #include <pulsecore/memblock.h>
 
+struct resample_flags {
+    const char *str;
+    pa_resample_flags_t value;
+};
+
+/* Call like this to get an initializer for struct resample_flags:
+ *     RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE)
+ */
+#define RESAMPLE_FLAGS(flags) { .str = #flags, .value = (flags) }
+
+
 int main(int argc, char *argv[]) {
 
     static const pa_channel_map maps[] = {
@@ -45,7 +56,15 @@ int main(int argc, char *argv[]) {
         { 0, { 0 } }
     };
 
-    unsigned i, j;
+    static const struct resample_flags flag_sets[] = {
+        RESAMPLE_FLAGS(0),
+        RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMAP),
+        RESAMPLE_FLAGS(PA_RESAMPLER_NO_REMIX),
+        RESAMPLE_FLAGS(PA_RESAMPLER_NO_LFE),
+        { .str = NULL, .value = 0 },
+    };
+
+    unsigned i, j, k;
     pa_mempool *pool;
     unsigned crossover_freq = 120;
 
@@ -59,20 +78,24 @@ int main(int argc, char *argv[]) {
             pa_resampler *r;
             pa_sample_spec ss1, ss2;
 
-            pa_log_info("Converting from '%s' to '%s'.", pa_channel_map_snprint(a, sizeof(a), &maps[i]), pa_channel_map_snprint(b, sizeof(b), &maps[j]));
-
             ss1.channels = maps[i].channels;
             ss2.channels = maps[j].channels;
 
             ss1.rate = ss2.rate = 44100;
             ss1.format = ss2.format = PA_SAMPLE_S16NE;
 
-            r = pa_resampler_new(pool, &ss1, &maps[i], &ss2, &maps[j], crossover_freq, PA_RESAMPLER_AUTO, 0);
+            for (k = 0; flag_sets[k].str; k++) {
+                pa_log_info("Converting from '%s' to '%s' with flags %s.", pa_channel_map_snprint(a, sizeof(a), &maps[i]),
+                            pa_channel_map_snprint(b, sizeof(b), &maps[j]), flag_sets[k].str);
+
+                r = pa_resampler_new(pool, &ss1, &maps[i], &ss2, &maps[j], crossover_freq, PA_RESAMPLER_AUTO,
+                                     flag_sets[k].value);
 
-            /* We don't really care for the resampler. We just want to
-             * see the remixing debug output. */
+                /* We don't really care for the resampler. We just want to
+                 * see the remixing debug output. */
 
-            pa_resampler_free(r);
+                pa_resampler_free(r);
+            }
         }
 
     pa_mempool_unref(pool);



More information about the pulseaudio-commits mailing list