2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <liboil/liboilfuncs.h>
34 #include <liboil/liboil.h>
36 #include <pulse/timeval.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/macro.h>
41 #include <pulsecore/g711.h>
42 #include <pulsecore/core-util.h>
44 #include "sample-util.h"
45 #include "endianmacros.h"
47 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
49 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
55 data
= pa_memblock_acquire(b
);
56 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
57 pa_memblock_release(b
);
62 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
66 pa_assert(c
->memblock
);
69 data
= pa_memblock_acquire(c
->memblock
);
70 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
71 pa_memblock_release(c
->memblock
);
76 static uint8_t silence_byte(pa_sample_format_t format
) {
84 case PA_SAMPLE_FLOAT32LE
:
85 case PA_SAMPLE_FLOAT32BE
:
88 case PA_SAMPLE_S24_32LE
:
89 case PA_SAMPLE_S24_32BE
:
96 pa_assert_not_reached();
100 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
102 pa_assert(length
> 0);
105 memset(p
, silence_byte(spec
->format
), length
);
109 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
115 for (channel
= 0; channel
< volume
->channels
; channel
++)
116 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
119 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
125 for (channel
= 0; channel
< volume
->channels
; channel
++)
126 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
129 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
131 float linear
[PA_CHANNELS_MAX
];
137 calc_linear_float_volume(linear
, volume
);
139 for (k
= 0; k
< nstreams
; k
++) {
141 for (channel
= 0; channel
< spec
->channels
; channel
++) {
142 pa_mix_info
*m
= streams
+ k
;
143 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
148 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
150 float linear
[PA_CHANNELS_MAX
];
156 calc_linear_float_volume(linear
, volume
);
158 for (k
= 0; k
< nstreams
; k
++) {
160 for (channel
= 0; channel
< spec
->channels
; channel
++) {
161 pa_mix_info
*m
= streams
+ k
;
162 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
168 pa_mix_info streams
[],
172 const pa_sample_spec
*spec
,
173 const pa_cvolume
*volume
,
176 pa_cvolume full_volume
;
187 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
189 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
190 pa_silence_memory(data
, length
, spec
);
194 for (k
= 0; k
< nstreams
; k
++)
195 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
197 for (z
= 0; z
< nstreams
; z
++)
198 if (length
> streams
[z
].chunk
.length
)
199 length
= streams
[z
].chunk
.length
;
201 end
= (uint8_t*) data
+ length
;
203 switch (spec
->format
) {
205 case PA_SAMPLE_S16NE
:{
206 unsigned channel
= 0;
208 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
214 for (i
= 0; i
< nstreams
; i
++) {
215 pa_mix_info
*m
= streams
+ i
;
216 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
218 if (PA_UNLIKELY(cv
<= 0))
221 /* Multiplying the 32bit volume factor with the
222 * 16bit sample might result in an 48bit value. We
223 * want to do without 64 bit integers and hence do
224 * the multiplication independantly for the HI and
225 * LO part of the volume. */
230 v
= *((int16_t*) m
->ptr
);
231 v
= ((v
* lo
) >> 16) + (v
* hi
);
234 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
237 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
238 *((int16_t*) data
) = (int16_t) sum
;
240 data
= (uint8_t*) data
+ sizeof(int16_t);
242 if (PA_UNLIKELY(++channel
>= spec
->channels
))
249 case PA_SAMPLE_S16RE
:{
250 unsigned channel
= 0;
252 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
258 for (i
= 0; i
< nstreams
; i
++) {
259 pa_mix_info
*m
= streams
+ i
;
260 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
262 if (PA_UNLIKELY(cv
<= 0))
268 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
269 v
= ((v
* lo
) >> 16) + (v
* hi
);
272 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
275 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
276 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
278 data
= (uint8_t*) data
+ sizeof(int16_t);
280 if (PA_UNLIKELY(++channel
>= spec
->channels
))
287 case PA_SAMPLE_S32NE
:{
288 unsigned channel
= 0;
290 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
296 for (i
= 0; i
< nstreams
; i
++) {
297 pa_mix_info
*m
= streams
+ i
;
298 int32_t cv
= m
->linear
[channel
].i
;
301 if (PA_UNLIKELY(cv
<= 0))
304 v
= *((int32_t*) m
->ptr
);
308 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
311 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
312 *((int32_t*) data
) = (int32_t) sum
;
314 data
= (uint8_t*) data
+ sizeof(int32_t);
316 if (PA_UNLIKELY(++channel
>= spec
->channels
))
323 case PA_SAMPLE_S32RE
:{
324 unsigned channel
= 0;
326 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
332 for (i
= 0; i
< nstreams
; i
++) {
333 pa_mix_info
*m
= streams
+ i
;
334 int32_t cv
= m
->linear
[channel
].i
;
337 if (PA_UNLIKELY(cv
<= 0))
340 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
344 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
347 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
348 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
350 data
= (uint8_t*) data
+ sizeof(int32_t);
352 if (PA_UNLIKELY(++channel
>= spec
->channels
))
359 case PA_SAMPLE_S24NE
: {
360 unsigned channel
= 0;
362 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
368 for (i
= 0; i
< nstreams
; i
++) {
369 pa_mix_info
*m
= streams
+ i
;
370 int32_t cv
= m
->linear
[channel
].i
;
373 if (PA_UNLIKELY(cv
<= 0))
376 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
380 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
383 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
384 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
386 data
= (uint8_t*) data
+ 3;
388 if (PA_UNLIKELY(++channel
>= spec
->channels
))
395 case PA_SAMPLE_S24RE
: {
396 unsigned channel
= 0;
398 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
404 for (i
= 0; i
< nstreams
; i
++) {
405 pa_mix_info
*m
= streams
+ i
;
406 int32_t cv
= m
->linear
[channel
].i
;
409 if (PA_UNLIKELY(cv
<= 0))
412 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
416 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
419 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
420 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
422 data
= (uint8_t*) data
+ 3;
424 if (PA_UNLIKELY(++channel
>= spec
->channels
))
431 case PA_SAMPLE_S24_32NE
: {
432 unsigned channel
= 0;
434 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
440 for (i
= 0; i
< nstreams
; i
++) {
441 pa_mix_info
*m
= streams
+ i
;
442 int32_t cv
= m
->linear
[channel
].i
;
445 if (PA_UNLIKELY(cv
<= 0))
448 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
452 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
455 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
456 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
458 data
= (uint8_t*) data
+ sizeof(uint32_t);
460 if (PA_UNLIKELY(++channel
>= spec
->channels
))
467 case PA_SAMPLE_S24_32RE
: {
468 unsigned channel
= 0;
470 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
476 for (i
= 0; i
< nstreams
; i
++) {
477 pa_mix_info
*m
= streams
+ i
;
478 int32_t cv
= m
->linear
[channel
].i
;
481 if (PA_UNLIKELY(cv
<= 0))
484 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
488 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
491 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
492 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
494 data
= (uint8_t*) data
+ sizeof(uint32_t);
496 if (PA_UNLIKELY(++channel
>= spec
->channels
))
504 unsigned channel
= 0;
506 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
512 for (i
= 0; i
< nstreams
; i
++) {
513 pa_mix_info
*m
= streams
+ i
;
514 int32_t v
, cv
= m
->linear
[channel
].i
;
516 if (PA_UNLIKELY(cv
<= 0))
519 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
523 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
526 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
527 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
529 data
= (uint8_t*) data
+ 1;
531 if (PA_UNLIKELY(++channel
>= spec
->channels
))
538 case PA_SAMPLE_ULAW
: {
539 unsigned channel
= 0;
541 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
547 for (i
= 0; i
< nstreams
; i
++) {
548 pa_mix_info
*m
= streams
+ i
;
549 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
551 if (PA_UNLIKELY(cv
<= 0))
557 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
558 v
= ((v
* lo
) >> 16) + (v
* hi
);
561 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
564 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
565 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
567 data
= (uint8_t*) data
+ 1;
569 if (PA_UNLIKELY(++channel
>= spec
->channels
))
576 case PA_SAMPLE_ALAW
: {
577 unsigned channel
= 0;
579 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
585 for (i
= 0; i
< nstreams
; i
++) {
586 pa_mix_info
*m
= streams
+ i
;
587 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
589 if (PA_UNLIKELY(cv
<= 0))
595 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
596 v
= ((v
* lo
) >> 16) + (v
* hi
);
599 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
602 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
603 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
605 data
= (uint8_t*) data
+ 1;
607 if (PA_UNLIKELY(++channel
>= spec
->channels
))
614 case PA_SAMPLE_FLOAT32NE
: {
615 unsigned channel
= 0;
617 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
623 for (i
= 0; i
< nstreams
; i
++) {
624 pa_mix_info
*m
= streams
+ i
;
625 float v
, cv
= m
->linear
[channel
].f
;
627 if (PA_UNLIKELY(cv
<= 0))
630 v
= *((float*) m
->ptr
);
634 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
637 *((float*) data
) = sum
;
639 data
= (uint8_t*) data
+ sizeof(float);
641 if (PA_UNLIKELY(++channel
>= spec
->channels
))
648 case PA_SAMPLE_FLOAT32RE
: {
649 unsigned channel
= 0;
651 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
657 for (i
= 0; i
< nstreams
; i
++) {
658 pa_mix_info
*m
= streams
+ i
;
659 float v
, cv
= m
->linear
[channel
].f
;
661 if (PA_UNLIKELY(cv
<= 0))
664 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
668 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
671 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
673 data
= (uint8_t*) data
+ sizeof(float);
675 if (PA_UNLIKELY(++channel
>= spec
->channels
))
683 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
684 pa_assert_not_reached();
687 for (k
= 0; k
< nstreams
; k
++)
688 pa_memblock_release(streams
[k
].chunk
.memblock
);
694 void pa_volume_memchunk(
696 const pa_sample_spec
*spec
,
697 const pa_cvolume
*volume
) {
703 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
706 if (pa_memblock_is_silence(c
->memblock
))
709 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
712 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
713 pa_silence_memchunk(c
, spec
);
717 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
719 switch (spec
->format
) {
721 case PA_SAMPLE_S16NE
: {
724 int32_t linear
[PA_CHANNELS_MAX
];
726 calc_linear_integer_volume(linear
, volume
);
728 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
730 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
733 /* Multiplying the 32bit volume factor with the 16bit
734 * sample might result in an 48bit value. We want to
735 * do without 64 bit integers and hence do the
736 * multiplication independantly for the HI and LO part
739 hi
= linear
[channel
] >> 16;
740 lo
= linear
[channel
] & 0xFFFF;
743 t
= ((t
* lo
) >> 16) + (t
* hi
);
744 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
747 if (PA_UNLIKELY(++channel
>= spec
->channels
))
754 case PA_SAMPLE_S16RE
: {
757 int32_t linear
[PA_CHANNELS_MAX
];
759 calc_linear_integer_volume(linear
, volume
);
761 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
763 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
766 hi
= linear
[channel
] >> 16;
767 lo
= linear
[channel
] & 0xFFFF;
769 t
= (int32_t) PA_INT16_SWAP(*d
);
770 t
= ((t
* lo
) >> 16) + (t
* hi
);
771 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
772 *d
= PA_INT16_SWAP((int16_t) t
);
774 if (PA_UNLIKELY(++channel
>= spec
->channels
))
781 case PA_SAMPLE_S32NE
: {
784 int32_t linear
[PA_CHANNELS_MAX
];
786 calc_linear_integer_volume(linear
, volume
);
788 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
790 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
794 t
= (t
* linear
[channel
]) >> 16;
795 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
798 if (PA_UNLIKELY(++channel
>= spec
->channels
))
804 case PA_SAMPLE_S32RE
: {
807 int32_t linear
[PA_CHANNELS_MAX
];
809 calc_linear_integer_volume(linear
, volume
);
811 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
813 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
816 t
= (int64_t) PA_INT32_SWAP(*d
);
817 t
= (t
* linear
[channel
]) >> 16;
818 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
819 *d
= PA_INT32_SWAP((int32_t) t
);
821 if (PA_UNLIKELY(++channel
>= spec
->channels
))
827 case PA_SAMPLE_S24NE
: {
830 int32_t linear
[PA_CHANNELS_MAX
];
832 calc_linear_integer_volume(linear
, volume
);
834 e
= (uint8_t*) ptr
+ c
->length
;
836 for (channel
= 0, d
= ptr
; d
< e
; d
+= 3) {
839 t
= (int64_t)((int32_t) (PA_READ24NE(d
) << 8));
840 t
= (t
* linear
[channel
]) >> 16;
841 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
842 PA_WRITE24NE(d
, ((uint32_t) (int32_t) t
) >> 8);
844 if (PA_UNLIKELY(++channel
>= spec
->channels
))
850 case PA_SAMPLE_S24RE
: {
853 int32_t linear
[PA_CHANNELS_MAX
];
855 calc_linear_integer_volume(linear
, volume
);
857 e
= (uint8_t*) ptr
+ c
->length
;
859 for (channel
= 0, d
= ptr
; d
< e
; d
+= 3) {
862 t
= (int64_t)((int32_t) (PA_READ24RE(d
) << 8));
863 t
= (t
* linear
[channel
]) >> 16;
864 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
865 PA_WRITE24RE(d
, ((uint32_t) (int32_t) t
) >> 8);
867 if (PA_UNLIKELY(++channel
>= spec
->channels
))
873 case PA_SAMPLE_S24_32NE
: {
876 int32_t linear
[PA_CHANNELS_MAX
];
878 calc_linear_integer_volume(linear
, volume
);
880 e
= (uint32_t*) ptr
+ c
->length
/sizeof(uint32_t);
882 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
885 t
= (int64_t) ((int32_t) (*d
<< 8));
886 t
= (t
* linear
[channel
]) >> 16;
887 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
888 *d
= ((uint32_t) ((int32_t) t
)) >> 8;
890 if (PA_UNLIKELY(++channel
>= spec
->channels
))
896 case PA_SAMPLE_S24_32RE
: {
899 int32_t linear
[PA_CHANNELS_MAX
];
901 calc_linear_integer_volume(linear
, volume
);
903 e
= (uint32_t*) ptr
+ c
->length
/sizeof(uint32_t);
905 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
908 t
= (int64_t) ((int32_t) (PA_UINT32_SWAP(*d
) << 8));
909 t
= (t
* linear
[channel
]) >> 16;
910 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
911 *d
= PA_UINT32_SWAP(((uint32_t) ((int32_t) t
)) >> 8);
913 if (PA_UNLIKELY(++channel
>= spec
->channels
))
922 int32_t linear
[PA_CHANNELS_MAX
];
924 calc_linear_integer_volume(linear
, volume
);
926 e
= (uint8_t*) ptr
+ c
->length
;
928 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
931 hi
= linear
[channel
] >> 16;
932 lo
= linear
[channel
] & 0xFFFF;
934 t
= (int32_t) *d
- 0x80;
935 t
= ((t
* lo
) >> 16) + (t
* hi
);
936 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
937 *d
= (uint8_t) (t
+ 0x80);
939 if (PA_UNLIKELY(++channel
>= spec
->channels
))
945 case PA_SAMPLE_ULAW
: {
948 int32_t linear
[PA_CHANNELS_MAX
];
950 calc_linear_integer_volume(linear
, volume
);
952 e
= (uint8_t*) ptr
+ c
->length
;
954 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
957 hi
= linear
[channel
] >> 16;
958 lo
= linear
[channel
] & 0xFFFF;
960 t
= (int32_t) st_ulaw2linear16(*d
);
961 t
= ((t
* lo
) >> 16) + (t
* hi
);
962 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
963 *d
= (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
965 if (PA_UNLIKELY(++channel
>= spec
->channels
))
971 case PA_SAMPLE_ALAW
: {
974 int32_t linear
[PA_CHANNELS_MAX
];
976 calc_linear_integer_volume(linear
, volume
);
978 e
= (uint8_t*) ptr
+ c
->length
;
980 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
983 hi
= linear
[channel
] >> 16;
984 lo
= linear
[channel
] & 0xFFFF;
986 t
= (int32_t) st_alaw2linear16(*d
);
987 t
= ((t
* lo
) >> 16) + (t
* hi
);
988 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
989 *d
= (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
991 if (PA_UNLIKELY(++channel
>= spec
->channels
))
997 case PA_SAMPLE_FLOAT32NE
: {
1004 skip
= (int) (spec
->channels
* sizeof(float));
1005 n
= (unsigned) (c
->length
/sizeof(float)/spec
->channels
);
1007 for (channel
= 0; channel
< spec
->channels
; channel
++) {
1010 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
1013 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
1015 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, (int) n
);
1020 case PA_SAMPLE_FLOAT32RE
: {
1023 float linear
[PA_CHANNELS_MAX
];
1025 calc_linear_float_volume(linear
, volume
);
1027 e
= (float*) ptr
+ c
->length
/sizeof(float);
1029 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
1032 t
= PA_FLOAT32_SWAP(*d
);
1033 t
*= linear
[channel
];
1034 *d
= PA_FLOAT32_SWAP(t
);
1036 if (PA_UNLIKELY(++channel
>= spec
->channels
))
1045 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
1046 /* If we cannot change the volume, we just don't do it */
1049 pa_memblock_release(c
->memblock
);
1052 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
1057 fs
= pa_frame_size(ss
);
1062 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
1067 fs
= pa_frame_size(ss
);
1072 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
1077 pa_assert(channels
> 0);
1084 for (c
= 0; c
< channels
; c
++) {
1090 d
= (uint8_t*) dst
+ c
* ss
;
1092 for (j
= 0; j
< n
; j
++) {
1093 oil_memcpy(d
, s
, (int) ss
);
1094 s
= (uint8_t*) s
+ ss
;
1095 d
= (uint8_t*) d
+ fs
;
1100 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
1106 pa_assert(channels
> 0);
1112 for (c
= 0; c
< channels
; c
++) {
1117 s
= (uint8_t*) src
+ c
* ss
;
1120 for (j
= 0; j
< n
; j
++) {
1121 oil_memcpy(d
, s
, (int) ss
);
1122 s
= (uint8_t*) s
+ fs
;
1123 d
= (uint8_t*) d
+ ss
;
1128 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
1135 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
1137 b
= pa_memblock_new(pool
, length
);
1139 data
= pa_memblock_acquire(b
);
1140 memset(data
, c
, length
);
1141 pa_memblock_release(b
);
1143 pa_memblock_set_is_silence(b
, TRUE
);
1148 void pa_silence_cache_init(pa_silence_cache
*cache
) {
1151 memset(cache
, 0, sizeof(pa_silence_cache
));
1154 void pa_silence_cache_done(pa_silence_cache
*cache
) {
1155 pa_sample_format_t f
;
1158 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
1159 if (cache
->blocks
[f
])
1160 pa_memblock_unref(cache
->blocks
[f
]);
1162 memset(cache
, 0, sizeof(pa_silence_cache
));
1165 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
1170 pa_assert(pa_sample_spec_valid(spec
));
1172 if (!(b
= cache
->blocks
[spec
->format
]))
1174 switch (spec
->format
) {
1176 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
1178 case PA_SAMPLE_S16LE
:
1179 case PA_SAMPLE_S16BE
:
1180 case PA_SAMPLE_S32LE
:
1181 case PA_SAMPLE_S32BE
:
1182 case PA_SAMPLE_S24LE
:
1183 case PA_SAMPLE_S24BE
:
1184 case PA_SAMPLE_S24_32LE
:
1185 case PA_SAMPLE_S24_32BE
:
1186 case PA_SAMPLE_FLOAT32LE
:
1187 case PA_SAMPLE_FLOAT32BE
:
1188 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
1189 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
1190 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
1191 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
1192 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
1193 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
1194 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
1195 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
1196 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
1197 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
1199 case PA_SAMPLE_ALAW
:
1200 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
1202 case PA_SAMPLE_ULAW
:
1203 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
1206 pa_assert_not_reached();
1211 ret
->memblock
= pa_memblock_ref(b
);
1213 l
= pa_memblock_get_length(b
);
1214 if (length
> l
|| length
== 0)
1217 ret
->length
= pa_frame_align(length
, spec
);
1223 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
1229 if (format
== PA_SAMPLE_FLOAT32NE
) {
1231 float minus_one
= -1.0, plus_one
= 1.0;
1232 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
1235 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
1237 for (; n
> 0; n
--) {
1240 f
= PA_FLOAT32_SWAP(*s
);
1241 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
1242 *d
= PA_FLOAT32_SWAP(f
);
1244 s
= (const float*) ((const uint8_t*) s
+ sstr
);
1245 d
= (float*) ((uint8_t*) d
+ dstr
);
1250 /* Similar to pa_bytes_to_usec() but rounds up, not down */
1252 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
1258 fs
= pa_frame_size(spec
);
1259 length
= (length
+ fs
- 1) / fs
;
1261 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
1263 return (usec
+ spec
->rate
- 1) / spec
->rate
;
1266 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1268 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
1272 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
1274 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
1276 u
*= pa_frame_size(spec
);
1281 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1288 /* Only for debugging purposes */
1293 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1297 p
= pa_memblock_acquire(c
->memblock
);
1299 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1300 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1302 pa_memblock_release(c
->memblock
);
1307 static void calc_sine(float *f
, size_t l
, double freq
) {
1312 for (i
= 0; i
< l
; i
++)
1313 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1316 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1321 pa_memchunk_reset(c
);
1323 gcd
= pa_gcd(rate
, freq
);
1326 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1332 c
->length
= l
* sizeof(float);
1333 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1335 p
= pa_memblock_acquire(c
->memblock
);
1336 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1337 pa_memblock_release(c
->memblock
);