mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
sink, source: Add a mode to avoid resampling if possible
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. We still will do conversion if sample formats don't match, though. This means that if you want to play 96 kHz/24 bit audio without any modification the default format will need to 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.
This commit is contained in:
parent
5e1bb023a2
commit
cc021c7330
8 changed files with 30 additions and 4 deletions
|
|
@ -123,6 +123,15 @@ License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
|||
resampler to use.</p>
|
||||
</option>
|
||||
|
||||
<option>
|
||||
<p><opt>avoid-resampling=</opt> If set, try to configure the
|
||||
device to avoid resampling. This only works on devices which
|
||||
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>
|
||||
</option>
|
||||
|
||||
<option>
|
||||
<p><opt>enable-remixing=</opt> If disabled never upmix or
|
||||
downmix channels to different channel maps. Instead, do a simple
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,11 @@ 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 && (rate >= default_rate || rate >= alternate_rate)) {
|
||||
/* We just try to set the sink input's sample rate if it's not too low */
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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,11 @@ 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 && (rate >= default_rate || rate >= alternate_rate)) {
|
||||
/* We just try to set the source output's sample rate if it's not too low */
|
||||
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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue