2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
29 #include <pulse/i18n.h>
30 #include <pulsecore/core-util.h>
31 #include <pulsecore/macro.h>
35 int pa_cvolume_equal(const pa_cvolume
*a
, const pa_cvolume
*b
) {
40 if (a
->channels
!= b
->channels
)
43 for (i
= 0; i
< a
->channels
; i
++)
44 if (a
->values
[i
] != b
->values
[i
])
50 pa_cvolume
* pa_cvolume_init(pa_cvolume
*a
) {
57 for (c
= 0; c
< PA_CHANNELS_MAX
; c
++)
58 a
->values
[c
] = (pa_volume_t
) -1;
63 pa_cvolume
* pa_cvolume_set(pa_cvolume
*a
, unsigned channels
, pa_volume_t v
) {
67 pa_assert(channels
> 0);
68 pa_assert(channels
<= PA_CHANNELS_MAX
);
70 a
->channels
= (uint8_t) channels
;
72 for (i
= 0; i
< a
->channels
; i
++)
78 pa_volume_t
pa_cvolume_avg(const pa_cvolume
*a
) {
83 for (i
= 0; i
< a
->channels
; i
++)
88 return (pa_volume_t
) sum
;
91 pa_volume_t
pa_cvolume_max(const pa_cvolume
*a
) {
96 for (i
= 0; i
< a
->channels
; i
++)
103 pa_volume_t
pa_sw_volume_multiply(pa_volume_t a
, pa_volume_t b
) {
104 return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a
) * pa_sw_volume_to_linear(b
));
107 #define USER_DECIBEL_RANGE 60
109 pa_volume_t
pa_sw_volume_from_dB(double dB
) {
110 if (isinf(dB
) < 0 || dB
<= -USER_DECIBEL_RANGE
)
111 return PA_VOLUME_MUTED
;
113 return (pa_volume_t
) lrint((dB
/USER_DECIBEL_RANGE
+1)*PA_VOLUME_NORM
);
116 double pa_sw_volume_to_dB(pa_volume_t v
) {
117 if (v
== PA_VOLUME_MUTED
)
118 return PA_DECIBEL_MININFTY
;
120 return ((double) v
/PA_VOLUME_NORM
-1)*USER_DECIBEL_RANGE
;
123 pa_volume_t
pa_sw_volume_from_linear(double v
) {
126 return PA_VOLUME_MUTED
;
128 if (v
> .999 && v
< 1.001)
129 return PA_VOLUME_NORM
;
131 return pa_sw_volume_from_dB(20*log10(v
));
134 double pa_sw_volume_to_linear(pa_volume_t v
) {
136 if (v
== PA_VOLUME_MUTED
)
139 return pow(10.0, pa_sw_volume_to_dB(v
)/20.0);
142 char *pa_cvolume_snprint(char *s
, size_t l
, const pa_cvolume
*c
) {
144 pa_bool_t first
= TRUE
;
153 if (!pa_cvolume_valid(c
)) {
154 pa_snprintf(s
, l
, _("(invalid)"));
160 for (channel
= 0; channel
< c
->channels
&& l
> 1; channel
++) {
161 l
-= pa_snprintf(e
, l
, "%s%u: %3u%%",
164 (c
->values
[channel
]*100)/PA_VOLUME_NORM
);
173 char *pa_sw_cvolume_snprint_dB(char *s
, size_t l
, const pa_cvolume
*c
) {
175 pa_bool_t first
= TRUE
;
184 if (!pa_cvolume_valid(c
)) {
185 pa_snprintf(s
, l
, _("(invalid)"));
191 for (channel
= 0; channel
< c
->channels
&& l
> 1; channel
++) {
192 l
-= pa_snprintf(e
, l
, "%s%u: %0.2f dB",
195 pa_sw_volume_to_dB(c
->values
[channel
]));
204 /** Return non-zero if the volume of all channels is equal to the specified value */
205 int pa_cvolume_channels_equal_to(const pa_cvolume
*a
, pa_volume_t v
) {
209 for (c
= 0; c
< a
->channels
; c
++)
210 if (a
->values
[c
] != v
)
216 pa_cvolume
*pa_sw_cvolume_multiply(pa_cvolume
*dest
, const pa_cvolume
*a
, const pa_cvolume
*b
) {
223 for (i
= 0; i
< a
->channels
&& i
< b
->channels
&& i
< PA_CHANNELS_MAX
; i
++) {
225 dest
->values
[i
] = pa_sw_volume_multiply(
226 i
< a
->channels
? a
->values
[i
] : PA_VOLUME_NORM
,
227 i
< b
->channels
? b
->values
[i
] : PA_VOLUME_NORM
);
230 dest
->channels
= (uint8_t) i
;
235 int pa_cvolume_valid(const pa_cvolume
*v
) {
240 if (v
->channels
<= 0 || v
->channels
> PA_CHANNELS_MAX
)
243 for (c
= 0; c
< v
->channels
; c
++)
244 if (v
->values
[c
] == (pa_volume_t
) -1)
250 static pa_bool_t
on_left(pa_channel_position_t p
) {
253 p
== PA_CHANNEL_POSITION_FRONT_LEFT
||
254 p
== PA_CHANNEL_POSITION_REAR_LEFT
||
255 p
== PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
||
256 p
== PA_CHANNEL_POSITION_SIDE_LEFT
||
257 p
== PA_CHANNEL_POSITION_TOP_FRONT_LEFT
||
258 p
== PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
261 static pa_bool_t
on_right(pa_channel_position_t p
) {
264 p
== PA_CHANNEL_POSITION_FRONT_RIGHT
||
265 p
== PA_CHANNEL_POSITION_REAR_RIGHT
||
266 p
== PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
||
267 p
== PA_CHANNEL_POSITION_SIDE_RIGHT
||
268 p
== PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
||
269 p
== PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
272 static pa_bool_t
on_center(pa_channel_position_t p
) {
275 p
== PA_CHANNEL_POSITION_FRONT_CENTER
||
276 p
== PA_CHANNEL_POSITION_REAR_CENTER
||
277 p
== PA_CHANNEL_POSITION_TOP_CENTER
||
278 p
== PA_CHANNEL_POSITION_TOP_FRONT_CENTER
||
279 p
== PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
282 static pa_bool_t
on_lfe(pa_channel_position_t p
) {
284 p
== PA_CHANNEL_POSITION_LFE
;
287 pa_cvolume
*pa_cvolume_remap(pa_cvolume
*v
, pa_channel_map
*from
, pa_channel_map
*to
) {
294 pa_assert(v
->channels
== from
->channels
);
296 if (pa_channel_map_equal(from
, to
))
299 result
.channels
= to
->channels
;
301 for (b
= 0; b
< to
->channels
; b
++) {
305 for (a
= 0; a
< from
->channels
; a
++)
306 if (from
->map
[a
] == to
->map
[b
]) {
312 for (a
= 0; a
< from
->channels
; a
++)
313 if ((on_left(from
->map
[a
]) && on_left(to
->map
[b
])) ||
314 (on_right(from
->map
[a
]) && on_right(to
->map
[b
])) ||
315 (on_center(from
->map
[a
]) && on_center(to
->map
[b
])) ||
316 (on_lfe(from
->map
[a
]) && on_lfe(to
->map
[b
]))) {
324 k
= pa_cvolume_avg(v
);
328 result
.values
[b
] = k
;
335 int pa_cvolume_compatible(const pa_cvolume
*v
, const pa_sample_spec
*ss
) {
340 if (!pa_cvolume_valid(v
))
343 if (!pa_sample_spec_valid(ss
))
346 return v
->channels
== ss
->channels
;