[pulseaudio-discuss] [PATCH] sink, source: Add a mode to avoid resampling if possible

Peter Meerwald-Stadler pmeerw at pmeerw.net
Sat Jan 28 10:31:57 UTC 2017


> This adds an "avoid-resampling" option to daemon.conf that makes the
> daemon try to use the stream sample rate if possible (the device needs
> to support it, which currently only ALSA does), and there should not be
> any other stream connected).
> 
> This should enable some of the "audiophile" use-cases where users wish
> to play high sample rate audio files without resampling.

comments below, picking on wording
 
> We still will do conversion, though which means that the 96/24 case will
> require that the default format be set to be 24-bit as well, this will
> force all streams to be upconverted, which other than the wasted
> resources should be relatively harmless.
> ---
>  man/pulse-daemon.conf.5.xml.in |  9 +++++++++
>  src/daemon/daemon-conf.c       |  3 +++
>  src/daemon/daemon-conf.h       |  1 +
>  src/daemon/daemon.conf.in      |  1 +
>  src/daemon/main.c              |  1 +
>  src/pulsecore/core.h           |  1 +
>  src/pulsecore/sink.c           | 10 ++++++++--
>  src/pulsecore/source.c         | 10 ++++++++--
>  8 files changed, 32 insertions(+), 4 deletions(-)
> 
> NOTE: I didn't want to editorialise the commit message itself, but if you're
> excited about this feature, please do make sure you understand Monty's
> excellent post on the subject of high sample rate audio at:
> 
>   http://people.xiph.org/~xiphmont/demo/neil-young.html
> 
> diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
> index b81a549..cb09b97 100644
> --- a/man/pulse-daemon.conf.5.xml.in
> +++ b/man/pulse-daemon.conf.5.xml.in
> @@ -124,6 +124,15 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
>      </option>
>  
>      <option>
> +      <p><opt>avoid-resampling=</opt> If set, try to configure the
> +      device to avoid resampling. This only works if on devices that

only works on devices

> +      support reconfiguring their rate, and when no other streams are
> +      already playing or capturing audio. The device will also not be
> +      configured to a rate less than the default and alternate sample
> +      rates.</p>

rate

