summaryrefslogtreecommitdiff
path: root/debian/patches/0013-volume-change-pa_volume_t-mapping-to-cubic.patch
blob: de8360983e19d94b4648cf1fba42f12c5220dbac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From b79dab7f52d880968bf48cf7b1b8bf94b867d17e Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
Date: Fri, 22 May 2009 01:30:54 +0200
Subject: [PATCH] volume: change pa_volume_t mapping to cubic

---
 src/pulse/volume.c |   42 ++++++++++++++++++++++++++++++------------
 src/pulse/volume.h |    6 +++---
 2 files changed, 33 insertions(+), 15 deletions(-)

diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 6848771..0f80f72 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -120,20 +120,28 @@ pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
     return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) / v);
 }
 
-#define USER_DECIBEL_RANGE 90
+/* Amplitude, not power */
+static double linear_to_dB(double v) {
+    return 20.0 * log10(v);
+}
+
+static double dB_to_linear(double v) {
+    return pow(10.0, v / 20.0);
+}
 
 pa_volume_t pa_sw_volume_from_dB(double dB) {
-    if (isinf(dB) < 0 || dB <= -USER_DECIBEL_RANGE)
+    if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
         return PA_VOLUME_MUTED;
 
-    return (pa_volume_t) lrint(ceil((dB/USER_DECIBEL_RANGE+1.0)*PA_VOLUME_NORM));
+    return pa_sw_volume_from_linear(dB_to_linear(dB));
 }
 
 double pa_sw_volume_to_dB(pa_volume_t v) {
-    if (v == PA_VOLUME_MUTED)
+
+    if (v <= PA_VOLUME_MUTED)
         return PA_DECIBEL_MININFTY;
 
-    return ((double) v/PA_VOLUME_NORM-1)*USER_DECIBEL_RANGE;
+    return linear_to_dB(pa_sw_volume_to_linear(v));
 }
 
 pa_volume_t pa_sw_volume_from_linear(double v) {
@@ -141,18 +149,28 @@ pa_volume_t pa_sw_volume_from_linear(double v) {
     if (v <= 0.0)
         return PA_VOLUME_MUTED;
 
-    if (v > .999 && v < 1.001)
-        return PA_VOLUME_NORM;
+    /*
+     * We use a cubic mapping here, as suggested and discussed here:
+     *
+     * http://www.robotplanet.dk/audio/audio_gui_design/
+     * http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-May/thread.html#23151
+     */
 
-    return pa_sw_volume_from_dB(20.0*log10(v));
+    return (pa_volume_t) (cbrt(v) * PA_VOLUME_NORM);
 }
 
 double pa_sw_volume_to_linear(pa_volume_t v) {
+    double f;
 
-    if (v == PA_VOLUME_MUTED)
+    if (v <= PA_VOLUME_MUTED)
         return 0.0;
 
-    return pow(10.0, pa_sw_volume_to_dB(v)/20.0);
+    if (v == PA_VOLUME_NORM)
+        return 1.0;
+
+    f = ((double) v / PA_VOLUME_NORM);
+
+    return f*f*f;
 }
 
 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
@@ -225,7 +243,7 @@ char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
         l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
                          first ? "" : " ",
                          channel,
-                         isinf(f) < 0 || f <= -USER_DECIBEL_RANGE ? -INFINITY : f);
+                         isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
 
         e = strchr(e, 0);
         first = FALSE;
@@ -249,7 +267,7 @@ char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
 
     f = pa_sw_volume_to_dB(v);
     pa_snprintf(s, l, "%0.2f dB",
-                isinf(f) < 0 || f <= -USER_DECIBEL_RANGE ?  -INFINITY : f);
+                isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ?  -INFINITY : f);
 
     return s;
 }
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 5b7e121..b7c1876 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -212,10 +212,10 @@ pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) PA_GCC_CONST;
  * *dest. This is only valid for software volumes! \since 0.9.13 */
 pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b);
 
-/** Convert a decibel value to a volume. This is only valid for software volumes! */
+/** Convert a decibel value to a volume (amplitude, not power). This is only valid for software volumes! */
 pa_volume_t pa_sw_volume_from_dB(double f) PA_GCC_CONST;
 
-/** Convert a volume to a decibel value. This is only valid for software volumes! */
+/** Convert a volume to a decibel value (amplitude, not power). This is only valid for software volumes! */
 double pa_sw_volume_to_dB(pa_volume_t v) PA_GCC_CONST;
 
 /** Convert a linear factor to a volume. This is only valid for software volumes! */
@@ -227,7 +227,7 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 #ifdef INFINITY
 #define PA_DECIBEL_MININFTY ((double) -INFINITY)
 #else
-/** This value is used as minus infinity when using pa_volume_{to,from}_dB(). */
+/** This floor value is used as minus infinity when using pa_volume_{to,from}_dB(). */
 #define PA_DECIBEL_MININFTY ((double) -200.0)
 #endif
 
-- 
1.5.6.3