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
:
94 pa_assert_not_reached();
98 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
100 pa_assert(length
> 0);
103 memset(p
, silence_byte(spec
->format
), length
);
107 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
113 for (channel
= 0; channel
< volume
->channels
; channel
++)
114 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
117 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
123 for (channel
= 0; channel
< volume
->channels
; channel
++)
124 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
127 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
129 float linear
[PA_CHANNELS_MAX
];
135 calc_linear_float_volume(linear
, volume
);
137 for (k
= 0; k
< nstreams
; k
++) {
139 for (channel
= 0; channel
< spec
->channels
; channel
++) {
140 pa_mix_info
*m
= streams
+ k
;
141 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
146 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
148 float linear
[PA_CHANNELS_MAX
];
154 calc_linear_float_volume(linear
, volume
);
156 for (k
= 0; k
< nstreams
; k
++) {
158 for (channel
= 0; channel
< spec
->channels
; channel
++) {
159 pa_mix_info
*m
= streams
+ k
;
160 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
166 pa_mix_info streams
[],
170 const pa_sample_spec
*spec
,
171 const pa_cvolume
*volume
,
174 pa_cvolume full_volume
;
185 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
187 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
188 pa_silence_memory(data
, length
, spec
);
192 for (k
= 0; k
< nstreams
; k
++)
193 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
195 for (z
= 0; z
< nstreams
; z
++)
196 if (length
> streams
[z
].chunk
.length
)
197 length
= streams
[z
].chunk
.length
;
199 end
= (uint8_t*) data
+ length
;
201 switch (spec
->format
) {
203 case PA_SAMPLE_S16NE
:{
204 unsigned channel
= 0;
206 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
212 for (i
= 0; i
< nstreams
; i
++) {
213 pa_mix_info
*m
= streams
+ i
;
214 int32_t v
, cv
= m
->linear
[channel
].i
;
216 if (PA_UNLIKELY(cv
<= 0))
219 v
= *((int16_t*) m
->ptr
);
220 v
= (v
* cv
) / 0x10000;
223 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
226 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
227 *((int16_t*) data
) = (int16_t) sum
;
229 data
= (uint8_t*) data
+ sizeof(int16_t);
231 if (PA_UNLIKELY(++channel
>= spec
->channels
))
238 case PA_SAMPLE_S16RE
:{
239 unsigned channel
= 0;
241 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
247 for (i
= 0; i
< nstreams
; i
++) {
248 pa_mix_info
*m
= streams
+ i
;
249 int32_t v
, cv
= m
->linear
[channel
].i
;
251 if (PA_UNLIKELY(cv
<= 0))
254 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
255 v
= (v
* cv
) / 0x10000;
258 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
261 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
262 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
264 data
= (uint8_t*) data
+ sizeof(int16_t);
266 if (PA_UNLIKELY(++channel
>= spec
->channels
))
273 case PA_SAMPLE_S32NE
:{
274 unsigned channel
= 0;
276 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
282 for (i
= 0; i
< nstreams
; i
++) {
283 pa_mix_info
*m
= streams
+ i
;
284 int32_t cv
= m
->linear
[channel
].i
;
287 if (PA_UNLIKELY(cv
<= 0))
290 v
= *((int32_t*) m
->ptr
);
291 v
= (v
* cv
) / 0x10000;
294 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
297 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
298 *((int32_t*) data
) = (int32_t) sum
;
300 data
= (uint8_t*) data
+ sizeof(int32_t);
302 if (PA_UNLIKELY(++channel
>= spec
->channels
))
309 case PA_SAMPLE_S32RE
:{
310 unsigned channel
= 0;
312 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
318 for (i
= 0; i
< nstreams
; i
++) {
319 pa_mix_info
*m
= streams
+ i
;
320 int32_t cv
= m
->linear
[channel
].i
;
323 if (PA_UNLIKELY(cv
<= 0))
326 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
327 v
= (v
* cv
) / 0x10000;
330 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
333 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
334 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
336 data
= (uint8_t*) data
+ sizeof(int32_t);
338 if (PA_UNLIKELY(++channel
>= spec
->channels
))
345 case PA_SAMPLE_S24NE
: {
346 unsigned channel
= 0;
348 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
354 for (i
= 0; i
< nstreams
; i
++) {
355 pa_mix_info
*m
= streams
+ i
;
356 int32_t cv
= m
->linear
[channel
].i
;
359 if (PA_UNLIKELY(cv
<= 0))
362 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
363 v
= (v
* cv
) / 0x10000;
366 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
369 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
370 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
372 data
= (uint8_t*) data
+ 3;
374 if (PA_UNLIKELY(++channel
>= spec
->channels
))
381 case PA_SAMPLE_S24RE
: {
382 unsigned channel
= 0;
384 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
390 for (i
= 0; i
< nstreams
; i
++) {
391 pa_mix_info
*m
= streams
+ i
;
392 int32_t cv
= m
->linear
[channel
].i
;
395 if (PA_UNLIKELY(cv
<= 0))
398 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
399 v
= (v
* cv
) / 0x10000;
402 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
405 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
406 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
408 data
= (uint8_t*) data
+ 3;
410 if (PA_UNLIKELY(++channel
>= spec
->channels
))
418 unsigned channel
= 0;
420 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
426 for (i
= 0; i
< nstreams
; i
++) {
427 pa_mix_info
*m
= streams
+ i
;
428 int32_t v
, cv
= m
->linear
[channel
].i
;
430 if (PA_UNLIKELY(cv
<= 0))
433 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
434 v
= (v
* cv
) / 0x10000;
437 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
440 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
441 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
443 data
= (uint8_t*) data
+ 1;
445 if (PA_UNLIKELY(++channel
>= spec
->channels
))
452 case PA_SAMPLE_ULAW
: {
453 unsigned channel
= 0;
455 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
461 for (i
= 0; i
< nstreams
; i
++) {
462 pa_mix_info
*m
= streams
+ i
;
463 int32_t v
, cv
= m
->linear
[channel
].i
;
465 if (PA_UNLIKELY(cv
<= 0))
468 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
469 v
= (v
* cv
) / 0x10000;
472 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
475 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
476 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
478 data
= (uint8_t*) data
+ 1;
480 if (PA_UNLIKELY(++channel
>= spec
->channels
))
487 case PA_SAMPLE_ALAW
: {
488 unsigned channel
= 0;
490 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
496 for (i
= 0; i
< nstreams
; i
++) {
497 pa_mix_info
*m
= streams
+ i
;
498 int32_t v
, cv
= m
->linear
[channel
].i
;
500 if (PA_UNLIKELY(cv
<= 0))
503 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
504 v
= (v
* cv
) / 0x10000;
507 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
510 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
511 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
513 data
= (uint8_t*) data
+ 1;
515 if (PA_UNLIKELY(++channel
>= spec
->channels
))
522 case PA_SAMPLE_FLOAT32NE
: {
523 unsigned channel
= 0;
525 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
531 for (i
= 0; i
< nstreams
; i
++) {
532 pa_mix_info
*m
= streams
+ i
;
533 float v
, cv
= m
->linear
[channel
].f
;
535 if (PA_UNLIKELY(cv
<= 0))
538 v
= *((float*) m
->ptr
);
542 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
545 *((float*) data
) = sum
;
547 data
= (uint8_t*) data
+ sizeof(float);
549 if (PA_UNLIKELY(++channel
>= spec
->channels
))
556 case PA_SAMPLE_FLOAT32RE
: {
557 unsigned channel
= 0;
559 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
565 for (i
= 0; i
< nstreams
; i
++) {
566 pa_mix_info
*m
= streams
+ i
;
567 float v
, cv
= m
->linear
[channel
].f
;
569 if (PA_UNLIKELY(cv
<= 0))
572 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
576 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
579 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
581 data
= (uint8_t*) data
+ sizeof(float);
583 if (PA_UNLIKELY(++channel
>= spec
->channels
))
591 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
592 pa_assert_not_reached();
595 for (k
= 0; k
< nstreams
; k
++)
596 pa_memblock_release(streams
[k
].chunk
.memblock
);
602 void pa_volume_memchunk(
604 const pa_sample_spec
*spec
,
605 const pa_cvolume
*volume
) {
611 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
614 if (pa_memblock_is_silence(c
->memblock
))
617 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
620 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
621 pa_silence_memchunk(c
, spec
);
625 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
627 switch (spec
->format
) {
629 case PA_SAMPLE_S16NE
: {
632 int32_t linear
[PA_CHANNELS_MAX
];
634 calc_linear_integer_volume(linear
, volume
);
636 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
638 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
642 t
= (t
* linear
[channel
]) / 0x10000;
643 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
646 if (PA_UNLIKELY(++channel
>= spec
->channels
))
652 case PA_SAMPLE_S16RE
: {
655 int32_t linear
[PA_CHANNELS_MAX
];
657 calc_linear_integer_volume(linear
, volume
);
659 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
661 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
664 t
= (int32_t) PA_INT16_SWAP(*d
);
665 t
= (t
* linear
[channel
]) / 0x10000;
666 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
667 *d
= PA_INT16_SWAP((int16_t) t
);
669 if (PA_UNLIKELY(++channel
>= spec
->channels
))
676 case PA_SAMPLE_S32NE
: {
679 int32_t linear
[PA_CHANNELS_MAX
];
681 calc_linear_integer_volume(linear
, volume
);
683 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
685 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
689 t
= (t
* linear
[channel
]) / 0x10000;
690 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
693 if (PA_UNLIKELY(++channel
>= spec
->channels
))
699 case PA_SAMPLE_S32RE
: {
702 int32_t linear
[PA_CHANNELS_MAX
];
704 calc_linear_integer_volume(linear
, volume
);
706 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
708 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
711 t
= (int64_t) PA_INT32_SWAP(*d
);
712 t
= (t
* linear
[channel
]) / 0x10000;
713 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
714 *d
= PA_INT32_SWAP((int32_t) t
);
716 if (PA_UNLIKELY(++channel
>= spec
->channels
))
722 case PA_SAMPLE_S24NE
: {
725 int32_t linear
[PA_CHANNELS_MAX
];
727 calc_linear_integer_volume(linear
, volume
);
729 e
= (uint8_t*) ptr
+ c
->length
/3;
731 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
734 t
= (int64_t)((int32_t) (PA_READ24NE(d
) << 8));
735 t
= (t
* linear
[channel
]) / 0x10000;
736 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
737 PA_WRITE24NE(d
, ((uint32_t) (int32_t) t
) >> 8);
739 if (PA_UNLIKELY(++channel
>= spec
->channels
))
745 case PA_SAMPLE_S24RE
: {
748 int32_t linear
[PA_CHANNELS_MAX
];
750 calc_linear_integer_volume(linear
, volume
);
752 e
= (uint8_t*) ptr
+ c
->length
/3;
754 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
757 t
= (int64_t)((int32_t) (PA_READ24RE(d
) << 8));
758 t
= (t
* linear
[channel
]) / 0x10000;
759 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
760 PA_WRITE24RE(d
, ((uint32_t) (int32_t) t
) >> 8);
762 if (PA_UNLIKELY(++channel
>= spec
->channels
))
771 int32_t linear
[PA_CHANNELS_MAX
];
773 calc_linear_integer_volume(linear
, volume
);
775 e
= (uint8_t*) ptr
+ c
->length
;
777 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
780 t
= (int32_t) *d
- 0x80;
781 t
= (t
* linear
[channel
]) / 0x10000;
782 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
783 *d
= (uint8_t) (t
+ 0x80);
785 if (PA_UNLIKELY(++channel
>= spec
->channels
))
791 case PA_SAMPLE_ULAW
: {
794 int32_t linear
[PA_CHANNELS_MAX
];
796 calc_linear_integer_volume(linear
, volume
);
798 e
= (uint8_t*) ptr
+ c
->length
;
800 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
803 t
= (int32_t) st_ulaw2linear16(*d
);
804 t
= (t
* linear
[channel
]) / 0x10000;
805 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
806 *d
= (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
808 if (PA_UNLIKELY(++channel
>= spec
->channels
))
814 case PA_SAMPLE_ALAW
: {
817 int32_t linear
[PA_CHANNELS_MAX
];
819 calc_linear_integer_volume(linear
, volume
);
821 e
= (uint8_t*) ptr
+ c
->length
;
823 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
826 t
= (int32_t) st_alaw2linear16(*d
);
827 t
= (t
* linear
[channel
]) / 0x10000;
828 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
829 *d
= (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
831 if (PA_UNLIKELY(++channel
>= spec
->channels
))
837 case PA_SAMPLE_FLOAT32NE
: {
844 skip
= (int) (spec
->channels
* sizeof(float));
845 n
= (unsigned) (c
->length
/sizeof(float)/spec
->channels
);
847 for (channel
= 0; channel
< spec
->channels
; channel
++) {
850 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
853 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
855 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, (int) n
);
860 case PA_SAMPLE_FLOAT32RE
: {
863 float linear
[PA_CHANNELS_MAX
];
865 calc_linear_float_volume(linear
, volume
);
867 e
= (float*) ptr
+ c
->length
/sizeof(float);
869 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
872 t
= PA_FLOAT32_SWAP(*d
);
873 t
*= linear
[channel
];
874 *d
= PA_FLOAT32_SWAP(t
);
876 if (PA_UNLIKELY(++channel
>= spec
->channels
))
885 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
886 /* If we cannot change the volume, we just don't do it */
889 pa_memblock_release(c
->memblock
);
892 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
897 fs
= pa_frame_size(ss
);
902 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
907 fs
= pa_frame_size(ss
);
912 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
917 pa_assert(channels
> 0);
924 for (c
= 0; c
< channels
; c
++) {
930 d
= (uint8_t*) dst
+ c
* ss
;
932 for (j
= 0; j
< n
; j
++) {
933 oil_memcpy(d
, s
, (int) ss
);
934 s
= (uint8_t*) s
+ ss
;
935 d
= (uint8_t*) d
+ fs
;
940 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
946 pa_assert(channels
> 0);
952 for (c
= 0; c
< channels
; c
++) {
957 s
= (uint8_t*) src
+ c
* ss
;
960 for (j
= 0; j
< n
; j
++) {
961 oil_memcpy(d
, s
, (int) ss
);
962 s
= (uint8_t*) s
+ fs
;
963 d
= (uint8_t*) d
+ ss
;
968 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
975 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
977 b
= pa_memblock_new(pool
, length
);
979 data
= pa_memblock_acquire(b
);
980 memset(data
, c
, length
);
981 pa_memblock_release(b
);
983 pa_memblock_set_is_silence(b
, TRUE
);
988 void pa_silence_cache_init(pa_silence_cache
*cache
) {
991 memset(cache
, 0, sizeof(pa_silence_cache
));
994 void pa_silence_cache_done(pa_silence_cache
*cache
) {
995 pa_sample_format_t f
;
998 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
999 if (cache
->blocks
[f
])
1000 pa_memblock_unref(cache
->blocks
[f
]);
1002 memset(cache
, 0, sizeof(pa_silence_cache
));
1005 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
1010 pa_assert(pa_sample_spec_valid(spec
));
1012 if (!(b
= cache
->blocks
[spec
->format
]))
1014 switch (spec
->format
) {
1016 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
1018 case PA_SAMPLE_S16LE
:
1019 case PA_SAMPLE_S16BE
:
1020 case PA_SAMPLE_S32LE
:
1021 case PA_SAMPLE_S32BE
:
1022 case PA_SAMPLE_S24LE
:
1023 case PA_SAMPLE_S24BE
:
1024 case PA_SAMPLE_FLOAT32LE
:
1025 case PA_SAMPLE_FLOAT32BE
:
1026 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
1027 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
1028 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
1029 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
1030 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
1031 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
1032 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
1033 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
1035 case PA_SAMPLE_ALAW
:
1036 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
1038 case PA_SAMPLE_ULAW
:
1039 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
1042 pa_assert_not_reached();
1047 ret
->memblock
= pa_memblock_ref(b
);
1049 l
= pa_memblock_get_length(b
);
1050 if (length
> l
|| length
== 0)
1053 ret
->length
= pa_frame_align(length
, spec
);
1059 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
1065 if (format
== PA_SAMPLE_FLOAT32NE
) {
1067 float minus_one
= -1.0, plus_one
= 1.0;
1068 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
1071 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
1073 for (; n
> 0; n
--) {
1076 f
= PA_FLOAT32_SWAP(*s
);
1077 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
1078 *d
= PA_FLOAT32_SWAP(f
);
1080 s
= (const float*) ((const uint8_t*) s
+ sstr
);
1081 d
= (float*) ((uint8_t*) d
+ dstr
);
1086 /* Similar to pa_bytes_to_usec() but rounds up, not down */
1088 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
1094 fs
= pa_frame_size(spec
);
1095 length
= (length
+ fs
- 1) / fs
;
1097 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
1099 return (usec
+ spec
->rate
- 1) / spec
->rate
;
1102 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1104 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
1108 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
1110 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
1112 u
*= pa_frame_size(spec
);
1117 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1124 /* Only for debugging purposes */
1129 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1133 p
= pa_memblock_acquire(c
->memblock
);
1135 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1136 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1138 pa_memblock_release(c
->memblock
);
1143 static void calc_sine(float *f
, size_t l
, double freq
) {
1148 for (i
= 0; i
< l
; i
++)
1149 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1152 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1157 pa_memchunk_reset(c
);
1159 gcd
= pa_gcd(rate
, freq
);
1162 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1168 c
->length
= l
* sizeof(float);
1169 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1171 p
= pa_memblock_acquire(c
->memblock
);
1172 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1173 pa_memblock_release(c
->memblock
);