> +    </option>
> +
> +    <option>
>        <p><opt>enable-remixing=</opt> If disabled never upmix or
>        downmix channels to different channel maps. Instead, do a simple
>        name-based matching only. Defaults to <opt>yes.</opt></p>
> diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
> index 31e4b14..9883126 100644
> --- a/src/daemon/daemon-conf.c
> +++ b/src/daemon/daemon-conf.c
> @@ -81,6 +81,7 @@ static const pa_daemon_conf default_conf = {
>      .log_meta = false,
>      .log_time = false,
>      .resample_method = PA_RESAMPLER_AUTO,
> +    .avoid_resampling = false,
>      .disable_remixing = false,
>      .remixing_use_all_sink_channels = true,
>      .disable_lfe_remixing = true,
> @@ -553,6 +554,7 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
>          { "deferred-volume-extra-delay-usec",
>                                          pa_config_parse_int,      &c->deferred_volume_extra_delay_usec, NULL },
>          { "nice-level",                 parse_nice_level,         c, NULL },
> +        { "avoid-resampling",           pa_config_parse_bool,     &c->avoid_resampling, 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",
> @@ -750,6 +752,7 @@ char *pa_daemon_conf_dump(pa_daemon_conf *c) {
>      pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
>      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, "avoid-resampling = %s\n", pa_yes_no(!c->avoid_resampling));
>      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));
> diff --git a/src/daemon/daemon-conf.h b/src/daemon/daemon-conf.h
> index e61f67f..953ea33 100644
> --- a/src/daemon/daemon-conf.h
> +++ b/src/daemon/daemon-conf.h
> @@ -67,6 +67,7 @@ typedef struct pa_daemon_conf {
>          no_cpu_limit,
>          disable_shm,
>          disable_memfd,
> +        avoid_resampling,
>          disable_remixing,
>          remixing_use_all_sink_channels,
>          disable_lfe_remixing,
> diff --git a/src/daemon/daemon.conf.in b/src/daemon/daemon.conf.in
> index 2d74afa..a955523 100644
> --- a/src/daemon/daemon.conf.in
> +++ b/src/daemon/daemon.conf.in
> @@ -54,6 +54,7 @@ ifelse(@HAVE_DBUS@, 1, [dnl
>  ; log-backtrace = 0
>  
>  ; resample-method = speex-float-1
> +; avoid-resampling = false
>  ; enable-remixing = yes
>  ; remixing-use-all-sink-channels = yes
>  ; enable-lfe-remixing = no
> diff --git a/src/daemon/main.c b/src/daemon/main.c
> index 280252a..f35252d 100644
> --- a/src/daemon/main.c
> +++ b/src/daemon/main.c
> @@ -1036,6 +1036,7 @@ int main(int argc, char *argv[]) {
>      c->resample_method = conf->resample_method;
>      c->realtime_priority = conf->realtime_priority;
>      c->realtime_scheduling = conf->realtime_scheduling;
> +    c->avoid_resampling = conf->avoid_resampling;
>      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;
> diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
> index d2fe887..212f6f7 100644
> --- a/src/pulsecore/core.h
> +++ b/src/pulsecore/core.h
> @@ -199,6 +199,7 @@ struct pa_core {
>      bool disallow_exit:1;
>      bool running_as_daemon:1;
>      bool realtime_scheduling:1;
> +    bool avoid_resampling:1;
>      bool disable_remixing:1;
>      bool remixing_use_all_sink_channels:1;
>      bool disable_lfe_remixing:1;
> diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
> index aa21822..370ea9b 100644
> --- a/src/pulsecore/sink.c
> +++ b/src/pulsecore/sink.c
> @@ -1414,6 +1414,7 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
>      pa_sink_input *i;
>      bool default_rate_is_usable = false;
>      bool alternate_rate_is_usable = false;
> +    bool avoid_resampling = s->core->avoid_resampling;
>  
>      if (rate == s->sample_spec.rate)
>          return 0;
> @@ -1421,7 +1422,7 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
>      if (!s->update_rate)
>          return -1;
>  
> -    if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough)) {
> +    if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !avoid_resampling)) {
>          pa_log_debug("Default and alternate sample rates are the same, so there is no point in switching.");
>          return -1;
>      }
> @@ -1442,7 +1443,12 @@ int pa_sink_update_rate(pa_sink *s, uint32_t rate, bool passthrough) {
>      if (PA_UNLIKELY(!pa_sample_rate_valid(desired_rate)))
>          return -1;
>  
> -    if (!passthrough && default_rate != desired_rate && alternate_rate != desired_rate) {
> +    if (avoid_resampling) {
> +        /* We just try to set the sink input's sample rate if it's not too low */
> +        if (rate > default_rate || rate > alternate_rate)
> +            desired_rate = rate;
> +
> +    } else if (!passthrough && default_rate != desired_rate && alternate_rate != desired_rate) {
>          if (default_rate % 11025 == 0 && desired_rate % 11025 == 0)
>              default_rate_is_usable = true;
>          if (default_rate % 4000 == 0 && desired_rate % 4000 == 0)
> diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
> index 8ce7818..ba59929 100644
> --- a/src/pulsecore/source.c
> +++ b/src/pulsecore/source.c
> @@ -982,6 +982,7 @@ int pa_source_update_rate(pa_source *s, uint32_t rate, bool passthrough) {
>      uint32_t alternate_rate = s->alternate_sample_rate;
>      bool default_rate_is_usable = false;
>      bool alternate_rate_is_usable = false;
> +    bool avoid_resampling = s->core->avoid_resampling;
>  
>      if (rate == s->sample_spec.rate)
>          return 0;
> @@ -989,7 +990,7 @@ int pa_source_update_rate(pa_source *s, uint32_t rate, bool passthrough) {
>      if (!s->update_rate && !s->monitor_of)
>          return -1;
>  
> -    if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough)) {
> +    if (PA_UNLIKELY(default_rate == alternate_rate && !passthrough && !avoid_resampling)) {
>          pa_log_debug("Default and alternate sample rates are the same, so there is no point in switching.");
>          return -1;
>      }
> @@ -1010,7 +1011,12 @@ int pa_source_update_rate(pa_source *s, uint32_t rate, bool passthrough) {
>      if (PA_UNLIKELY(!pa_sample_rate_valid(desired_rate)))
>          return -1;
>  
> -    if (!passthrough && default_rate != desired_rate && alternate_rate != desired_rate) {
> +    if (avoid_resampling) {
> +        /* We just try to set the source output's sample rate if it's not too low */
> +        if (rate > default_rate || rate > alternate_rate)
> +            desired_rate = rate;
> +
> +    } else if (!passthrough && default_rate != desired_rate && alternate_rate != desired_rate) {
>          if (default_rate % 11025 == 0 && desired_rate % 11025 == 0)
>              default_rate_is_usable = true;
>          if (default_rate % 4000 == 0 && desired_rate % 4000 == 0)
> -- 
> 2.9.3
> 
> _______________________________________________
> pulseaudio-discuss mailing list
> pulseaudio-discuss at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/pulseaudio-discuss
> 

-- 

Peter Meerwald-Stadler
+43-664-2444418 (mobile)


More information about the pulseaudio-discuss mailing list