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 <pulsecore/core-util.h>
30 #include <pulsecore/macro.h>
34 int pa_cvolume_equal(const pa_cvolume
*a
, const pa_cvolume
*b
) {
39 if (a
->channels
!= b
->channels
)
42 for (i
= 0; i
< a
->channels
; i
++)
43 if (a
->values
[i
] != b
->values
[i
])
49 pa_cvolume
* pa_cvolume_set(pa_cvolume
*a
, unsigned channels
, pa_volume_t v
) {
53 pa_assert(channels
> 0);
54 pa_assert(channels
<= PA_CHANNELS_MAX
);
56 a
->channels
= (uint8_t) channels
;
58 for (i
= 0; i
< a
->channels
; i
++)
64 pa_volume_t
pa_cvolume_avg(const pa_cvolume
*a
) {
69 for (i
= 0; i
< a
->channels
; i
++)
74 return (pa_volume_t
) sum
;
77 pa_volume_t
pa_cvolume_max(const pa_cvolume
*a
) {
82 for (i
= 0; i
< a
->channels
; i
++)
89 pa_volume_t
pa_sw_volume_multiply(pa_volume_t a
, pa_volume_t b
) {
90 return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a
)* pa_sw_volume_to_linear(b
));
93 #define USER_DECIBEL_RANGE 60
95 pa_volume_t
pa_sw_volume_from_dB(double dB
) {
96 if (isinf(dB
) < 0 || dB
<= -USER_DECIBEL_RANGE
)
97 return PA_VOLUME_MUTED
;
99 return (pa_volume_t
) ((dB
/USER_DECIBEL_RANGE
+1)*PA_VOLUME_NORM
);
102 double pa_sw_volume_to_dB(pa_volume_t v
) {
103 if (v
== PA_VOLUME_MUTED
)
104 return PA_DECIBEL_MININFTY
;
106 return ((double) v
/PA_VOLUME_NORM
-1)*USER_DECIBEL_RANGE
;
109 pa_volume_t
pa_sw_volume_from_linear(double v
) {
112 return PA_VOLUME_MUTED
;
114 if (v
> .999 && v
< 1.001)
115 return PA_VOLUME_NORM
;
117 return pa_sw_volume_from_dB(20*log10(v
));
120 double pa_sw_volume_to_linear(pa_volume_t v
) {
122 if (v
== PA_VOLUME_MUTED
)
125 return pow(10, pa_sw_volume_to_dB(v
)/20);
128 char *pa_cvolume_snprint(char *s
, size_t l
, const pa_cvolume
*c
) {
139 for (channel
= 0; channel
< c
->channels
&& l
> 1; channel
++) {
140 l
-= pa_snprintf(e
, l
, "%s%u: %3u%%",
143 (c
->values
[channel
]*100)/PA_VOLUME_NORM
);
152 /** Return non-zero if the volume of all channels is equal to the specified value */
153 int pa_cvolume_channels_equal_to(const pa_cvolume
*a
, pa_volume_t v
) {
157 for (c
= 0; c
< a
->channels
; c
++)
158 if (a
->values
[c
] != v
)
164 pa_cvolume
*pa_sw_cvolume_multiply(pa_cvolume
*dest
, const pa_cvolume
*a
, const pa_cvolume
*b
) {
171 for (i
= 0; i
< a
->channels
&& i
< b
->channels
&& i
< PA_CHANNELS_MAX
; i
++) {
173 dest
->values
[i
] = pa_sw_volume_multiply(
174 i
< a
->channels
? a
->values
[i
] : PA_VOLUME_NORM
,
175 i
< b
->channels
? b
->values
[i
] : PA_VOLUME_NORM
);
178 dest
->channels
= (uint8_t) i
;
183 int pa_cvolume_valid(const pa_cvolume
*v
) {
186 if (v
->channels
<= 0 || v
->channels
> PA_CHANNELS_MAX
)
192 static pa_bool_t
on_left(pa_channel_position_t p
) {
195 p
== PA_CHANNEL_POSITION_FRONT_LEFT
||
196 p
== PA_CHANNEL_POSITION_REAR_LEFT
||
197 p
== PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
||
198 p
== PA_CHANNEL_POSITION_SIDE_LEFT
||
199 p
== PA_CHANNEL_POSITION_TOP_FRONT_LEFT
||
200 p
== PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
203 static pa_bool_t
on_right(pa_channel_position_t p
) {
206 p
== PA_CHANNEL_POSITION_FRONT_RIGHT
||
207 p
== PA_CHANNEL_POSITION_REAR_RIGHT
||
208 p
== PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
||
209 p
== PA_CHANNEL_POSITION_SIDE_RIGHT
||
210 p
== PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
||
211 p
== PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
214 static pa_bool_t
on_center(pa_channel_position_t p
) {
217 p
== PA_CHANNEL_POSITION_FRONT_CENTER
||
218 p
== PA_CHANNEL_POSITION_REAR_CENTER
||
219 p
== PA_CHANNEL_POSITION_TOP_CENTER
||
220 p
== PA_CHANNEL_POSITION_TOP_FRONT_CENTER
||
221 p
== PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
224 static pa_bool_t
on_lfe(pa_channel_position_t p
) {
226 p
== PA_CHANNEL_POSITION_LFE
;
229 pa_cvolume
*pa_cvolume_remap(pa_cvolume
*v
, pa_channel_map
*from
, pa_channel_map
*to
) {
236 pa_assert(v
->channels
== from
->channels
);
238 if (pa_channel_map_equal(from
, to
))
241 result
.channels
= to
->channels
;
243 for (b
= 0; b
< to
->channels
; b
++) {
247 for (a
= 0; a
< from
->channels
; a
++)
248 if (from
->map
[a
] == to
->map
[b
]) {
254 for (a
= 0; a
< from
->channels
; a
++)
255 if ((on_left(from
->map
[a
]) && on_left(to
->map
[b
])) ||
256 (on_right(from
->map
[a
]) && on_right(to
->map
[b
])) ||
257 (on_center(from
->map
[a
]) && on_center(to
->map
[b
])) ||
258 (on_lfe(from
->map
[a
]) && on_lfe(to
->map
[b
]))) {
266 k
= pa_cvolume_avg(v
);
270 result
.values
[b
] = k
;