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
|