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
31 #include <liboil/liboilfuncs.h>
32 #include <liboil/liboil.h>
34 #include <pulsecore/log.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/g711.h>
38 #include "sample-util.h"
39 #include "endianmacros.h"
41 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
43 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
49 data
= pa_memblock_acquire(b
);
50 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
51 pa_memblock_release(b
);
56 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
60 pa_assert(c
->memblock
);
63 data
= pa_memblock_acquire(c
->memblock
);
64 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
65 pa_memblock_release(c
->memblock
);
70 static uint8_t silence_byte(pa_sample_format_t format
) {
78 case PA_SAMPLE_FLOAT32LE
:
79 case PA_SAMPLE_FLOAT32BE
:
86 pa_assert_not_reached();
91 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
93 pa_assert(length
> 0);
96 memset(p
, silence_byte(spec
->format
), length
);
100 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
106 for (k
= 0; k
< nstreams
; k
++) {
109 for (channel
= 0; channel
< spec
->channels
; channel
++) {
110 pa_mix_info
*m
= streams
+ k
;
111 m
->linear
[channel
].i
= (int32_t) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * 0x10000);
116 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
122 for (channel
= 0; channel
< volume
->channels
; channel
++)
123 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
126 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
132 for (k
= 0; k
< nstreams
; k
++) {
135 for (channel
= 0; channel
< spec
->channels
; channel
++) {
136 pa_mix_info
*m
= streams
+ k
;
137 m
->linear
[channel
].f
= pa_sw_volume_to_linear(m
->volume
.values
[channel
]);
142 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
148 for (channel
= 0; channel
< volume
->channels
; channel
++)
149 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
153 pa_mix_info streams
[],
157 const pa_sample_spec
*spec
,
158 const pa_cvolume
*volume
,
161 pa_cvolume full_volume
;
171 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
173 for (k
= 0; k
< nstreams
; k
++)
174 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
176 switch (spec
->format
) {
178 case PA_SAMPLE_S16NE
:{
179 unsigned channel
= 0;
180 int32_t linear
[PA_CHANNELS_MAX
];
182 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
183 calc_linear_integer_volume(linear
, volume
);
185 for (d
= 0;; d
+= sizeof(int16_t)) {
189 if (PA_UNLIKELY(d
>= length
))
192 for (i
= 0; i
< nstreams
; i
++) {
193 pa_mix_info
*m
= streams
+ i
;
194 int32_t v
, cv
= m
->linear
[channel
].i
;
196 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
199 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
202 v
= *((int16_t*) m
->ptr
);
203 v
= (v
* cv
) / 0x10000;
207 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
210 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
211 sum
= (sum
* linear
[channel
]) / 0x10000;
212 *((int16_t*) data
) = (int16_t) sum
;
214 data
= (uint8_t*) data
+ sizeof(int16_t);
216 if (PA_UNLIKELY(++channel
>= spec
->channels
))
223 case PA_SAMPLE_S16RE
:{
224 unsigned channel
= 0;
225 int32_t linear
[PA_CHANNELS_MAX
];
227 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
228 calc_linear_integer_volume(linear
, volume
);
230 for (d
= 0;; d
+= sizeof(int16_t)) {
234 if (PA_UNLIKELY(d
>= length
))
237 for (i
= 0; i
< nstreams
; i
++) {
238 pa_mix_info
*m
= streams
+ i
;
239 int32_t v
, cv
= m
->linear
[channel
].i
;
241 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
244 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
247 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
248 v
= (v
* cv
) / 0x10000;
252 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
255 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
256 sum
= (sum
* linear
[channel
]) / 0x10000;
257 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
259 data
= (uint8_t*) data
+ sizeof(int16_t);
261 if (PA_UNLIKELY(++channel
>= spec
->channels
))
268 case PA_SAMPLE_S32NE
:{
269 unsigned channel
= 0;
270 int32_t linear
[PA_CHANNELS_MAX
];
272 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
273 calc_linear_integer_volume(linear
, volume
);
275 for (d
= 0;; d
+= sizeof(int32_t)) {
279 if (PA_UNLIKELY(d
>= length
))
282 for (i
= 0; i
< nstreams
; i
++) {
283 pa_mix_info
*m
= streams
+ i
;
285 int32_t cv
= m
->linear
[channel
].i
;
287 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
290 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
293 v
= *((int32_t*) m
->ptr
);
294 v
= (v
* cv
) / 0x10000;
298 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
301 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
302 sum
= (sum
* linear
[channel
]) / 0x10000;
303 *((int32_t*) data
) = (int32_t) sum
;
305 data
= (uint8_t*) data
+ sizeof(int32_t);
307 if (PA_UNLIKELY(++channel
>= spec
->channels
))
314 case PA_SAMPLE_S32RE
:{
315 unsigned channel
= 0;
316 int32_t linear
[PA_CHANNELS_MAX
];
318 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
319 calc_linear_integer_volume(linear
, volume
);
321 for (d
= 0;; d
+= sizeof(int32_t)) {
325 if (PA_UNLIKELY(d
>= length
))
328 for (i
= 0; i
< nstreams
; i
++) {
329 pa_mix_info
*m
= streams
+ i
;
331 int32_t cv
= m
->linear
[channel
].i
;
333 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
336 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
339 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
340 v
= (v
* cv
) / 0x10000;
344 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
347 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
348 sum
= (sum
* linear
[channel
]) / 0x10000;
349 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
351 data
= (uint8_t*) data
+ sizeof(int32_t);
353 if (PA_UNLIKELY(++channel
>= spec
->channels
))
361 unsigned channel
= 0;
362 int32_t linear
[PA_CHANNELS_MAX
];
364 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
365 calc_linear_integer_volume(linear
, volume
);
371 if (PA_UNLIKELY(d
>= length
))
374 for (i
= 0; i
< nstreams
; i
++) {
375 pa_mix_info
*m
= streams
+ i
;
376 int32_t v
, cv
= m
->linear
[channel
].i
;
378 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
381 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
384 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
385 v
= (v
* cv
) / 0x10000;
389 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
392 sum
= (sum
* linear
[channel
]) / 0x10000;
393 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
394 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
396 data
= (uint8_t*) data
+ 1;
398 if (PA_UNLIKELY(++channel
>= spec
->channels
))
405 case PA_SAMPLE_ULAW
: {
406 unsigned channel
= 0;
407 int32_t linear
[PA_CHANNELS_MAX
];
409 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
410 calc_linear_integer_volume(linear
, volume
);
416 if (PA_UNLIKELY(d
>= length
))
419 for (i
= 0; i
< nstreams
; i
++) {
420 pa_mix_info
*m
= streams
+ i
;
421 int32_t v
, cv
= m
->linear
[channel
].i
;
423 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
426 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
429 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
430 v
= (v
* cv
) / 0x10000;
434 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
437 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
438 sum
= (sum
* linear
[channel
]) / 0x10000;
439 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw(sum
>> 2);
441 data
= (uint8_t*) data
+ 1;
443 if (PA_UNLIKELY(++channel
>= spec
->channels
))
450 case PA_SAMPLE_ALAW
: {
451 unsigned channel
= 0;
452 int32_t linear
[PA_CHANNELS_MAX
];
454 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
455 calc_linear_integer_volume(linear
, volume
);
461 if (PA_UNLIKELY(d
>= length
))
464 for (i
= 0; i
< nstreams
; i
++) {
465 pa_mix_info
*m
= streams
+ i
;
466 int32_t v
, cv
= m
->linear
[channel
].i
;
468 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
471 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
474 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
475 v
= (v
* cv
) / 0x10000;
479 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
482 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
483 sum
= (sum
* linear
[channel
]) / 0x10000;
484 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw(sum
>> 3);
486 data
= (uint8_t*) data
+ 1;
488 if (PA_UNLIKELY(++channel
>= spec
->channels
))
495 case PA_SAMPLE_FLOAT32NE
: {
496 unsigned channel
= 0;
497 float linear
[PA_CHANNELS_MAX
];
499 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
500 calc_linear_float_volume(linear
, volume
);
502 for (d
= 0;; d
+= sizeof(float)) {
506 if (PA_UNLIKELY(d
>= length
))
509 for (i
= 0; i
< nstreams
; i
++) {
510 pa_mix_info
*m
= streams
+ i
;
511 float v
, cv
= m
->linear
[channel
].f
;
513 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
516 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
519 v
= *((float*) m
->ptr
);
524 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
527 sum
*= linear
[channel
];
528 *((float*) data
) = sum
;
530 data
= (uint8_t*) data
+ sizeof(float);
532 if (PA_UNLIKELY(++channel
>= spec
->channels
))
539 case PA_SAMPLE_FLOAT32RE
: {
540 unsigned channel
= 0;
541 float linear
[PA_CHANNELS_MAX
];
543 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
544 calc_linear_float_volume(linear
, volume
);
546 for (d
= 0;; d
+= sizeof(float)) {
550 if (PA_UNLIKELY(d
>= length
))
553 for (i
= 0; i
< nstreams
; i
++) {
554 pa_mix_info
*m
= streams
+ i
;
555 float v
, cv
= m
->linear
[channel
].f
;
557 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
560 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
563 uint32_t z
= *(uint32_t*) m
->ptr
;
564 z
= PA_UINT32_SWAP(z
);
570 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
573 sum
*= linear
[channel
];
574 *((uint32_t*) data
) = PA_UINT32_SWAP(*(uint32_t*) &sum
);
576 data
= (uint8_t*) data
+ sizeof(float);
578 if (PA_UNLIKELY(++channel
>= spec
->channels
))
586 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
587 pa_assert_not_reached();
592 for (k
= 0; k
< nstreams
; k
++)
593 pa_memblock_release(streams
[k
].chunk
.memblock
);
599 void pa_volume_memchunk(
601 const pa_sample_spec
*spec
,
602 const pa_cvolume
*volume
) {
608 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
611 if (pa_memblock_is_silence(c
->memblock
))
614 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
617 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
618 pa_silence_memchunk(c
, spec
);
622 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
624 switch (spec
->format
) {
626 case PA_SAMPLE_S16NE
: {
630 int32_t linear
[PA_CHANNELS_MAX
];
632 calc_linear_integer_volume(linear
, volume
);
634 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
638 t
= (t
* linear
[channel
]) / 0x10000;
639 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
642 if (PA_UNLIKELY(++channel
>= spec
->channels
))
648 case PA_SAMPLE_S16RE
: {
652 int32_t linear
[PA_CHANNELS_MAX
];
654 calc_linear_integer_volume(linear
, volume
);
656 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
659 t
= (int32_t)(PA_INT16_SWAP(*d
));
660 t
= (t
* linear
[channel
]) / 0x10000;
661 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
662 *d
= PA_INT16_SWAP((int16_t) t
);
664 if (PA_UNLIKELY(++channel
>= spec
->channels
))
671 case PA_SAMPLE_S32NE
: {
675 int32_t linear
[PA_CHANNELS_MAX
];
677 calc_linear_integer_volume(linear
, volume
);
679 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
683 t
= (t
* linear
[channel
]) / 0x10000;
684 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
687 if (PA_UNLIKELY(++channel
>= spec
->channels
))
693 case PA_SAMPLE_S32RE
: {
697 int32_t linear
[PA_CHANNELS_MAX
];
699 calc_linear_integer_volume(linear
, volume
);
701 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
704 t
= (int64_t)(PA_INT32_SWAP(*d
));
705 t
= (t
* linear
[channel
]) / 0x10000;
706 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
707 *d
= PA_INT32_SWAP((int32_t) t
);
709 if (PA_UNLIKELY(++channel
>= spec
->channels
))
720 int32_t linear
[PA_CHANNELS_MAX
];
722 calc_linear_integer_volume(linear
, volume
);
724 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
727 t
= (int32_t) *d
- 0x80;
728 t
= (t
* linear
[channel
]) / 0x10000;
729 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
730 *d
= (uint8_t) (t
+ 0x80);
732 if (PA_UNLIKELY(++channel
>= spec
->channels
))
738 case PA_SAMPLE_ULAW
: {
742 int32_t linear
[PA_CHANNELS_MAX
];
744 calc_linear_integer_volume(linear
, volume
);
746 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
749 t
= (int32_t) st_ulaw2linear16(*d
);
750 t
= (t
* linear
[channel
]) / 0x10000;
751 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
752 *d
= (uint8_t) st_14linear2ulaw(t
>> 2);
754 if (PA_UNLIKELY(++channel
>= spec
->channels
))
760 case PA_SAMPLE_ALAW
: {
764 int32_t linear
[PA_CHANNELS_MAX
];
766 calc_linear_integer_volume(linear
, volume
);
768 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
771 t
= (int32_t) st_alaw2linear16(*d
);
772 t
= (t
* linear
[channel
]) / 0x10000;
773 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
774 *d
= (uint8_t) st_13linear2alaw(t
>> 3);
776 if (PA_UNLIKELY(++channel
>= spec
->channels
))
782 case PA_SAMPLE_FLOAT32NE
: {
789 skip
= spec
->channels
* sizeof(float);
790 n
= c
->length
/sizeof(float)/spec
->channels
;
792 for (channel
= 0; channel
< spec
->channels
; channel
++) {
795 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
798 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
800 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
805 case PA_SAMPLE_FLOAT32RE
: {
809 float linear
[PA_CHANNELS_MAX
];
811 calc_linear_float_volume(linear
, volume
);
813 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(float); n
> 0; d
++, n
--) {
817 z
= PA_UINT32_SWAP(*d
);
819 t
*= linear
[channel
];
821 *d
= PA_UINT32_SWAP(z
);
823 if (PA_UNLIKELY(++channel
>= spec
->channels
))
832 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
833 /* If we cannot change the volume, we just don't do it */
836 pa_memblock_release(c
->memblock
);
839 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
844 fs
= pa_frame_size(ss
);
849 int pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
854 fs
= pa_frame_size(ss
);
859 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
864 pa_assert(channels
> 0);
871 for (c
= 0; c
< channels
; c
++) {
877 d
= (uint8_t*) dst
+ c
* ss
;
879 for (j
= 0; j
< n
; j
++) {
880 oil_memcpy(d
, s
, ss
);
881 s
= (uint8_t*) s
+ ss
;
882 d
= (uint8_t*) d
+ fs
;
887 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
893 pa_assert(channels
> 0);
899 for (c
= 0; c
< channels
; c
++) {
904 s
= (uint8_t*) src
+ c
* ss
;
907 for (j
= 0; j
< n
; j
++) {
908 oil_memcpy(d
, s
, ss
);
909 s
= (uint8_t*) s
+ fs
;
910 d
= (uint8_t*) d
+ ss
;
915 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
922 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
924 b
= pa_memblock_new(pool
, length
);
926 data
= pa_memblock_acquire(b
);
927 memset(data
, c
, length
);
928 pa_memblock_release(b
);
930 pa_memblock_set_is_silence(b
, TRUE
);
935 void pa_silence_cache_init(pa_silence_cache
*cache
) {
938 memset(cache
, 0, sizeof(pa_silence_cache
));
941 void pa_silence_cache_done(pa_silence_cache
*cache
) {
942 pa_sample_format_t f
;
945 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
946 if (cache
->blocks
[f
])
947 pa_memblock_unref(cache
->blocks
[f
]);
949 memset(cache
, 0, sizeof(pa_silence_cache
));
952 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
957 pa_assert(pa_sample_spec_valid(spec
));
959 if (!(b
= cache
->blocks
[spec
->format
]))
961 switch (spec
->format
) {
963 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
965 case PA_SAMPLE_S16LE
:
966 case PA_SAMPLE_S16BE
:
967 case PA_SAMPLE_S32LE
:
968 case PA_SAMPLE_S32BE
:
969 case PA_SAMPLE_FLOAT32LE
:
970 case PA_SAMPLE_FLOAT32BE
:
971 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
972 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
973 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
974 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
975 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
976 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
979 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
982 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
985 pa_assert_not_reached();
990 ret
->memblock
= pa_memblock_ref(b
);
992 l
= pa_memblock_get_length(b
);
993 if (length
> l
|| length
== 0)
996 ret
->length
= pa_frame_align(length
, spec
);
1002 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
1008 if (format
== PA_SAMPLE_FLOAT32NE
) {
1010 float minus_one
= -1.0, plus_one
= 1.0;
1011 oil_clip_f32(d
, dstr
, s
, sstr
, n
, &minus_one
, &plus_one
);
1014 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
1016 for (; n
> 0; n
--) {
1019 f
= PA_FLOAT32_SWAP(*s
);
1020 f
= PA_CLAMP_UNLIKELY(f
, -1.0, 1.0);
1021 *d
= PA_FLOAT32_SWAP(f
);
1023 s
= (const float*) ((const uint8_t*) s
+ sstr
);
1024 d
= (float*) ((uint8_t*) d
+ dstr
);