2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6 Copyright 2013 Peter Meerwald <pmeerw@pmeerw.net>
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as published
10 by the Free Software Foundation; either version 2.1 of the License,
11 or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <pulsecore/sample-util.h>
31 #include <pulsecore/macro.h>
32 #include <pulsecore/g711.h>
33 #include <pulsecore/endianmacros.h>
37 #define VOLUME_PADDING 32
39 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
40 unsigned channel
, nchannels
, padding
;
45 nchannels
= volume
->channels
;
47 for (channel
= 0; channel
< nchannels
; channel
++)
48 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
50 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
51 linear
[channel
] = linear
[padding
];
54 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
55 unsigned channel
, nchannels
, padding
;
60 nchannels
= volume
->channels
;
62 for (channel
= 0; channel
< nchannels
; channel
++)
63 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
65 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
66 linear
[channel
] = linear
[padding
];
69 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
71 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
77 calc_linear_float_volume(linear
, volume
);
79 for (k
= 0; k
< nstreams
; k
++) {
81 for (channel
= 0; channel
< spec
->channels
; channel
++) {
82 pa_mix_info
*m
= streams
+ k
;
83 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
88 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
90 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
96 calc_linear_float_volume(linear
, volume
);
98 for (k
= 0; k
< nstreams
; k
++) {
100 for (channel
= 0; channel
< spec
->channels
; channel
++) {
101 pa_mix_info
*m
= streams
+ k
;
102 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
107 typedef void (*pa_calc_stream_volumes_func_t
) (pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
);
109 static const pa_calc_stream_volumes_func_t calc_stream_volumes_table
[] = {
110 [PA_SAMPLE_U8
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
111 [PA_SAMPLE_ALAW
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
112 [PA_SAMPLE_ULAW
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
113 [PA_SAMPLE_S16LE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
114 [PA_SAMPLE_S16BE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
115 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_stream_volumes_func_t
) calc_linear_float_stream_volumes
,
116 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_stream_volumes_func_t
) calc_linear_float_stream_volumes
,
117 [PA_SAMPLE_S32LE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
118 [PA_SAMPLE_S32BE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
119 [PA_SAMPLE_S24LE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
120 [PA_SAMPLE_S24BE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
121 [PA_SAMPLE_S24_32LE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
,
122 [PA_SAMPLE_S24_32BE
] = (pa_calc_stream_volumes_func_t
) calc_linear_integer_stream_volumes
125 /* special case: mix 2 s16ne streams, 1 channel each */
126 static void pa_mix2_ch1_s16ne(pa_mix_info streams
[], int16_t *data
, unsigned length
) {
127 const int16_t *ptr0
= streams
[0].ptr
;
128 const int16_t *ptr1
= streams
[1].ptr
;
130 const int32_t cv0
= streams
[0].linear
[0].i
;
131 const int32_t cv1
= streams
[1].linear
[0].i
;
133 length
/= sizeof(int16_t);
135 for (; length
> 0; length
--) {
138 sum
= pa_mult_s16_volume(*ptr0
++, cv0
);
139 sum
+= pa_mult_s16_volume(*ptr1
++, cv1
);
141 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
146 /* special case: mix 2 s16ne streams, 2 channels each */
147 static void pa_mix2_ch2_s16ne(pa_mix_info streams
[], int16_t *data
, unsigned length
) {
148 const int16_t *ptr0
= streams
[0].ptr
;
149 const int16_t *ptr1
= streams
[1].ptr
;
151 length
/= sizeof(int16_t) * 2;
153 for (; length
> 0; length
--) {
156 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[0].i
);
157 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[0].i
);
159 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
162 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[1].i
);
163 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[1].i
);
165 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
170 /* special case: mix 2 s16ne streams */
171 static void pa_mix2_s16ne(pa_mix_info streams
[], unsigned channels
, int16_t *data
, unsigned length
) {
172 const int16_t *ptr0
= streams
[0].ptr
;
173 const int16_t *ptr1
= streams
[1].ptr
;
174 unsigned channel
= 0;
176 length
/= sizeof(int16_t);
178 for (; length
> 0; length
--) {
181 sum
= pa_mult_s16_volume(*ptr0
++, streams
[0].linear
[channel
].i
);
182 sum
+= pa_mult_s16_volume(*ptr1
++, streams
[1].linear
[channel
].i
);
184 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
187 if (PA_UNLIKELY(++channel
>= channels
))
192 /* special case: mix s16ne streams, 2 channels each */
193 static void pa_mix_ch2_s16ne(pa_mix_info streams
[], unsigned nstreams
, int16_t *data
, unsigned length
) {
195 length
/= sizeof(int16_t) * 2;
197 for (; length
> 0; length
--) {
198 int32_t sum0
= 0, sum1
= 0;
201 for (i
= 0; i
< nstreams
; i
++) {
202 pa_mix_info
*m
= streams
+ i
;
203 int32_t cv0
= m
->linear
[0].i
;
204 int32_t cv1
= m
->linear
[1].i
;
206 sum0
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv0
);
207 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
209 sum1
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv1
);
210 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
213 *data
++ = PA_CLAMP_UNLIKELY(sum0
, -0x8000, 0x7FFF);
214 *data
++ = PA_CLAMP_UNLIKELY(sum1
, -0x8000, 0x7FFF);
218 static void pa_mix_generic_s16ne(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int16_t *data
, unsigned length
) {
219 unsigned channel
= 0;
221 length
/= sizeof(int16_t);
223 for (; length
> 0; length
--) {
227 for (i
= 0; i
< nstreams
; i
++) {
228 pa_mix_info
*m
= streams
+ i
;
229 int32_t cv
= m
->linear
[channel
].i
;
231 if (PA_LIKELY(cv
> 0))
232 sum
+= pa_mult_s16_volume(*((int16_t*) m
->ptr
), cv
);
233 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
236 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
239 if (PA_UNLIKELY(++channel
>= channels
))
244 static void pa_mix_s16ne_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int16_t *data
, unsigned length
) {
245 if (nstreams
== 2 && channels
== 1)
246 pa_mix2_ch1_s16ne(streams
, data
, length
);
247 else if (nstreams
== 2 && channels
== 2)
248 pa_mix2_ch2_s16ne(streams
, data
, length
);
249 else if (nstreams
== 2)
250 pa_mix2_s16ne(streams
, channels
, data
, length
);
251 else if (channels
== 2)
252 pa_mix_ch2_s16ne(streams
, nstreams
, data
, length
);
254 pa_mix_generic_s16ne(streams
, nstreams
, channels
, data
, length
);
257 static void pa_mix_s16re_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int16_t *data
, unsigned length
) {
258 unsigned channel
= 0;
260 length
/= sizeof(int16_t);
262 for (; length
> 0; length
--, data
++) {
266 for (i
= 0; i
< nstreams
; i
++) {
267 pa_mix_info
*m
= streams
+ i
;
268 int32_t cv
= m
->linear
[channel
].i
;
270 if (PA_LIKELY(cv
> 0))
271 sum
+= pa_mult_s16_volume(PA_INT16_SWAP(*((int16_t*) m
->ptr
)), cv
);
272 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
275 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
276 *data
= PA_INT16_SWAP((int16_t) sum
);
278 if (PA_UNLIKELY(++channel
>= channels
))
283 static void pa_mix_s32ne_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int32_t *data
, unsigned length
) {
284 unsigned channel
= 0;
286 length
/= sizeof(int32_t);
288 for (; length
> 0; length
--, data
++) {
292 for (i
= 0; i
< nstreams
; i
++) {
293 pa_mix_info
*m
= streams
+ i
;
294 int32_t cv
= m
->linear
[channel
].i
;
297 if (PA_LIKELY(cv
> 0)) {
298 v
= *((int32_t*) m
->ptr
);
302 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
305 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
306 *data
= (int32_t) sum
;
308 if (PA_UNLIKELY(++channel
>= channels
))
313 static void pa_mix_s32re_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, int32_t *data
, unsigned length
) {
314 unsigned channel
= 0;
316 length
/= sizeof(int32_t);
318 for (; length
> 0; length
--, data
++) {
322 for (i
= 0; i
< nstreams
; i
++) {
323 pa_mix_info
*m
= streams
+ i
;
324 int32_t cv
= m
->linear
[channel
].i
;
327 if (PA_LIKELY(cv
> 0)) {
328 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
332 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
335 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
336 *data
= PA_INT32_SWAP((int32_t) sum
);
338 if (PA_UNLIKELY(++channel
>= channels
))
343 static void pa_mix_s24ne_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint8_t *data
, unsigned length
) {
344 unsigned channel
= 0;
346 for (; length
> 0; length
-= 3, data
+= 3) {
350 for (i
= 0; i
< nstreams
; i
++) {
351 pa_mix_info
*m
= streams
+ i
;
352 int32_t cv
= m
->linear
[channel
].i
;
355 if (PA_LIKELY(cv
> 0)) {
356 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
360 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
363 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
364 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
366 if (PA_UNLIKELY(++channel
>= channels
))
371 static void pa_mix_s24re_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint8_t *data
, unsigned length
) {
372 unsigned channel
= 0;
374 for (; length
> 0; length
-= 3, data
+= 3) {
378 for (i
= 0; i
< nstreams
; i
++) {
379 pa_mix_info
*m
= streams
+ i
;
380 int32_t cv
= m
->linear
[channel
].i
;
383 if (PA_LIKELY(cv
> 0)) {
384 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
388 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
391 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
392 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
394 if (PA_UNLIKELY(++channel
>= channels
))
399 static void pa_mix_s24_32ne_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint32_t *data
, unsigned length
) {
400 unsigned channel
= 0;
402 length
/= sizeof(uint32_t);
404 for (; length
> 0; length
--, data
++) {
408 for (i
= 0; i
< nstreams
; i
++) {
409 pa_mix_info
*m
= streams
+ i
;
410 int32_t cv
= m
->linear
[channel
].i
;
413 if (PA_LIKELY(cv
> 0)) {
414 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
418 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
421 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
422 *data
= ((uint32_t) (int32_t) sum
) >> 8;
424 if (PA_UNLIKELY(++channel
>= channels
))
429 static void pa_mix_s24_32re_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint32_t *data
, unsigned length
) {
430 unsigned channel
= 0;
432 length
/= sizeof(uint32_t);
434 for (; length
> 0; length
--, data
++) {
438 for (i
= 0; i
< nstreams
; i
++) {
439 pa_mix_info
*m
= streams
+ i
;
440 int32_t cv
= m
->linear
[channel
].i
;
443 if (PA_LIKELY(cv
> 0)) {
444 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
448 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
451 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
452 *data
= PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
454 if (PA_UNLIKELY(++channel
>= channels
))
459 static void pa_mix_u8_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint8_t *data
, unsigned length
) {
460 unsigned channel
= 0;
462 length
/= sizeof(uint8_t);
464 for (; length
> 0; length
--, data
++) {
468 for (i
= 0; i
< nstreams
; i
++) {
469 pa_mix_info
*m
= streams
+ i
;
470 int32_t v
, cv
= m
->linear
[channel
].i
;
472 if (PA_LIKELY(cv
> 0)) {
473 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
477 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
480 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
481 *data
= (uint8_t) (sum
+ 0x80);
483 if (PA_UNLIKELY(++channel
>= channels
))
488 static void pa_mix_ulaw_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint8_t *data
, unsigned length
) {
489 unsigned channel
= 0;
491 length
/= sizeof(uint8_t);
493 for (; length
> 0; length
--, data
++) {
497 for (i
= 0; i
< nstreams
; i
++) {
498 pa_mix_info
*m
= streams
+ i
;
499 int32_t cv
= m
->linear
[channel
].i
;
501 if (PA_LIKELY(cv
> 0))
502 sum
+= pa_mult_s16_volume(st_ulaw2linear16(*((uint8_t*) m
->ptr
)), cv
);
503 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
506 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
507 *data
= (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
509 if (PA_UNLIKELY(++channel
>= channels
))
514 static void pa_mix_alaw_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, uint8_t *data
, unsigned length
) {
515 unsigned channel
= 0;
517 length
/= sizeof(uint8_t);
519 for (; length
> 0; length
--, data
++) {
523 for (i
= 0; i
< nstreams
; i
++) {
524 pa_mix_info
*m
= streams
+ i
;
525 int32_t cv
= m
->linear
[channel
].i
;
527 if (PA_LIKELY(cv
> 0))
528 sum
+= pa_mult_s16_volume(st_alaw2linear16(*((uint8_t*) m
->ptr
)), cv
);
529 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
532 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
533 *data
= (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
535 if (PA_UNLIKELY(++channel
>= channels
))
540 static void pa_mix_float32ne_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, float *data
, unsigned length
) {
541 unsigned channel
= 0;
543 length
/= sizeof(float);
545 for (; length
> 0; length
--, data
++) {
549 for (i
= 0; i
< nstreams
; i
++) {
550 pa_mix_info
*m
= streams
+ i
;
551 float v
, cv
= m
->linear
[channel
].f
;
553 if (PA_LIKELY(cv
> 0)) {
554 v
= *((float*) m
->ptr
);
558 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
563 if (PA_UNLIKELY(++channel
>= channels
))
568 static void pa_mix_float32re_c(pa_mix_info streams
[], unsigned nstreams
, unsigned channels
, float *data
, unsigned length
) {
569 unsigned channel
= 0;
571 length
/= sizeof(float);
573 for (; length
> 0; length
--, data
++) {
577 for (i
= 0; i
< nstreams
; i
++) {
578 pa_mix_info
*m
= streams
+ i
;
579 float v
, cv
= m
->linear
[channel
].f
;
581 if (PA_LIKELY(cv
> 0)) {
582 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
586 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
589 *data
= PA_FLOAT32_SWAP(sum
);
591 if (PA_UNLIKELY(++channel
>= channels
))
596 static pa_do_mix_func_t do_mix_table
[] = {
597 [PA_SAMPLE_U8
] = (pa_do_mix_func_t
) pa_mix_u8_c
,
598 [PA_SAMPLE_ALAW
] = (pa_do_mix_func_t
) pa_mix_alaw_c
,
599 [PA_SAMPLE_ULAW
] = (pa_do_mix_func_t
) pa_mix_ulaw_c
,
600 [PA_SAMPLE_S16NE
] = (pa_do_mix_func_t
) pa_mix_s16ne_c
,
601 [PA_SAMPLE_S16RE
] = (pa_do_mix_func_t
) pa_mix_s16re_c
,
602 [PA_SAMPLE_FLOAT32NE
] = (pa_do_mix_func_t
) pa_mix_float32ne_c
,
603 [PA_SAMPLE_FLOAT32RE
] = (pa_do_mix_func_t
) pa_mix_float32re_c
,
604 [PA_SAMPLE_S32NE
] = (pa_do_mix_func_t
) pa_mix_s32ne_c
,
605 [PA_SAMPLE_S32RE
] = (pa_do_mix_func_t
) pa_mix_s32re_c
,
606 [PA_SAMPLE_S24NE
] = (pa_do_mix_func_t
) pa_mix_s24ne_c
,
607 [PA_SAMPLE_S24RE
] = (pa_do_mix_func_t
) pa_mix_s24re_c
,
608 [PA_SAMPLE_S24_32NE
] = (pa_do_mix_func_t
) pa_mix_s24_32ne_c
,
609 [PA_SAMPLE_S24_32RE
] = (pa_do_mix_func_t
) pa_mix_s24_32re_c
613 pa_mix_info streams
[],
617 const pa_sample_spec
*spec
,
618 const pa_cvolume
*volume
,
621 pa_cvolume full_volume
;
630 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
632 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
633 pa_silence_memory(data
, length
, spec
);
637 for (k
= 0; k
< nstreams
; k
++) {
638 streams
[k
].ptr
= pa_memblock_acquire_chunk(&streams
[k
].chunk
);
639 if (length
> streams
[k
].chunk
.length
)
640 length
= streams
[k
].chunk
.length
;
643 calc_stream_volumes_table
[spec
->format
](streams
, nstreams
, volume
, spec
);
644 do_mix_table
[spec
->format
](streams
, nstreams
, spec
->channels
, data
, length
);
646 for (k
= 0; k
< nstreams
; k
++)
647 pa_memblock_release(streams
[k
].chunk
.memblock
);
652 pa_do_mix_func_t
pa_get_mix_func(pa_sample_format_t f
) {
653 pa_assert(pa_sample_format_valid(f
));
655 return do_mix_table
[f
];
658 void pa_set_mix_func(pa_sample_format_t f
, pa_do_mix_func_t func
) {
659 pa_assert(pa_sample_format_valid(f
));
661 do_mix_table
[f
] = func
;
669 typedef void (*pa_calc_volume_func_t
) (void *volumes
, const pa_cvolume
*volume
);
671 static const pa_calc_volume_func_t calc_volume_table
[] = {
672 [PA_SAMPLE_U8
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
673 [PA_SAMPLE_ALAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
674 [PA_SAMPLE_ULAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
675 [PA_SAMPLE_S16LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
676 [PA_SAMPLE_S16BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
677 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
678 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
679 [PA_SAMPLE_S32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
680 [PA_SAMPLE_S32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
681 [PA_SAMPLE_S24LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
682 [PA_SAMPLE_S24BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
683 [PA_SAMPLE_S24_32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
684 [PA_SAMPLE_S24_32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
687 void pa_volume_memchunk(
689 const pa_sample_spec
*spec
,
690 const pa_cvolume
*volume
) {
693 volume_val linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
694 pa_do_volume_func_t do_volume
;
698 pa_assert(pa_sample_spec_valid(spec
));
699 pa_assert(pa_frame_aligned(c
->length
, spec
));
702 if (pa_memblock_is_silence(c
->memblock
))
705 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
708 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
709 pa_silence_memchunk(c
, spec
);
713 do_volume
= pa_get_volume_func(spec
->format
);
714 pa_assert(do_volume
);
716 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
718 ptr
= pa_memblock_acquire_chunk(c
);
720 do_volume(ptr
, (void *)linear
, spec
->channels
, c
->length
);
722 pa_memblock_release(c
->memblock
);