libpulse: some minor optimizations when checking equality
[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
29 #include <pulse/i18n.h>
30
31 #include <pulsecore/core-util.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_t) -1;
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         a->values[i] = v;
83
84     return a;
85 }
86
87 pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
88     uint64_t sum = 0;
89     unsigned c;
90
91     pa_assert(a);
92     pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
93
94     for (c = 0; c < a->channels; c++)
95         sum += a->values[c];
96
97     sum /= a->channels;
98
99     return (pa_volume_t) sum;
100 }
101
102 pa_volume_t pa_cvolume_avg_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
103     uint64_t sum = 0;
104     unsigned c, n;
105
106     pa_assert(a);
107
108     if (!cm)
109         return pa_cvolume_avg(a);
110
111     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
112
113     for (c = n = 0; c < a->channels; c++) {
114
115         if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
116             continue;
117
118         sum += a->values[c];
119         n ++;
120     }
121
122     if (n > 0)
123         sum /= n;
124
125     return (pa_volume_t) sum;
126 }
127
128 pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
129     pa_volume_t m = 0;
130     unsigned c;
131
132     pa_assert(a);
133     pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
134
135     for (c = 0; c < a->channels; c++)
136         if (a->values[c] > m)
137             m = a->values[c];
138
139     return m;
140 }
141
142 pa_volume_t pa_cvolume_max_mask(const pa_cvolume *a, const pa_channel_map *cm, pa_channel_position_mask_t mask) {
143     pa_volume_t m = 0;
144     unsigned c, n;
145
146     pa_assert(a);
147
148     if (!cm)
149         return pa_cvolume_max(a);
150
151     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(a, cm), PA_VOLUME_MUTED);
152
153     for (c = n = 0; c < a->channels; c++) {
154
155         if (!(PA_CHANNEL_POSITION_MASK(cm->map[c]) & mask))
156             continue;
157
158         if (a->values[c] > m)
159             m = a->values[c];
160     }
161
162     return m;
163 }
164
165 pa_volume_t pa_sw_volume_multiply(pa_volume_t a, pa_volume_t b) {
166     return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) * pa_sw_volume_to_linear(b));
167 }
168
169 pa_volume_t pa_sw_volume_divide(pa_volume_t a, pa_volume_t b) {
170     double v = pa_sw_volume_to_linear(b);
171
172     if (v <= 0)
173         return 0;
174
175     return pa_sw_volume_from_linear(pa_sw_volume_to_linear(a) / v);
176 }
177
178 /* Amplitude, not power */
179 static double linear_to_dB(double v) {
180     return 20.0 * log10(v);
181 }
182
183 static double dB_to_linear(double v) {
184     return pow(10.0, v / 20.0);
185 }
186
187 pa_volume_t pa_sw_volume_from_dB(double dB) {
188     if (isinf(dB) < 0 || dB <= PA_DECIBEL_MININFTY)
189         return PA_VOLUME_MUTED;
190
191     return pa_sw_volume_from_linear(dB_to_linear(dB));
192 }
193
194 double pa_sw_volume_to_dB(pa_volume_t v) {
195
196     if (v <= PA_VOLUME_MUTED)
197         return PA_DECIBEL_MININFTY;
198
199     return linear_to_dB(pa_sw_volume_to_linear(v));
200 }
201
202 pa_volume_t pa_sw_volume_from_linear(double v) {
203
204     if (v <= 0.0)
205         return PA_VOLUME_MUTED;
206
207     /*
208      * We use a cubic mapping here, as suggested and discussed here:
209      *
210      * http://www.robotplanet.dk/audio/audio_gui_design/
211      * http://lists.linuxaudio.org/pipermail/linux-audio-dev/2009-May/thread.html#23151
212      *
213      * We make sure that the conversion to linear and back yields the
214      * same volume value! That's why we need the lround() below!
215      */
216
217     return (pa_volume_t) lround(cbrt(v) * PA_VOLUME_NORM);
218 }
219
220 double pa_sw_volume_to_linear(pa_volume_t v) {
221     double f;
222
223     if (v <= PA_VOLUME_MUTED)
224         return 0.0;
225
226     if (v == PA_VOLUME_NORM)
227         return 1.0;
228
229     f = ((double) v / PA_VOLUME_NORM);
230
231     return f*f*f;
232 }
233
234 char *pa_cvolume_snprint(char *s, size_t l, const pa_cvolume *c) {
235     unsigned channel;
236     pa_bool_t first = TRUE;
237     char *e;
238
239     pa_assert(s);
240     pa_assert(l > 0);
241     pa_assert(c);
242
243     pa_init_i18n();
244
245     if (!pa_cvolume_valid(c)) {
246         pa_snprintf(s, l, _("(invalid)"));
247         return s;
248     }
249
250     *(e = s) = 0;
251
252     for (channel = 0; channel < c->channels && l > 1; channel++) {
253         l -= pa_snprintf(e, l, "%s%u: %3u%%",
254                       first ? "" : " ",
255                       channel,
256                       (c->values[channel]*100)/PA_VOLUME_NORM);
257
258         e = strchr(e, 0);
259         first = FALSE;
260     }
261
262     return s;
263 }
264
265 char *pa_volume_snprint(char *s, size_t l, pa_volume_t v) {
266     pa_assert(s);
267     pa_assert(l > 0);
268
269     pa_init_i18n();
270
271     if (v == (pa_volume_t) -1) {
272         pa_snprintf(s, l, _("(invalid)"));
273         return s;
274     }
275
276     pa_snprintf(s, l, "%3u%%", (v*100)/PA_VOLUME_NORM);
277     return s;
278 }
279
280 char *pa_sw_cvolume_snprint_dB(char *s, size_t l, const pa_cvolume *c) {
281     unsigned channel;
282     pa_bool_t first = TRUE;
283     char *e;
284
285     pa_assert(s);
286     pa_assert(l > 0);
287     pa_assert(c);
288
289     pa_init_i18n();
290
291     if (!pa_cvolume_valid(c)) {
292         pa_snprintf(s, l, _("(invalid)"));
293         return s;
294     }
295
296     *(e = s) = 0;
297
298     for (channel = 0; channel < c->channels && l > 1; channel++) {
299         double f = pa_sw_volume_to_dB(c->values[channel]);
300
301         l -= pa_snprintf(e, l, "%s%u: %0.2f dB",
302                          first ? "" : " ",
303                          channel,
304                          isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ? -INFINITY : f);
305
306         e = strchr(e, 0);
307         first = FALSE;
308     }
309
310     return s;
311 }
312
313 char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
314     double f;
315
316     pa_assert(s);
317     pa_assert(l > 0);
318
319     pa_init_i18n();
320
321     if (v == (pa_volume_t) -1) {
322         pa_snprintf(s, l, _("(invalid)"));
323         return s;
324     }
325
326     f = pa_sw_volume_to_dB(v);
327     pa_snprintf(s, l, "%0.2f dB",
328                 isinf(f) < 0 || f <= PA_DECIBEL_MININFTY ?  -INFINITY : f);
329
330     return s;
331 }
332
333 int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
334     unsigned c;
335     pa_assert(a);
336
337     pa_return_val_if_fail(pa_cvolume_valid(a), 0);
338
339     for (c = 0; c < a->channels; c++)
340         if (a->values[c] != v)
341             return 0;
342
343     return 1;
344 }
345
346 pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
347     unsigned i;
348
349     pa_assert(dest);
350     pa_assert(a);
351     pa_assert(b);
352
353     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
354     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
355
356     for (i = 0; i < a->channels && i < b->channels; i++)
357         dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
358
359     dest->channels = (uint8_t) i;
360
361     return dest;
362 }
363
364 pa_cvolume *pa_sw_cvolume_multiply_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
365     unsigned i;
366
367     pa_assert(dest);
368     pa_assert(a);
369
370     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
371
372     for (i = 0; i < a->channels; i++)
373         dest->values[i] = pa_sw_volume_multiply(a->values[i], b);
374
375     dest->channels = (uint8_t) i;
376
377     return dest;
378 }
379
380 pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
381     unsigned i;
382
383     pa_assert(dest);
384     pa_assert(a);
385     pa_assert(b);
386
387     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
388     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
389
390     for (i = 0; i < a->channels && i < b->channels; i++)
391         dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
392
393     dest->channels = (uint8_t) i;
394
395     return dest;
396 }
397
398 pa_cvolume *pa_sw_cvolume_divide_scalar(pa_cvolume *dest, const pa_cvolume *a, pa_volume_t b) {
399     unsigned i;
400
401     pa_assert(dest);
402     pa_assert(a);
403
404     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
405
406     for (i = 0; i < a->channels; i++)
407         dest->values[i] = pa_sw_volume_divide(a->values[i], b);
408
409     dest->channels = (uint8_t) i;
410
411     return dest;
412 }
413
414 int pa_cvolume_valid(const pa_cvolume *v) {
415     unsigned c;
416
417     pa_assert(v);
418
419     if (v->channels <= 0 || v->channels > PA_CHANNELS_MAX)
420         return 0;
421
422     for (c = 0; c < v->channels; c++)
423         if (v->values[c] == (pa_volume_t) -1)
424             return 0;
425
426     return 1;
427 }
428
429 static pa_bool_t on_left(pa_channel_position_t p) {
430     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_LEFT);
431 }
432
433 static pa_bool_t on_right(pa_channel_position_t p) {
434     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_RIGHT);
435 }
436
437 static pa_bool_t on_center(pa_channel_position_t p) {
438     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_CENTER);
439 }
440
441 static pa_bool_t on_lfe(pa_channel_position_t p) {
442     return p == PA_CHANNEL_POSITION_LFE;
443 }
444
445 static pa_bool_t on_front(pa_channel_position_t p) {
446     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_FRONT);
447 }
448
449 static pa_bool_t on_rear(pa_channel_position_t p) {
450     return !!(PA_CHANNEL_POSITION_MASK(p) & PA_CHANNEL_POSITION_MASK_REAR);
451 }
452
453 pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to) {
454     int a, b;
455     pa_cvolume result;
456
457     pa_assert(v);
458     pa_assert(from);
459     pa_assert(to);
460
461     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
462     pa_return_val_if_fail(pa_channel_map_valid(from), NULL);
463     pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
464     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
465
466     if (pa_channel_map_equal(from, to))
467         return v;
468
469     result.channels = to->channels;
470
471     for (b = 0; b < to->channels; b++) {
472         pa_volume_t k = 0;
473         int n = 0;
474
475         for (a = 0; a < from->channels; a++)
476             if (from->map[a] == to->map[b]) {
477                 k += v->values[a];
478                 n ++;
479             }
480
481         if (n <= 0) {
482             for (a = 0; a < from->channels; a++)
483                 if ((on_left(from->map[a]) && on_left(to->map[b])) ||
484                     (on_right(from->map[a]) && on_right(to->map[b])) ||
485                     (on_center(from->map[a]) && on_center(to->map[b])) ||
486                     (on_lfe(from->map[a]) && on_lfe(to->map[b]))) {
487
488                     k += v->values[a];
489                     n ++;
490                 }
491         }
492
493         if (n <= 0)
494             k = pa_cvolume_avg(v);
495         else
496             k /= n;
497
498         result.values[b] = k;
499     }
500
501     *v = result;
502     return v;
503 }
504
505 int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
506
507     pa_assert(v);
508     pa_assert(ss);
509
510     pa_return_val_if_fail(pa_cvolume_valid(v), 0);
511     pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
512
513     return v->channels == ss->channels;
514 }
515
516 int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) {
517     pa_assert(v);
518     pa_assert(cm);
519
520     pa_return_val_if_fail(pa_cvolume_valid(v), 0);
521     pa_return_val_if_fail(pa_channel_map_valid(cm), 0);
522
523     return v->channels == cm->channels;
524 }
525
526 static void get_avg_lr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *l, pa_volume_t *r) {
527     int c;
528     pa_volume_t left = 0, right = 0;
529     unsigned n_left = 0, n_right = 0;
530
531     pa_assert(v);
532     pa_assert(map);
533     pa_assert(map->channels == v->channels);
534     pa_assert(l);
535     pa_assert(r);
536
537     for (c = 0; c < map->channels; c++) {
538         if (on_left(map->map[c])) {
539             left += v->values[c];
540             n_left++;
541         } else if (on_right(map->map[c])) {
542             right += v->values[c];
543             n_right++;
544         }
545     }
546
547     if (n_left <= 0)
548         *l = PA_VOLUME_NORM;
549     else
550         *l = left / n_left;
551
552     if (n_right <= 0)
553         *r = PA_VOLUME_NORM;
554     else
555         *r = right / n_right;
556 }
557
558 float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
559     pa_volume_t left, right;
560
561     pa_assert(v);
562     pa_assert(map);
563
564     pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
565     pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
566     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
567
568     if (!pa_channel_map_can_balance(map))
569         return 0.0f;
570
571     get_avg_lr(map, v, &left, &right);
572
573     if (left == right)
574         return 0.0f;
575
576     /*   1.0,  0.0  =>  -1.0
577          0.0,  1.0  =>   1.0
578          0.0,  0.0  =>   0.0
579          0.5,  0.5  =>   0.0
580          1.0,  0.5  =>  -0.5
581          1.0,  0.25 => -0.75
582          0.75, 0.25 => -0.66
583          0.5,  0.25 => -0.5   */
584
585     if (left > right)
586         return -1.0f + ((float) right / (float) left);
587     else
588         return 1.0f - ((float) left / (float) right);
589 }
590
591 pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, float new_balance) {
592     pa_volume_t left, nleft, right, nright, m;
593     unsigned c;
594
595     pa_assert(map);
596     pa_assert(v);
597     pa_assert(new_balance >= -1.0f);
598     pa_assert(new_balance <= 1.0f);
599
600     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
601     pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
602     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
603
604     if (!pa_channel_map_can_balance(map))
605         return v;
606
607     get_avg_lr(map, v, &left, &right);
608
609     m = PA_MAX(left, right);
610
611     if (new_balance <= 0) {
612         nright  = (new_balance + 1.0f) * m;
613         nleft = m;
614     } else  {
615         nleft = (1.0f - new_balance) * m;
616         nright = m;
617     }
618
619     for (c = 0; c < map->channels; c++) {
620         if (on_left(map->map[c])) {
621             if (left == 0)
622                 v->values[c] = nleft;
623             else
624                 v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nleft) / (uint64_t) left);
625         } else if (on_right(map->map[c])) {
626             if (right == 0)
627                 v->values[c] = nright;
628             else
629                 v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nright) / (uint64_t) right);
630         }
631     }
632
633     return v;
634 }
635
636 pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
637     unsigned c;
638     pa_volume_t t = 0;
639
640     pa_assert(v);
641
642     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
643     pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
644
645     t = pa_cvolume_max(v);
646
647     if (t <= PA_VOLUME_MUTED)
648         return pa_cvolume_set(v, v->channels, max);
649
650     for (c = 0; c < v->channels; c++)
651         v->values[c] = (pa_volume_t) (((uint64_t)  v->values[c] * (uint64_t) max) / (uint64_t) t);
652
653     return v;
654 }
655
656 pa_cvolume* pa_cvolume_scale_mask(pa_cvolume *v, pa_volume_t max, pa_channel_map *cm, pa_channel_position_mask_t mask) {
657     unsigned c;
658     pa_volume_t t = 0;
659
660     pa_assert(v);
661
662     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
663     pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
664
665     t = pa_cvolume_max_mask(v, cm, mask);
666
667     if (t <= PA_VOLUME_MUTED)
668         return pa_cvolume_set(v, v->channels, max);
669
670     for (c = 0; c < v->channels; c++)
671         v->values[c] = (pa_volume_t) (((uint64_t)  v->values[c] * (uint64_t) max) / (uint64_t) t);
672
673     return v;
674 }
675
676 static void get_avg_fr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *f, pa_volume_t *r) {
677     int c;
678     pa_volume_t front = 0, rear = 0;
679     unsigned n_front = 0, n_rear = 0;
680
681     pa_assert(v);
682     pa_assert(map);
683     pa_assert(map->channels == v->channels);
684     pa_assert(f);
685     pa_assert(r);
686
687     for (c = 0; c < map->channels; c++) {
688         if (on_front(map->map[c])) {
689             front += v->values[c];
690             n_front++;
691         } else if (on_rear(map->map[c])) {
692             rear += v->values[c];
693             n_rear++;
694         }
695     }
696
697     if (n_front <= 0)
698         *f = PA_VOLUME_NORM;
699     else
700         *f = front / n_front;
701
702     if (n_rear <= 0)
703         *r = PA_VOLUME_NORM;
704     else
705         *r = rear / n_rear;
706 }
707
708 float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
709     pa_volume_t front, rear;
710
711     pa_assert(v);
712     pa_assert(map);
713
714     pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
715     pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
716     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
717
718     if (!pa_channel_map_can_fade(map))
719         return 0.0f;
720
721     get_avg_fr(map, v, &front, &rear);
722
723     if (front == rear)
724         return 0.0f;
725
726     if (rear > front)
727         return -1.0f + ((float) front / (float) rear);
728     else
729         return 1.0f - ((float) rear / (float) front);
730 }
731
732 pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float new_fade) {
733     pa_volume_t front, nfront, rear, nrear, m;
734     unsigned c;
735
736     pa_assert(map);
737     pa_assert(v);
738     pa_assert(new_fade >= -1.0f);
739     pa_assert(new_fade <= 1.0f);
740
741     pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
742     pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
743     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
744
745     if (!pa_channel_map_can_fade(map))
746         return v;
747
748     get_avg_fr(map, v, &front, &rear);
749
750     m = PA_MAX(front, rear);
751
752     if (new_fade <= 0) {
753         nfront  = (new_fade + 1.0f) * m;
754         nrear = m;
755     } else  {
756         nrear = (1.0f - new_fade) * m;
757         nfront = m;
758     }
759
760     for (c = 0; c < map->channels; c++) {
761         if (on_front(map->map[c])) {
762             if (front == 0)
763                 v->values[c] = nfront;
764             else
765                 v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nfront) / (uint64_t) front);
766         } else if (on_rear(map->map[c])) {
767             if (rear == 0)
768                 v->values[c] = nrear;
769             else
770                 v->values[c] = (pa_volume_t) (((uint64_t) v->values[c] * (uint64_t) nrear) / (uint64_t) rear);
771         }
772     }
773
774     return v;
775 }
776
777 pa_cvolume* pa_cvolume_set_position(
778         pa_cvolume *cv,
779         const pa_channel_map *map,
780         pa_channel_position_t t,
781         pa_volume_t v) {
782
783     unsigned c;
784     pa_bool_t good = FALSE;
785
786     pa_assert(cv);
787     pa_assert(map);
788
789     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), NULL);
790     pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, NULL);
791
792     for (c = 0; c < map->channels; c++)
793         if (map->map[c] == t) {
794             cv->values[c] = v;
795             good = TRUE;
796         }
797
798     return good ? cv : NULL;
799 }
800
801 pa_volume_t pa_cvolume_get_position(
802         pa_cvolume *cv,
803         const pa_channel_map *map,
804         pa_channel_position_t t) {
805
806     unsigned c;
807     pa_volume_t v = PA_VOLUME_MUTED;
808
809     pa_assert(cv);
810     pa_assert(map);
811
812     pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(cv, map), PA_VOLUME_MUTED);
813     pa_return_val_if_fail(t < PA_CHANNEL_POSITION_MAX, PA_VOLUME_MUTED);
814
815     for (c = 0; c < map->channels; c++)
816         if (map->map[c] == t)
817             if (cv->values[c] > v)
818                 v = cv->values[c];
819
820     return v;
821 }
822
823 pa_cvolume* pa_cvolume_merge(pa_cvolume *dest, const pa_cvolume *a, const pa_cvolume *b) {
824     unsigned i;
825
826     pa_assert(dest);
827     pa_assert(a);
828     pa_assert(b);
829
830     pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
831     pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
832
833     for (i = 0; i < a->channels && i < b->channels; i++)
834         dest->values[i] = PA_MAX(a->values[i], b->values[i]);
835
836     dest->channels = (uint8_t) i;
837
838     return dest;
839 }