[pulseaudio-commits] 3 commits - src/pulse src/pulsecore
Georg Chini
gchini at kemper.freedesktop.org
Sat Apr 29 08:44:59 UTC 2017
src/pulse/volume.c | 22 +++++++++++++++++-----
src/pulsecore/sink.c | 4 ++--
src/pulsecore/source.c | 4 ++--
3 files changed, 21 insertions(+), 9 deletions(-)
New commits:
commit 68203100ff1d5ac35ade6db4fc56e355274d6a0e
Author: Georg Chini <georg at chini.tk>
Date: Sat Apr 29 10:38:05 2017 +0200
volume: Fix overflow in percent calculation of pa_*volume_snprint*()
The percent calculation could overflow in the pa_*volume_snprint*() functions.
For large volumes, volume * 100 can exceed UINT32_MAX.
This patch adds appropriate type casts.
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 1488028b..ffd42ecb 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -313,7 +313,7 @@ char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
l -= pa_snprintf(e, l, "%s%u: %3u%%",
first ? "" : " ",
channel,
- (c->values[channel]*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM);
+ (unsigned)(((uint64_t)c->values[channel] * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
e = strchr(e, 0);
first = false;
@@ -333,7 +333,7 @@ char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
return s;
}
- pa_snprintf(s, l, "%3u%%", (v*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM);
+ pa_snprintf(s, l, "%3u%%", (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM));
return s;
}
@@ -446,7 +446,7 @@ char *pa_volume_snprint_verbose(char *s, size_t l, pa_volume_t v, int print_dB)
pa_snprintf(s, l, "%" PRIu32 " / %3u%%%s%s",
v,
- (v * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM,
+ (unsigned)(((uint64_t)v * 100 + (uint64_t)PA_VOLUME_NORM / 2) / (uint64_t)PA_VOLUME_NORM),
print_dB ? " / " : "",
print_dB ? pa_sw_volume_snprint_dB(dB, sizeof(dB), v) : "");
commit be1276d816171d9ce6c981581c22a297a61d62bc
Author: Georg Chini <georg at chini.tk>
Date: Sat Apr 29 10:12:01 2017 +0200
volume: Print a warning when volume is clipped in pa_sw_volume_multiply/divide()
When the volume exceeds PA_VOLUME_MAX in pa_sw_volume_multiply() or
pa_sw_volume_divide(), volume settings are insanely high and the
user should be notified about it.
This patch adds volume clamping to pa_sw_volume_divide() and prints
a warning when the volume is clipped in both functions.
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 1667b940..1488028b 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -199,16 +199,23 @@ pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, p
}
pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
+ uint64_t result;
pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
/* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
- return (pa_volume_t) PA_CLAMP_VOLUME((((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM));
+ result = ((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM;
+
+ if (result > (uint64_t)PA_VOLUME_MAX)
+ pa_log_warn("pa_sw_volume_multiply: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
+
+ return (pa_volume_t) PA_CLAMP_VOLUME(result);
}
pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
+ uint64_t result;
pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
@@ -216,7 +223,12 @@ pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
if (b <= PA_VOLUME_MUTED)
return 0;
- return (pa_volume_t) (((uint64_t) a * (uint64_t) PA_VOLUME_NORM + (uint64_t) b / 2ULL) / (uint64_t) b);
+ result = ((uint64_t) a * (uint64_t) PA_VOLUME_NORM + (uint64_t) b / 2ULL) / (uint64_t) b;
+
+ if (result > (uint64_t)PA_VOLUME_MAX)
+ pa_log_warn("pa_sw_volume_divide: Volume exceeds maximum allowed value and will be clipped. Please check your volume settings.");
+
+ return (pa_volume_t) PA_CLAMP_VOLUME(result);
}
/* Amplitude, not power */
commit d985276c8b4c005171ea10d412e854bb956a092b
Author: Georg Chini <georg at chini.tk>
Date: Sat Apr 29 10:07:01 2017 +0200
source/sink: Fix wrong calculation of thread_info.current_hw_volume
In pa_{source,sink}_new() and pa_{source,sink}_put() the current hardware
volume was miscalculated:
hw volume (dB) = real volume (dB) + soft volume (dB)
was used instead of
hw volume (dB) = real volume (dB) - soft volume (dB)
This lead to a crash in pa_alsa_path_set_volume() if high volumes were
set and the port was changed.
This patch fixes the calculation. Thanks to Tanu for pointing out
the correct solution.
Bug link: https://bugs.freedesktop.org/show_bug.cgi?id=65520
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 92670c13..dbbec535 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -342,7 +342,7 @@ pa_sink* pa_sink_new(
PA_LLIST_HEAD_INIT(pa_sink_volume_change, s->thread_info.volume_changes);
s->thread_info.volume_changes_tail = NULL;
- pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
+ pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
s->thread_info.port_latency_offset = s->port_latency_offset;
@@ -639,7 +639,7 @@ void pa_sink_put(pa_sink* s) {
s->thread_info.soft_volume = s->soft_volume;
s->thread_info.soft_muted = s->muted;
- pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
+ pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
pa_assert((s->flags & PA_SINK_HW_VOLUME_CTRL)
|| (s->base_volume == PA_VOLUME_NORM
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 6af1d675..08e7254d 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -327,7 +327,7 @@ pa_source* pa_source_new(
PA_LLIST_HEAD_INIT(pa_source_volume_change, s->thread_info.volume_changes);
s->thread_info.volume_changes_tail = NULL;
- pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
+ pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
s->thread_info.volume_change_safety_margin = core->deferred_volume_safety_margin_usec;
s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
s->thread_info.port_latency_offset = s->port_latency_offset;
@@ -590,7 +590,7 @@ void pa_source_put(pa_source *s) {
s->thread_info.soft_volume = s->soft_volume;
s->thread_info.soft_muted = s->muted;
- pa_sw_cvolume_multiply(&s->thread_info.current_hw_volume, &s->soft_volume, &s->real_volume);
+ pa_sw_cvolume_divide(&s->thread_info.current_hw_volume, &s->real_volume, &s->soft_volume);
pa_assert((s->flags & PA_SOURCE_HW_VOLUME_CTRL)
|| (s->base_volume == PA_VOLUME_NORM
More information about the pulseaudio-commits
mailing list