[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