volume: Print a warning when volume is clipped in pa_sw_volume_multiply/divide()
authorGeorg Chini <georg@chini.tk>
Sat, 29 Apr 2017 08:12:01 +0000 (10:12 +0200)
committerGeorg Chini <georg@chini.tk>
Sat, 29 Apr 2017 08:12:01 +0000 (10:12 +0200)
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.

src/pulse/volume.c

index 1667b940c5083f112b2c4d77eec3a260c323290d..1488028ba27f34ba160193b9b2d247db3de7cacd 100644 (file)
@@ -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 */