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