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 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
/3;
836 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
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
/3;
859 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
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_FLOAT32LE
:
1185 case PA_SAMPLE_FLOAT32BE
:
1186 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
1187 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
1188 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
1189 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
1190 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
1191 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
1192 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
1193 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
1195 case PA_SAMPLE_ALAW
:
1196 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
1198 case PA_SAMPLE_ULAW
:
1199 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
1202 pa_assert_not_reached();
1207 ret
->memblock
= pa_memblock_ref(b
);
1209 l
= pa_memblock_get_length(b
);
1210 if (length
> l
|| length
== 0)
1213 ret
->length
= pa_frame_align(length
, spec
);
1219 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
1225 if (format
== PA_SAMPLE_FLOAT32NE
) {
1227 float minus_one
= -1.0, plus_one
= 1.0;
1228 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
1231 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
1233 for (; n
> 0; n
--) {
1236 f
= PA_FLOAT32_SWAP(*s
);
1237 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
1238 *d
= PA_FLOAT32_SWAP(f
);
1240 s
= (const float*) ((const uint8_t*) s
+ sstr
);
1241 d
= (float*) ((uint8_t*) d
+ dstr
);
1246 /* Similar to pa_bytes_to_usec() but rounds up, not down */
1248 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
1254 fs
= pa_frame_size(spec
);
1255 length
= (length
+ fs
- 1) / fs
;
1257 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
1259 return (usec
+ spec
->rate
- 1) / spec
->rate
;
1262 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1264 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
1268 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
1270 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
1272 u
*= pa_frame_size(spec
);
1277 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1284 /* Only for debugging purposes */
1289 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1293 p
= pa_memblock_acquire(c
->memblock
);
1295 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1296 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1298 pa_memblock_release(c
->memblock
);
1303 static void calc_sine(float *f
, size_t l
, double freq
) {
1308 for (i
= 0; i
< l
; i
++)
1309 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1312 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1317 pa_memchunk_reset(c
);
1319 gcd
= pa_gcd(rate
, freq
);
1322 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1328 c
->length
= l
* sizeof(float);
1329 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1331 p
= pa_memblock_acquire(c
->memblock
);
1332 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1333 pa_memblock_release(c
->memblock
);