pulse: Add verbose volume printing functions
[platform/upstream/pulseaudio.git] / src / pulse / volume.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5
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.1 of the License,
9   or (at your option) any later version.
10
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.
15
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
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <math.h>
29
30 #include <pulsecore/core-util.h>
31 #include <pulsecore/i18n.h>
32 #include <pulsecore/macro.h>
33 #include <pulsecore/sample-util.h>
34
35 #include "volume.h"
36
37 int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
38     int i;
39     pa_assert(a);
40     pa_assert(b);
41
42     pa_return_val_if_fail(pa_cvolume_valid(a), 0);
43
44     if (PA_UNLIKELY(a == b))
45         return 1;
46
47     pa_return_val_if_fail(pa_cvolume_valid(b), 0);
48
49     if (a->channels != b->channels)
50         return 0;
51
52     for (i = 0; i < a->channels; i++)
53         if (a->values[i] != b->values[i])
54             return 0;
55
56     return 1;
57 }
58
59 pa_cvolume* pa_cvolume_init(pa_cvolume *a) {
60     unsigned c;
61
62     pa_assert(a);
63
64     a->channels = 0;
65
66     for (c = 0; c < PA_CHANNELS_MAX; c++)
67         a->values[c] = PA_VOLUME_INVALID;
68
69     return a;
70 }
71
72 pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
73     int i;
74
75     pa_assert(a);
76     pa_assert(channels > 0);
77     pa_assert(channels <= PA_CHANNELS_MAX);
78
79     a->channels = (uint8_t) channels;
80
81     for (i = 0; i < a->channels; i++)
82         /* Clamp in case there is stale data that exceeds the current
83          * PA_VOLUME_MAX */
84         a->values[i] = PA_CLAMP_VOLUME(v);
85
86     return a;
87 }
88
89 pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
90     uint64_t sum = 0;
91     unsigned c;
92
93     pa_assert(a);
94     pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
95
96     for (c = 0; c < a->channels; c++)
97         sum += a->values[c];
98
99     sum /= a->channels;
100
101     return (pa_volume_t) sum;
102 }
103
104 pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
105     uint64_t sum = 0;
106     unsigned c, n;
107
108     pa_assert(a);
109
110     if (!cm)
111         return pa_cvolume_avg(a);
112
113     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
114
115     for (c = n = 0; c < a->channels; c++) {
116
117         if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
118             continue;
119
120         sum += a->values[c];
121         n ++;
122     }
123
124     if (n > 0)
125         sum /= n;
126
127     return (pa_volume_t) sum;
128 }
129
130 pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
131     pa_volume_t m = PA_VOLUME_MUTED;
132     unsigned c;
133
134     pa_assert(a);
135     pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
136
137     for (c = 0; c < a->channels; c++)
138         if (a->values[c] > m)
139             m = a->values[c];
140
141     return m;
142 }
143
144 pa_volume_t pa_cvolume_min(const pa_cvolume *a) {
145     pa_volume_t m = PA_VOLUME_MAX;
146     unsigned c;
147
148     pa_assert(a);
149     pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
150
151     for (c = 0; c < a->channels; c++)
152         if (a->values[c] < m)
153             m = a->values[c];
154
155     return m;
156 }
157
158 pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
159     pa_volume_t m = PA_VOLUME_MUTED;
160     unsigned c;
161
162     pa_assert(a);
163
164     if (!cm)
165         return pa_cvolume_max(a);
166
167     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
168
169     for (c = 0; c < a->channels; c++) {
170
171         if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
172             continue;
173
174         if (a->values[c] > m)
175             m = a->values[c];
176     }
177
178     return m;
179 }
180
181 pa_volume_t pa_cvolume_min_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
182     pa_volume_t m = PA_VOLUME_MAX;
183     unsigned c;
184
185     pa_assert(a);
186
187     if (!cm)
188         return pa_cvolume_min(a);
189
190     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
191
192     for (c = 0; c < a->channels; c++) {
193
194         if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
195             continue;
196
197         if (a->values[c] < m)
198             m = a->values[c];
199     }
200
201     return m;
202 }
203
204 pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
205
206     pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
207     pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
208
209     /* cbrt((a/PA_VOLUME_NORM)^3*(b/PA_VOLUME_NORM)^3)*PA_VOLUME_NORM = a*b/PA_VOLUME_NORM */
210
211     return (pa_volume_t) PA_CLAMP_VOLUME((((uint64_t) a * (uint64_t) b + (uint64_t) PA_VOLUME_NORM / 2ULL) / (uint64_t) PA_VOLUME_NORM));
212 }
213
214 pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
215
216     pa_return_val_if_fail(PA_VOLUME_IS_VALID(a), PA_VOLUME_INVALID);
217     pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), PA_VOLUME_INVALID);
218
219     if (b <= PA_VOLUME_MUTED)
220         return 0;
221
222     return (pa_volume_t) (((uint64_t) a * (uint64_t) PA_VOLUME_NORM + (uint64_t) b / 2ULL) / (uint64_t) b);
223 }
224
225 /* Amplitude, not power */
226 static double linear_to_dB(double v) {
227     return 20.0 * log10(v);
228 }
229
230 static double dB_to_linear(double v) {
231     return pow(10.0, v / 20.0);
232 }
233
234 pa_volume_t pa_sw_volume_from_dB(double dB) {
235     if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
236         return PA_VOLUME_MUTED;
237
238     return pa_sw_volume_from_linear(dB_to_linear(dB));
239 }
240
241 double pa_sw_volume_to_dB(pa_volume_t v) {
242
243     pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), PA_DECIBEL_MININFTY);
244
245     if (v <= PA_VOLUME_MUTED)
246         return PA_DECIBEL_MININFTY;
247
248     return linear_to_dB(pa_sw_volume_to_linear(v));
249 }
250
251 pa_volume_t pa_sw_volume_from_linear(double v) {
252
253     if (v <= 0.0)
254         return PA_VOLUME_MUTED;
255
256     /*
257      * We use a cubic mapping here, as suggested and discussed here:
258      *
259      * http://www.robotplanet.dk/audio/audio_gui_design/
260      * http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-May/thread.html#23151
261      *
262      * We make sure that the conversion to linear and back yields the
263      * same volume value! That's why we need the lround() below!
264      */
265
266     return (pa_volume_t) PA_CLAMP_VOLUME((uint64_t) lround(cbrt(v) * PA_VOLUME_NORM));
267 }
268
269 double pa_sw_volume_to_linear(pa_volume_t v) {
270     double f;
271
272     pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0.0);
273
274     if (v <= PA_VOLUME_MUTED)
275         return 0.0;
276
277     if (v == PA_VOLUME_NORM)
278         return 1.0;
279
280     f = ((double) v / PA_VOLUME_NORM);
281
282     return f*f*f;
283 }
284
285 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
286     unsigned channel;
287     bool first = true;
288     char *e;
289
290     pa_assert(s);
291     pa_assert(l > 0);
292     pa_assert(c);
293
294     pa_init_i18n();
295
296     if (!pa_cvolume_valid(c)) {
297         pa_snprintf(s, l, _("(invalid)"));
298         return s;
299     }
300
301     *(e = s) = 0;
302
303     for (channel = 0; channel < c->channels && l > 1; channel++) {
304         l -= pa_snprintf(e, l, "%s%u: %3u%%",
305                       first ? "" : " ",
306                       channel,
307                       (c->values[channel]*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM);
308
309         e = strchr(e, 0);
310         first = false;
311     }
312
313     return s;
314 }
315
316 char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
317     pa_assert(s);
318     pa_assert(l > 0);
319
320     pa_init_i18n();
321
322     if (!PA_VOLUME_IS_VALID(v)) {
323         pa_snprintf(s, l, _("(invalid)"));
324         return s;
325     }
326
327     pa_snprintf(s, l, "%3u%%", (v*100+PA_VOLUME_NORM/2)/PA_VOLUME_NORM);
328     return s;
329 }
330
331 char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
332     unsigned channel;
333     bool first = true;
334     char *e;
335
336     pa_assert(s);
337     pa_assert(l > 0);
338     pa_assert(c);
339
340     pa_init_i18n();
341
342     if (!pa_cvolume_valid(c)) {
343         pa_snprintf(s, l, _("(invalid)"));
344         return s;
345     }
346
347     *(e = s) = 0;
348
349     for (channel = 0; channel < c->channels && l > 1; channel++) {
350         double f = pa_sw_volume_to_dB(c->values[channel]);
351
352         l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
353                          first ? "" : " ",
354                          channel,
355                          isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
356
357         e = strchr(e, 0);
358         first = false;
359     }
360
361     return s;
362 }
363
364 char *pa_cvolume_snprint_verbose(char *s, size_t l, const pa_cvolume *c, const pa_channel_map *map, int print_dB) {
365     char *current = s;
366     bool first = true;
367
368     pa_assert(s);
369     pa_assert(l > 0);
370     pa_assert(c);
371
372     pa_init_i18n();
373
374     if (!pa_cvolume_valid(c)) {
375         pa_snprintf(s, l, _("(invalid)"));
376         return s;
377     }
378
379     pa_assert(!map || (map->channels == c->channels));
380     pa_assert(!map || pa_channel_map_valid(map));
381
382     current[0] = 0;
383
384     for (unsigned channel = 0; channel < c->channels && l > 1; channel++) {
385         char channel_position[32];
386         size_t bytes_printed;
387         char buf[PA_VOLUME_SNPRINT_VERBOSE_MAX];
388
389         if (map)
390             pa_snprintf(channel_position, sizeof(channel_position), "%s", pa_channel_position_to_string(map->map[channel]));
391         else
392             pa_snprintf(channel_position, sizeof(channel_position), "%u", channel);
393
394         bytes_printed = pa_snprintf(current, l, "%s%s: %s",
395                                     first ? "" : ",   ",
396                                     channel_position,
397                                     pa_volume_snprint_verbose(buf, sizeof(buf), c->values[channel], print_dB));
398         l -= bytes_printed;
399         current += bytes_printed;
400         first = false;
401     }
402
403     return s;
404 }
405
406 char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
407     double f;
408
409     pa_assert(s);
410     pa_assert(l > 0);
411
412     pa_init_i18n();
413
414     if (!PA_VOLUME_IS_VALID(v)) {
415         pa_snprintf(s, l, _("(invalid)"));
416         return s;
417     }
418
419     f = pa_sw_volume_to_dB(v);
420     pa_snprintf(s, l, "%0.2f dB", isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
421
422     return s;
423 }
424
425 char *pa_volume_snprint_verbose(char *s, size_t l, pa_volume_t v, int print_dB) {
426     char dB[PA_SW_VOLUME_SNPRINT_DB_MAX];
427
428     pa_assert(s);
429     pa_assert(l > 0);
430
431     pa_init_i18n();
432
433     if (!PA_VOLUME_IS_VALID(v)) {
434         pa_snprintf(s, l, _("(invalid)"));
435         return s;
436     }
437
438     pa_snprintf(s, l, "%" PRIu32 " / %3u%%%s%s",
439                 v,
440                 (v * 100 + PA_VOLUME_NORM / 2) / PA_VOLUME_NORM,
441                 print_dB ? " / " : "",
442                 print_dB ? pa_sw_volume_snprint_dB(dB, sizeof(dB), v) : "");
443
444     return s;
445 }
446
447 int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
448     unsigned c;
449     pa_assert(a);
450
451     pa_return_val_if_fail(pa_cvolume_valid(a), 0);
452     pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), 0);
453
454     for (c = 0; c < a->channels; c++)
455         if (a->values[c] != v)
456             return 0;
457
458     return 1;
459 }
460
461 pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
462     unsigned i;
463
464     pa_assert(dest);
465     pa_assert(a);
466     pa_assert(b);
467
468     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
469     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
470
471     for (i = 0; i < a->channels && i < b->channels; i++)
472         dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
473
474     dest->channels = (uint8_t) i;
475
476     return dest;
477 }
478
479 pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
480     unsigned i;
481
482     pa_assert(dest);
483     pa_assert(a);
484
485     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
486     pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
487
488     for (i = 0; i < a->channels; i++)
489         dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
490
491     dest->channels = (uint8_t) i;
492
493     return dest;
494 }
495
496 pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
497     unsigned i;
498
499     pa_assert(dest);
500     pa_assert(a);
501     pa_assert(b);
502
503     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
504     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
505
506     for (i = 0; i < a->channels && i < b->channels; i++)
507         dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
508
509     dest->channels = (uint8_t) i;
510
511     return dest;
512 }
513
514 pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
515     unsigned i;
516
517     pa_assert(dest);
518     pa_assert(a);
519
520     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
521     pa_return_val_if_fail(PA_VOLUME_IS_VALID(b), NULL);
522
523     for (i = 0; i < a->channels; i++)
524         dest->values[i] = pa_sw_volume_divide(a->values[i], b);
525
526     dest->channels = (uint8_t) i;
527
528     return dest;
529 }
530
531 int pa_cvolume_valid(const pa_cvolume *v) {
532     unsigned c;
533
534     pa_assert(v);
535
536     if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
537         return 0;
538
539     for (c = 0; c < v->channels; c++)
540         if (!PA_VOLUME_IS_VALID(v->values[c]))
541             return 0;
542
543     return 1;
544 }
545
546 static bool on_left(pa_channel_position_t p) {
547     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LEFT);
548 }
549
550 static bool on_right(pa_channel_position_t p) {
551     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_RIGHT);
552 }
553
554 static bool on_center(pa_channel_position_t p) {
555     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_CENTER);
556 }
557
558 static bool on_lfe(pa_channel_position_t p) {
559     return p == PA_CHANNEL_POSITION_LFE;
560 }
561
562 static bool on_front(pa_channel_position_t p) {
563     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_FRONT);
564 }
565
566 static bool on_rear(pa_channel_position_t p) {
567     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_REAR);
568 }
569
570 pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
571     int a, b;
572     pa_cvolume result;
573
574     pa_assert(v);
575     pa_assert(from);
576     pa_assert(to);
577
578     pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
579     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
580
581     if (pa_channel_map_equal(from, to))
582         return v;
583
584     result.channels = to->channels;
585
586     for (b = 0; b < to->channels; b++) {
587         pa_volume_t k = 0;
588         int n = 0;
589
590         for (a = 0; a < from->channels; a++)
591             if (from->map[a] == to->map[b]) {
592                 k += v->values[a];
593                 n ++;
594             }
595
596         if (n <= 0) {
597             for (a = 0; a < from->channels; a++)
598                 if ((on_left(from->map[a]) && on_left(to->map[b])) ||
599                     (on_right(from->map[a]) && on_right(to->map[b])) ||
600                     (on_center(from->map[a]) && on_center(to->map[b])) ||
601                     (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
602
603                     k += v->values[a];
604                     n ++;
605                 }
606         }
607
608         if (n <= 0)
609             k = pa_cvolume_avg(v);
610         else
611             k /= n;
612
613         result.values[b] = k;
614     }
615
616     *v = result;
617     return v;
618 }
619
620 int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
621
622     pa_assert(v);
623     pa_assert(ss);
624
625     pa_return_val_if_fail(pa_cvolume_valid(v), 0);
626     pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
627
628     return v->channels == ss->channels;
629 }
630
631 int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) {
632     pa_assert(v);
633     pa_assert(cm);
634
635     pa_return_val_if_fail(pa_cvolume_valid(v), 0);
636     pa_return_val_if_fail(pa_channel_map_valid(cm), 0);
637
638     return v->channels == cm->channels;
639 }
640
641 static void get_avg_lr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *l, pa_volume_t *r) {
642     int c;
643     pa_volume_t left = 0, right = 0;
644     unsigned n_left = 0, n_right = 0;
645
646     pa_assert(v);
647     pa_assert(map);
648     pa_assert(map->channels == v->channels);
649     pa_assert(l);
650     pa_assert(r);
651
652     for (c = 0; c < map->channels; c++) {
653         if (on_left(map->map[c])) {
654             left += v->values[c];
655             n_left++;
656         } else if (on_right(map->map[c])) {
657             right += v->values[c];
658             n_right++;
659         }
660     }
661
662     if (n_left <= 0)
663         *l = PA_VOLUME_NORM;
664     else
665         *l = left / n_left;
666
667     if (n_right <= 0)
668         *r = PA_VOLUME_NORM;
669     else
670         *r = right / n_right;
671 }
672
673 float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
674     pa_volume_t left, right;
675
676     pa_assert(v);
677     pa_assert(map);
678
679     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
680
681     if (!pa_channel_map_can_balance(map))
682         return 0.0f;
683
684     get_avg_lr(map, v, &left, &right);
685
686     if (left == right)
687         return 0.0f;
688
689     /*   1.0,  0.0  =>  -1.0
690          0.0,  1.0  =>   1.0
691          0.0,  0.0  =>   0.0
692          0.5,  0.5  =>   0.0
693          1.0,  0.5  =>  -0.5
694          1.0,  0.25 => -0.75
695          0.75, 0.25 => -0.66
696          0.5,  0.25 => -0.5   */
697
698     if (left > right)
699         return -1.0f + ((float) right / (float) left);
700     else
701         return 1.0f - ((float) left / (float) right);
702 }
703
704 pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
705     pa_volume_t left, nleft, right, nright, m;
706     unsigned c;
707
708     pa_assert(map);
709     pa_assert(v);
710
711     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
712     pa_return_val_if_fail(new_balance >= -1.0f, NULL);
713     pa_return_val_if_fail(new_balance <= 1.0f, NULL);
714
715     if (!pa_channel_map_can_balance(map))
716         return v;
717
718     get_avg_lr(map, v, &left, &right);
719
720     m = PA_MAX(left, right);
721
722     if (new_balance <= 0) {
723         nright = (new_balance + 1.0f) * m;
724         nleft = m;
725     } else {
726         nleft = (1.0f - new_balance) * m;
727         nright = m;
728     }
729
730     for (c = 0; c < map->channels; c++) {
731         if (on_left(map->map[c])) {
732             if (left == 0)
733                 v->values[c] = nleft;
734             else
735                 v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nleft) / (uint64_t) left);
736         } else if (on_right(map->map[c])) {
737             if (right == 0)
738                 v->values[c] = nright;
739             else
740                 v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nright) / (uint64_t) right);
741         }
742     }
743
744     return v;
745 }
746
747 pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
748     unsigned c;
749     pa_volume_t t = 0;
750
751     pa_assert(v);
752
753     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
754     pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
755
756     t = pa_cvolume_max(v);
757
758     if (t <= PA_VOLUME_MUTED)
759         return pa_cvolume_set(v, v->channels, max);
760
761     for (c = 0; c < v->channels; c++)
762         v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
763
764     return v;
765 }
766
767 pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask) {
768     unsigned c;
769     pa_volume_t t = 0;
770
771     pa_assert(v);
772
773     pa_return_val_if_fail(PA_VOLUME_IS_VALID(max), NULL);
774
775     if (!cm)
776         return pa_cvolume_scale(v, max);
777
778     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, cm), NULL);
779
780     t = pa_cvolume_max_mask(v, cm, mask);
781
782     if (t <= PA_VOLUME_MUTED)
783         return pa_cvolume_set(v, v->channels, max);
784
785     for (c = 0; c < v->channels; c++)
786         v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) max) / (uint64_t) t);
787
788     return v;
789 }
790
791 static void get_avg_fr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *f, pa_volume_t *r) {
792     int c;
793     pa_volume_t front = 0, rear = 0;
794     unsigned n_front = 0, n_rear = 0;
795
796     pa_assert(v);
797     pa_assert(map);
798     pa_assert(map->channels == v->channels);
799     pa_assert(f);
800     pa_assert(r);
801
802     for (c = 0; c < map->channels; c++) {
803         if (on_front(map->map[c])) {
804             front += v->values[c];
805             n_front++;
806         } else if (on_rear(map->map[c])) {
807             rear += v->values[c];
808             n_rear++;
809         }
810     }
811
812     if (n_front <= 0)
813         *f = PA_VOLUME_NORM;
814     else
815         *f = front / n_front;
816
817     if (n_rear <= 0)
818         *r = PA_VOLUME_NORM;
819     else
820         *r = rear / n_rear;
821 }
822
823 float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
824     pa_volume_t front, rear;
825
826     pa_assert(v);
827     pa_assert(map);
828
829     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
830
831     if (!pa_channel_map_can_fade(map))
832         return 0.0f;
833
834     get_avg_fr(map, v, &front, &rear);
835
836     if (front == rear)
837         return 0.0f;
838
839     if (rear > front)
840         return -1.0f + ((float) front / (float) rear);
841     else
842         return 1.0f - ((float) rear / (float) front);
843 }
844
845 pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) {
846     pa_volume_t front, nfront, rear, nrear, m;
847     unsigned c;
848
849     pa_assert(map);
850     pa_assert(v);
851
852     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
853     pa_return_val_if_fail(new_fade >= -1.0f, NULL);
854     pa_return_val_if_fail(new_fade <= 1.0f, NULL);
855
856     if (!pa_channel_map_can_fade(map))
857         return v;
858
859     get_avg_fr(map, v, &front, &rear);
860
861     m = PA_MAX(front, rear);
862
863     if (new_fade <= 0) {
864         nfront = (new_fade + 1.0f) * m;
865         nrear = m;
866     } else {
867         nrear = (1.0f - new_fade) * m;
868         nfront = m;
869     }
870
871     for (c = 0; c < map->channels; c++) {
872         if (on_front(map->map[c])) {
873             if (front == 0)
874                 v->values[c] = nfront;
875             else
876                 v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nfront) / (uint64_t) front);
877         } else if (on_rear(map->map[c])) {
878             if (rear == 0)
879                 v->values[c] = nrear;
880             else
881                 v->values[c] = (pa_volume_t) PA_CLAMP_VOLUME(((uint64_t) v->values[c] * (uint64_t) nrear) / (uint64_t) rear);
882         }
883     }
884
885     return v;
886 }
887
888 pa_cvolume* pa_cvolume_set_position(
889         pa_cvolume *cv,
890         const pa_channel_map *map,
891         pa_channel_position_t t,
892         pa_volume_t v) {
893
894     unsigned c;
895     bool good = false;
896
897     pa_assert(cv);
898     pa_assert(map);
899
900     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
901     pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
902     pa_return_val_if_fail(PA_VOLUME_IS_VALID(v), NULL);
903
904     for (c = 0; c < map->channels; c++)
905         if (map->map[c] == t) {
906             cv->values[c] = v;
907             good = true;
908         }
909
910     return good ? cv : NULL;
911 }
912
913 pa_volume_t pa_cvolume_get_position(
914         pa_cvolume *cv,
915         const pa_channel_map *map,
916         pa_channel_position_t t) {
917
918     unsigned c;
919     pa_volume_t v = PA_VOLUME_MUTED;
920
921     pa_assert(cv);
922     pa_assert(map);
923
924     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
925     pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
926
927     for (c = 0; c < map->channels; c++)
928         if (map->map[c] == t)
929             if (cv->values[c] > v)
930                 v = cv->values[c];
931
932     return v;
933 }
934
935 pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
936     unsigned i;
937
938     pa_assert(dest);
939     pa_assert(a);
940     pa_assert(b);
941
942     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
943     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
944
945     for (i = 0; i < a->channels && i < b->channels; i++)
946         dest->values[i] = PA_MAX(a->values[i], b->values[i]);
947
948     dest->channels = (uint8_t) i;
949
950     return dest;
951 }
952
953 pa_cvolume* pa_cvolume_inc_clamp(pa_cvolume *v, pa_volume_t inc, pa_volume_t limit) {
954     pa_volume_t m;
955
956     pa_assert(v);
957
958     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
959     pa_return_val_if_fail(PA_VOLUME_IS_VALID(inc), NULL);
960
961     m = pa_cvolume_max(v);
962
963     if (m >= limit - inc)
964         m = limit;
965     else
966         m += inc;
967
968     return pa_cvolume_scale(v, m);
969 }
970
971 pa_cvolume* pa_cvolume_inc(pa_cvolume *v, pa_volume_t inc) {
972     return pa_cvolume_inc_clamp(v, inc, PA_VOLUME_MAX);
973 }
974
975 pa_cvolume* pa_cvolume_dec(pa_cvolume *v, pa_volume_t dec) {
976     pa_volume_t m;
977
978     pa_assert(v);
979
980     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
981     pa_return_val_if_fail(PA_VOLUME_IS_VALID(dec), NULL);
982
983     m = pa_cvolume_max(v);
984
985     if (m <= PA_VOLUME_MUTED + dec)
986         m = PA_VOLUME_MUTED;
987     else
988         m -= dec;
989
990     return pa_cvolume_scale(v, m);
991 }