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 pa_volume_t
pa_sw_volume_divide(pa_volume_t a
, pa_volume_t b
) {
108 double v
= pa_sw_volume_to_linear(b
);
113 return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a
) / v
);
116 #define USER_DECIBEL_RANGE 60
118 pa_volume_t
pa_sw_volume_from_dB(double dB
) {
119 if (isinf(dB
) < 0 || dB
<= -USER_DECIBEL_RANGE
)
120 return PA_VOLUME_MUTED
;
122 return (pa_volume_t
) lrint((dB
/USER_DECIBEL_RANGE
+1)*PA_VOLUME_NORM
);
125 double pa_sw_volume_to_dB(pa_volume_t v
) {
126 if (v
== PA_VOLUME_MUTED
)
127 return PA_DECIBEL_MININFTY
;
129 return ((double) v
/PA_VOLUME_NORM
-1)*USER_DECIBEL_RANGE
;
132 pa_volume_t
pa_sw_volume_from_linear(double v
) {
135 return PA_VOLUME_MUTED
;
137 if (v
> .999 && v
< 1.001)
138 return PA_VOLUME_NORM
;
140 return pa_sw_volume_from_dB(20*log10(v
));
143 double pa_sw_volume_to_linear(pa_volume_t v
) {
145 if (v
== PA_VOLUME_MUTED
)
148 return pow(10.0, pa_sw_volume_to_dB(v
)/20.0);
151 char *pa_cvolume_snprint(char *s
, size_t l
, const pa_cvolume
*c
) {
153 pa_bool_t first
= TRUE
;
162 if (!pa_cvolume_valid(c
)) {
163 pa_snprintf(s
, l
, _("(invalid)"));
169 for (channel
= 0; channel
< c
->channels
&& l
> 1; channel
++) {
170 l
-= pa_snprintf(e
, l
, "%s%u: %3u%%",
173 (c
->values
[channel
]*100)/PA_VOLUME_NORM
);
182 char *pa_volume_snprint(char *s
, size_t l
, pa_volume_t v
) {
188 if (v
== (pa_volume_t
) -1) {
189 pa_snprintf(s
, l
, _("(invalid)"));
193 pa_snprintf(s
, l
, "%3u%%", (v
*100)/PA_VOLUME_NORM
);
197 char *pa_sw_cvolume_snprint_dB(char *s
, size_t l
, const pa_cvolume
*c
) {
199 pa_bool_t first
= TRUE
;
208 if (!pa_cvolume_valid(c
)) {
209 pa_snprintf(s
, l
, _("(invalid)"));
215 for (channel
= 0; channel
< c
->channels
&& l
> 1; channel
++) {
216 double f
= pa_sw_volume_to_dB(c
->values
[channel
]);
218 l
-= pa_snprintf(e
, l
, "%s%u: %0.2f dB",
221 isinf(f
) < 0 || f
<= -USER_DECIBEL_RANGE
? -INFINITY
: f
);
230 char *pa_sw_volume_snprint_dB(char *s
, size_t l
, pa_volume_t v
) {
238 if (v
== (pa_volume_t
) -1) {
239 pa_snprintf(s
, l
, _("(invalid)"));
243 f
= pa_sw_volume_to_dB(v
);
244 pa_snprintf(s
, l
, "%0.2f dB",
245 isinf(f
) < 0 || f
<= -USER_DECIBEL_RANGE
? -INFINITY
: f
);
250 /** Return non-zero if the volume of all channels is equal to the specified value */
251 int pa_cvolume_channels_equal_to(const pa_cvolume
*a
, pa_volume_t v
) {
255 for (c
= 0; c
< a
->channels
; c
++)
256 if (a
->values
[c
] != v
)
262 pa_cvolume
*pa_sw_cvolume_multiply(pa_cvolume
*dest
, const pa_cvolume
*a
, const pa_cvolume
*b
) {
269 for (i
= 0; i
< a
->channels
&& i
< b
->channels
&& i
< PA_CHANNELS_MAX
; i
++)
270 dest
->values
[i
] = pa_sw_volume_multiply(a
->values
[i
], b
->values
[i
]);
272 dest
->channels
= (uint8_t) i
;
277 pa_cvolume
*pa_sw_cvolume_divide(pa_cvolume
*dest
, const pa_cvolume
*a
, const pa_cvolume
*b
) {
284 for (i
= 0; i
< a
->channels
&& i
< b
->channels
&& i
< PA_CHANNELS_MAX
; i
++)
285 dest
->values
[i
] = pa_sw_volume_divide(a
->values
[i
], b
->values
[i
]);
287 dest
->channels
= (uint8_t) i
;
292 int pa_cvolume_valid(const pa_cvolume
*v
) {
297 if (v
->channels
<= 0 || v
->channels
> PA_CHANNELS_MAX
)
300 for (c
= 0; c
< v
->channels
; c
++)
301 if (v
->values
[c
] == (pa_volume_t
) -1)
307 static pa_bool_t
on_left(pa_channel_position_t p
) {
310 p
== PA_CHANNEL_POSITION_FRONT_LEFT
||
311 p
== PA_CHANNEL_POSITION_REAR_LEFT
||
312 p
== PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
||
313 p
== PA_CHANNEL_POSITION_SIDE_LEFT
||
314 p
== PA_CHANNEL_POSITION_TOP_FRONT_LEFT
||
315 p
== PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
318 static pa_bool_t
on_right(pa_channel_position_t p
) {
321 p
== PA_CHANNEL_POSITION_FRONT_RIGHT
||
322 p
== PA_CHANNEL_POSITION_REAR_RIGHT
||
323 p
== PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
||
324 p
== PA_CHANNEL_POSITION_SIDE_RIGHT
||
325 p
== PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
||
326 p
== PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
329 static pa_bool_t
on_center(pa_channel_position_t p
) {
332 p
== PA_CHANNEL_POSITION_FRONT_CENTER
||
333 p
== PA_CHANNEL_POSITION_REAR_CENTER
||
334 p
== PA_CHANNEL_POSITION_TOP_CENTER
||
335 p
== PA_CHANNEL_POSITION_TOP_FRONT_CENTER
||
336 p
== PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
339 static pa_bool_t
on_lfe(pa_channel_position_t p
) {
341 p
== PA_CHANNEL_POSITION_LFE
;
344 pa_cvolume
*pa_cvolume_remap(pa_cvolume
*v
, const pa_channel_map
*from
, const pa_channel_map
*to
) {
351 pa_assert(v
->channels
== from
->channels
);
353 if (pa_channel_map_equal(from
, to
))
356 result
.channels
= to
->channels
;
358 for (b
= 0; b
< to
->channels
; b
++) {
362 for (a
= 0; a
< from
->channels
; a
++)
363 if (from
->map
[a
] == to
->map
[b
]) {
369 for (a
= 0; a
< from
->channels
; a
++)
370 if ((on_left(from
->map
[a
]) && on_left(to
->map
[b
])) ||
371 (on_right(from
->map
[a
]) && on_right(to
->map
[b
])) ||
372 (on_center(from
->map
[a
]) && on_center(to
->map
[b
])) ||
373 (on_lfe(from
->map
[a
]) && on_lfe(to
->map
[b
]))) {
381 k
= pa_cvolume_avg(v
);
385 result
.values
[b
] = k
;
392 int pa_cvolume_compatible(const pa_cvolume
*v
, const pa_sample_spec
*ss
) {
397 if (!pa_cvolume_valid(v
))
400 if (!pa_sample_spec_valid(ss
))
403 return v
->channels
== ss
->channels
;
406 static void get_avg_lr(const pa_channel_map
*map
, const pa_cvolume
*v
, pa_volume_t
*l
, pa_volume_t
*r
) {
408 pa_volume_t left
= 0, right
= 0;
409 unsigned n_left
= 0, n_right
= 0;
413 pa_assert(map
->channels
== v
->channels
);
417 for (c
= 0; c
< map
->channels
; c
++) {
418 if (on_left(map
->map
[c
])) {
419 left
+= v
->values
[c
];
421 } else if (on_right(map
->map
[c
])) {
422 right
+= v
->values
[c
];
435 *r
= right
/ n_right
;
438 float pa_cvolume_get_balance(const pa_cvolume
*v
, const pa_channel_map
*map
) {
439 pa_volume_t left
, right
;
443 pa_assert(map
->channels
== v
->channels
);
445 get_avg_lr(map
, v
, &left
, &right
);
460 return -1.0f
+ ((float) right
/ (float) left
);
462 return 1.0f
- ((float) left
/ (float) right
);
465 pa_cvolume
* pa_cvolume_set_balance(pa_cvolume
*v
, const pa_channel_map
*map
, float new_balance
) {
466 pa_volume_t left
, nleft
, right
, nright
, m
;
469 pa_assert(map
->channels
== v
->channels
);
472 pa_assert(new_balance
>= -1.0f
);
473 pa_assert(new_balance
<= 1.0f
);
475 get_avg_lr(map
, v
, &left
, &right
);
477 m
= PA_MAX(left
, right
);
479 if (new_balance
<= 0) {
480 nright
= (new_balance
+ 1.0f
) * m
;
483 nleft
= (1.0f
- new_balance
) * m
;
487 for (c
= 0; c
< map
->channels
; c
++) {
488 if (on_left(map
->map
[c
])) {
492 v
->values
[c
] = (pa_volume_t
) (((uint64_t) v
->values
[c
] * (uint64_t) nleft
) / (uint64_t) left
);
493 } else if (on_right(map
->map
[c
])) {
497 v
->values
[c
] = (pa_volume_t
) (((uint64_t) v
->values
[c
] * (uint64_t) nright
) / (uint64_t) right
);
504 pa_cvolume
* pa_cvolume_scale(pa_cvolume
*v
, pa_volume_t max
) {
510 for (c
= 0; c
< v
->channels
; c
++)
511 if (v
->values
[c
] > t
)
515 return pa_cvolume_set(v
, v
->channels
, max
);
517 for (c
= 0; c
< v
->channels
; c
++)
518 v
->values
[c
] = (pa_volume_t
) (((uint64_t) v
->values
[c
] * (uint64_t) max
) / (uint64_t) t
);