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
]);
108 pa_mix_info streams
[],
112 const pa_sample_spec
*spec
,
113 const pa_cvolume
*volume
,
116 pa_cvolume full_volume
;
127 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
129 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
130 pa_silence_memory(data
, length
, spec
);
134 for (k
= 0; k
< nstreams
; k
++)
135 streams
[k
].ptr
= pa_memblock_acquire_chunk(&streams
[k
].chunk
);
137 for (z
= 0; z
< nstreams
; z
++)
138 if (length
> streams
[z
].chunk
.length
)
139 length
= streams
[z
].chunk
.length
;
141 end
= (uint8_t*) data
+ length
;
143 switch (spec
->format
) {
145 case PA_SAMPLE_S16NE
:{
146 unsigned channel
= 0;
148 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
154 for (i
= 0; i
< nstreams
; i
++) {
155 pa_mix_info
*m
= streams
+ i
;
156 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
158 if (PA_LIKELY(cv
> 0)) {
160 /* Multiplying the 32bit volume factor with the
161 * 16bit sample might result in an 48bit value. We
162 * want to do without 64 bit integers and hence do
163 * the multiplication independently for the HI and
164 * LO part of the volume. */
169 v
= *((int16_t*) m
->ptr
);
170 v
= ((v
* lo
) >> 16) + (v
* hi
);
173 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
176 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
177 *((int16_t*) data
) = (int16_t) sum
;
179 data
= (uint8_t*) data
+ sizeof(int16_t);
181 if (PA_UNLIKELY(++channel
>= spec
->channels
))
188 case PA_SAMPLE_S16RE
:{
189 unsigned channel
= 0;
191 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
197 for (i
= 0; i
< nstreams
; i
++) {
198 pa_mix_info
*m
= streams
+ i
;
199 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
201 if (PA_LIKELY(cv
> 0)) {
206 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
207 v
= ((v
* lo
) >> 16) + (v
* hi
);
210 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
213 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
214 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
216 data
= (uint8_t*) data
+ sizeof(int16_t);
218 if (PA_UNLIKELY(++channel
>= spec
->channels
))
225 case PA_SAMPLE_S32NE
:{
226 unsigned channel
= 0;
228 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
234 for (i
= 0; i
< nstreams
; i
++) {
235 pa_mix_info
*m
= streams
+ i
;
236 int32_t cv
= m
->linear
[channel
].i
;
239 if (PA_LIKELY(cv
> 0)) {
241 v
= *((int32_t*) m
->ptr
);
245 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
248 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
249 *((int32_t*) data
) = (int32_t) sum
;
251 data
= (uint8_t*) data
+ sizeof(int32_t);
253 if (PA_UNLIKELY(++channel
>= spec
->channels
))
260 case PA_SAMPLE_S32RE
:{
261 unsigned channel
= 0;
263 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
269 for (i
= 0; i
< nstreams
; i
++) {
270 pa_mix_info
*m
= streams
+ i
;
271 int32_t cv
= m
->linear
[channel
].i
;
274 if (PA_LIKELY(cv
> 0)) {
276 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
280 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
283 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
284 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
286 data
= (uint8_t*) data
+ sizeof(int32_t);
288 if (PA_UNLIKELY(++channel
>= spec
->channels
))
295 case PA_SAMPLE_S24NE
: {
296 unsigned channel
= 0;
298 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
304 for (i
= 0; i
< nstreams
; i
++) {
305 pa_mix_info
*m
= streams
+ i
;
306 int32_t cv
= m
->linear
[channel
].i
;
309 if (PA_LIKELY(cv
> 0)) {
311 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
315 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
318 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
319 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
321 data
= (uint8_t*) data
+ 3;
323 if (PA_UNLIKELY(++channel
>= spec
->channels
))
330 case PA_SAMPLE_S24RE
: {
331 unsigned channel
= 0;
333 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
339 for (i
= 0; i
< nstreams
; i
++) {
340 pa_mix_info
*m
= streams
+ i
;
341 int32_t cv
= m
->linear
[channel
].i
;
344 if (PA_LIKELY(cv
> 0)) {
346 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
350 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
353 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
354 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
356 data
= (uint8_t*) data
+ 3;
358 if (PA_UNLIKELY(++channel
>= spec
->channels
))
365 case PA_SAMPLE_S24_32NE
: {
366 unsigned channel
= 0;
368 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
374 for (i
= 0; i
< nstreams
; i
++) {
375 pa_mix_info
*m
= streams
+ i
;
376 int32_t cv
= m
->linear
[channel
].i
;
379 if (PA_LIKELY(cv
> 0)) {
381 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
385 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
388 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
389 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
391 data
= (uint8_t*) data
+ sizeof(uint32_t);
393 if (PA_UNLIKELY(++channel
>= spec
->channels
))
400 case PA_SAMPLE_S24_32RE
: {
401 unsigned channel
= 0;
403 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
409 for (i
= 0; i
< nstreams
; i
++) {
410 pa_mix_info
*m
= streams
+ i
;
411 int32_t cv
= m
->linear
[channel
].i
;
414 if (PA_LIKELY(cv
> 0)) {
416 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
420 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
423 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
424 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
426 data
= (uint8_t*) data
+ sizeof(uint32_t);
428 if (PA_UNLIKELY(++channel
>= spec
->channels
))
436 unsigned channel
= 0;
438 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
444 for (i
= 0; i
< nstreams
; i
++) {
445 pa_mix_info
*m
= streams
+ i
;
446 int32_t v
, cv
= m
->linear
[channel
].i
;
448 if (PA_LIKELY(cv
> 0)) {
450 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
454 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
457 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
458 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
460 data
= (uint8_t*) data
+ 1;
462 if (PA_UNLIKELY(++channel
>= spec
->channels
))
469 case PA_SAMPLE_ULAW
: {
470 unsigned channel
= 0;
472 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
478 for (i
= 0; i
< nstreams
; i
++) {
479 pa_mix_info
*m
= streams
+ i
;
480 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
482 if (PA_LIKELY(cv
> 0)) {
487 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
488 v
= ((v
* lo
) >> 16) + (v
* hi
);
491 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
494 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
495 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
497 data
= (uint8_t*) data
+ 1;
499 if (PA_UNLIKELY(++channel
>= spec
->channels
))
506 case PA_SAMPLE_ALAW
: {
507 unsigned channel
= 0;
509 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
515 for (i
= 0; i
< nstreams
; i
++) {
516 pa_mix_info
*m
= streams
+ i
;
517 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
519 if (PA_LIKELY(cv
> 0)) {
524 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
525 v
= ((v
* lo
) >> 16) + (v
* hi
);
528 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
531 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
532 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
534 data
= (uint8_t*) data
+ 1;
536 if (PA_UNLIKELY(++channel
>= spec
->channels
))
543 case PA_SAMPLE_FLOAT32NE
: {
544 unsigned channel
= 0;
546 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
552 for (i
= 0; i
< nstreams
; i
++) {
553 pa_mix_info
*m
= streams
+ i
;
554 float v
, cv
= m
->linear
[channel
].f
;
556 if (PA_LIKELY(cv
> 0)) {
558 v
= *((float*) m
->ptr
);
562 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
565 *((float*) data
) = sum
;
567 data
= (uint8_t*) data
+ sizeof(float);
569 if (PA_UNLIKELY(++channel
>= spec
->channels
))
576 case PA_SAMPLE_FLOAT32RE
: {
577 unsigned channel
= 0;
579 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
585 for (i
= 0; i
< nstreams
; i
++) {
586 pa_mix_info
*m
= streams
+ i
;
587 float v
, cv
= m
->linear
[channel
].f
;
589 if (PA_LIKELY(cv
> 0)) {
591 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
595 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
598 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
600 data
= (uint8_t*) data
+ sizeof(float);
602 if (PA_UNLIKELY(++channel
>= spec
->channels
))
610 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
611 pa_assert_not_reached();
614 for (k
= 0; k
< nstreams
; k
++)
615 pa_memblock_release(streams
[k
].chunk
.memblock
);
625 typedef void (*pa_calc_volume_func_t
) (void *volumes
, const pa_cvolume
*volume
);
627 static const pa_calc_volume_func_t calc_volume_table
[] = {
628 [PA_SAMPLE_U8
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
629 [PA_SAMPLE_ALAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
630 [PA_SAMPLE_ULAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
631 [PA_SAMPLE_S16LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
632 [PA_SAMPLE_S16BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
633 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
634 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
635 [PA_SAMPLE_S32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
636 [PA_SAMPLE_S32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
637 [PA_SAMPLE_S24LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
638 [PA_SAMPLE_S24BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
639 [PA_SAMPLE_S24_32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
640 [PA_SAMPLE_S24_32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
643 void pa_volume_memchunk(
645 const pa_sample_spec
*spec
,
646 const pa_cvolume
*volume
) {
649 volume_val linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
650 pa_do_volume_func_t do_volume
;
654 pa_assert(pa_sample_spec_valid(spec
));
655 pa_assert(pa_frame_aligned(c
->length
, spec
));
658 if (pa_memblock_is_silence(c
->memblock
))
661 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
664 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
665 pa_silence_memchunk(c
, spec
);
669 do_volume
= pa_get_volume_func(spec
->format
);
670 pa_assert(do_volume
);
672 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
674 ptr
= pa_memblock_acquire_chunk(c
);
676 do_volume(ptr
, (void *)linear
, spec
->channels
, c
->length
);
678 pa_memblock_release(c
->memblock
);