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