4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <liboil/liboilfuncs.h>
34 #include <liboil/liboil.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/g711.h>
40 #include "sample-util.h"
41 #include "endianmacros.h"
43 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
45 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
51 data
= pa_memblock_acquire(b
);
52 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
53 pa_memblock_release(b
);
58 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
62 pa_assert(c
->memblock
);
65 data
= pa_memblock_acquire(c
->memblock
);
66 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
67 pa_memblock_release(c
->memblock
);
72 static uint8_t silence_byte(pa_sample_format_t format
) {
80 case PA_SAMPLE_FLOAT32LE
:
81 case PA_SAMPLE_FLOAT32BE
:
88 pa_assert_not_reached();
93 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
95 pa_assert(length
> 0);
98 memset(p
, silence_byte(spec
->format
), length
);
102 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
108 for (k
= 0; k
< nstreams
; k
++) {
111 for (channel
= 0; channel
< spec
->channels
; channel
++) {
112 pa_mix_info
*m
= streams
+ k
;
113 m
->linear
[channel
].i
= (int32_t) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * 0x10000);
118 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
124 for (channel
= 0; channel
< volume
->channels
; channel
++)
125 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
128 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
134 for (k
= 0; k
< nstreams
; k
++) {
137 for (channel
= 0; channel
< spec
->channels
; channel
++) {
138 pa_mix_info
*m
= streams
+ k
;
139 m
->linear
[channel
].f
= pa_sw_volume_to_linear(m
->volume
.values
[channel
]);
144 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
150 for (channel
= 0; channel
< volume
->channels
; channel
++)
151 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
155 pa_mix_info streams
[],
159 const pa_sample_spec
*spec
,
160 const pa_cvolume
*volume
,
163 pa_cvolume full_volume
;
173 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
175 for (k
= 0; k
< nstreams
; k
++)
176 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
178 switch (spec
->format
) {
180 case PA_SAMPLE_S16NE
:{
181 unsigned channel
= 0;
182 int32_t linear
[PA_CHANNELS_MAX
];
184 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
185 calc_linear_integer_volume(linear
, volume
);
187 for (d
= 0;; d
+= sizeof(int16_t)) {
191 if (PA_UNLIKELY(d
>= length
))
194 for (i
= 0; i
< nstreams
; i
++) {
195 pa_mix_info
*m
= streams
+ i
;
196 int32_t v
, cv
= m
->linear
[channel
].i
;
198 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
201 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
204 v
= *((int16_t*) m
->ptr
);
205 v
= (v
* cv
) / 0x10000;
209 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
212 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
213 sum
= (sum
* linear
[channel
]) / 0x10000;
214 *((int16_t*) data
) = (int16_t) sum
;
216 data
= (uint8_t*) data
+ sizeof(int16_t);
218 if (PA_UNLIKELY(++channel
>= spec
->channels
))
225 case PA_SAMPLE_S16RE
:{
226 unsigned channel
= 0;
227 int32_t linear
[PA_CHANNELS_MAX
];
229 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
230 calc_linear_integer_volume(linear
, volume
);
232 for (d
= 0;; d
+= sizeof(int16_t)) {
236 if (PA_UNLIKELY(d
>= length
))
239 for (i
= 0; i
< nstreams
; i
++) {
240 pa_mix_info
*m
= streams
+ i
;
241 int32_t v
, cv
= m
->linear
[channel
].i
;
243 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
246 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
249 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
250 v
= (v
* cv
) / 0x10000;
254 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
257 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
258 sum
= (sum
* linear
[channel
]) / 0x10000;
259 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
261 data
= (uint8_t*) data
+ sizeof(int16_t);
263 if (PA_UNLIKELY(++channel
>= spec
->channels
))
270 case PA_SAMPLE_S32NE
:{
271 unsigned channel
= 0;
272 int32_t linear
[PA_CHANNELS_MAX
];
274 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
275 calc_linear_integer_volume(linear
, volume
);
277 for (d
= 0;; d
+= sizeof(int32_t)) {
281 if (PA_UNLIKELY(d
>= length
))
284 for (i
= 0; i
< nstreams
; i
++) {
285 pa_mix_info
*m
= streams
+ i
;
287 int32_t cv
= m
->linear
[channel
].i
;
289 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
292 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
295 v
= *((int32_t*) m
->ptr
);
296 v
= (v
* cv
) / 0x10000;
300 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
303 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
304 sum
= (sum
* linear
[channel
]) / 0x10000;
305 *((int32_t*) data
) = (int32_t) sum
;
307 data
= (uint8_t*) data
+ sizeof(int32_t);
309 if (PA_UNLIKELY(++channel
>= spec
->channels
))
316 case PA_SAMPLE_S32RE
:{
317 unsigned channel
= 0;
318 int32_t linear
[PA_CHANNELS_MAX
];
320 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
321 calc_linear_integer_volume(linear
, volume
);
323 for (d
= 0;; d
+= sizeof(int32_t)) {
327 if (PA_UNLIKELY(d
>= length
))
330 for (i
= 0; i
< nstreams
; i
++) {
331 pa_mix_info
*m
= streams
+ i
;
333 int32_t cv
= m
->linear
[channel
].i
;
335 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
338 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
341 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
342 v
= (v
* cv
) / 0x10000;
346 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
349 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
350 sum
= (sum
* linear
[channel
]) / 0x10000;
351 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
353 data
= (uint8_t*) data
+ sizeof(int32_t);
355 if (PA_UNLIKELY(++channel
>= spec
->channels
))
363 unsigned channel
= 0;
364 int32_t linear
[PA_CHANNELS_MAX
];
366 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
367 calc_linear_integer_volume(linear
, volume
);
373 if (PA_UNLIKELY(d
>= length
))
376 for (i
= 0; i
< nstreams
; i
++) {
377 pa_mix_info
*m
= streams
+ i
;
378 int32_t v
, cv
= m
->linear
[channel
].i
;
380 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
383 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
386 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
387 v
= (v
* cv
) / 0x10000;
391 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
394 sum
= (sum
* linear
[channel
]) / 0x10000;
395 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
396 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
398 data
= (uint8_t*) data
+ 1;
400 if (PA_UNLIKELY(++channel
>= spec
->channels
))
407 case PA_SAMPLE_ULAW
: {
408 unsigned channel
= 0;
409 int32_t linear
[PA_CHANNELS_MAX
];
411 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
412 calc_linear_integer_volume(linear
, volume
);
418 if (PA_UNLIKELY(d
>= length
))
421 for (i
= 0; i
< nstreams
; i
++) {
422 pa_mix_info
*m
= streams
+ i
;
423 int32_t v
, cv
= m
->linear
[channel
].i
;
425 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
428 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
431 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
432 v
= (v
* cv
) / 0x10000;
436 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
439 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
440 sum
= (sum
* linear
[channel
]) / 0x10000;
441 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw(sum
>> 2);
443 data
= (uint8_t*) data
+ 1;
445 if (PA_UNLIKELY(++channel
>= spec
->channels
))
452 case PA_SAMPLE_ALAW
: {
453 unsigned channel
= 0;
454 int32_t linear
[PA_CHANNELS_MAX
];
456 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
457 calc_linear_integer_volume(linear
, volume
);
463 if (PA_UNLIKELY(d
>= length
))
466 for (i
= 0; i
< nstreams
; i
++) {
467 pa_mix_info
*m
= streams
+ i
;
468 int32_t v
, cv
= m
->linear
[channel
].i
;
470 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
473 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
476 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
477 v
= (v
* cv
) / 0x10000;
481 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
484 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
485 sum
= (sum
* linear
[channel
]) / 0x10000;
486 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw(sum
>> 3);
488 data
= (uint8_t*) data
+ 1;
490 if (PA_UNLIKELY(++channel
>= spec
->channels
))
497 case PA_SAMPLE_FLOAT32NE
: {
498 unsigned channel
= 0;
499 float linear
[PA_CHANNELS_MAX
];
501 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
502 calc_linear_float_volume(linear
, volume
);
504 for (d
= 0;; d
+= sizeof(float)) {
508 if (PA_UNLIKELY(d
>= length
))
511 for (i
= 0; i
< nstreams
; i
++) {
512 pa_mix_info
*m
= streams
+ i
;
513 float v
, cv
= m
->linear
[channel
].f
;
515 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
518 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
521 v
= *((float*) m
->ptr
);
526 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
529 sum
*= linear
[channel
];
530 *((float*) data
) = sum
;
532 data
= (uint8_t*) data
+ sizeof(float);
534 if (PA_UNLIKELY(++channel
>= spec
->channels
))
541 case PA_SAMPLE_FLOAT32RE
: {
542 unsigned channel
= 0;
543 float linear
[PA_CHANNELS_MAX
];
545 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
546 calc_linear_float_volume(linear
, volume
);
548 for (d
= 0;; d
+= sizeof(float)) {
552 if (PA_UNLIKELY(d
>= length
))
555 for (i
= 0; i
< nstreams
; i
++) {
556 pa_mix_info
*m
= streams
+ i
;
557 float v
, cv
= m
->linear
[channel
].f
;
559 if (PA_UNLIKELY(d
>= m
->chunk
.length
))
562 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(!!mute
) || PA_UNLIKELY(linear
[channel
] <= 0))
565 uint32_t z
= *(uint32_t*) m
->ptr
;
566 z
= PA_UINT32_SWAP(z
);
572 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
575 sum
*= linear
[channel
];
576 *((uint32_t*) data
) = PA_UINT32_SWAP(*(uint32_t*) &sum
);
578 data
= (uint8_t*) data
+ sizeof(float);
580 if (PA_UNLIKELY(++channel
>= spec
->channels
))
588 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
589 pa_assert_not_reached();
594 for (k
= 0; k
< nstreams
; k
++)
595 pa_memblock_release(streams
[k
].chunk
.memblock
);
601 void pa_volume_memchunk(
603 const pa_sample_spec
*spec
,
604 const pa_cvolume
*volume
) {
610 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
613 if (pa_memblock_is_silence(c
->memblock
))
616 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
619 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
620 pa_silence_memchunk(c
, spec
);
624 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
626 switch (spec
->format
) {
628 case PA_SAMPLE_S16NE
: {
632 int32_t linear
[PA_CHANNELS_MAX
];
634 calc_linear_integer_volume(linear
, volume
);
636 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
640 t
= (t
* linear
[channel
]) / 0x10000;
641 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
644 if (PA_UNLIKELY(++channel
>= spec
->channels
))
650 case PA_SAMPLE_S16RE
: {
654 int32_t linear
[PA_CHANNELS_MAX
];
656 calc_linear_integer_volume(linear
, volume
);
658 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
661 t
= (int32_t)(PA_INT16_SWAP(*d
));
662 t
= (t
* linear
[channel
]) / 0x10000;
663 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
664 *d
= PA_INT16_SWAP((int16_t) t
);
666 if (PA_UNLIKELY(++channel
>= spec
->channels
))
673 case PA_SAMPLE_S32NE
: {
677 int32_t linear
[PA_CHANNELS_MAX
];
679 calc_linear_integer_volume(linear
, volume
);
681 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
685 t
= (t
* linear
[channel
]) / 0x10000;
686 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
689 if (PA_UNLIKELY(++channel
>= spec
->channels
))
695 case PA_SAMPLE_S32RE
: {
699 int32_t linear
[PA_CHANNELS_MAX
];
701 calc_linear_integer_volume(linear
, volume
);
703 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
706 t
= (int64_t)(PA_INT32_SWAP(*d
));
707 t
= (t
* linear
[channel
]) / 0x10000;
708 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
709 *d
= PA_INT32_SWAP((int32_t) t
);
711 if (PA_UNLIKELY(++channel
>= spec
->channels
))
722 int32_t linear
[PA_CHANNELS_MAX
];
724 calc_linear_integer_volume(linear
, volume
);
726 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
729 t
= (int32_t) *d
- 0x80;
730 t
= (t
* linear
[channel
]) / 0x10000;
731 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
732 *d
= (uint8_t) (t
+ 0x80);
734 if (PA_UNLIKELY(++channel
>= spec
->channels
))
740 case PA_SAMPLE_ULAW
: {
744 int32_t linear
[PA_CHANNELS_MAX
];
746 calc_linear_integer_volume(linear
, volume
);
748 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
751 t
= (int32_t) st_ulaw2linear16(*d
);
752 t
= (t
* linear
[channel
]) / 0x10000;
753 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
754 *d
= (uint8_t) st_14linear2ulaw(t
>> 2);
756 if (PA_UNLIKELY(++channel
>= spec
->channels
))
762 case PA_SAMPLE_ALAW
: {
766 int32_t linear
[PA_CHANNELS_MAX
];
768 calc_linear_integer_volume(linear
, volume
);
770 for (channel
= 0, d
= ptr
, n
= c
->length
; n
> 0; d
++, n
--) {
773 t
= (int32_t) st_alaw2linear16(*d
);
774 t
= (t
* linear
[channel
]) / 0x10000;
775 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
776 *d
= (uint8_t) st_13linear2alaw(t
>> 3);
778 if (PA_UNLIKELY(++channel
>= spec
->channels
))
784 case PA_SAMPLE_FLOAT32NE
: {
791 skip
= spec
->channels
* sizeof(float);
792 n
= c
->length
/sizeof(float)/spec
->channels
;
794 for (channel
= 0; channel
< spec
->channels
; channel
++) {
797 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
800 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
802 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
807 case PA_SAMPLE_FLOAT32RE
: {
811 float linear
[PA_CHANNELS_MAX
];
813 calc_linear_float_volume(linear
, volume
);
815 for (channel
= 0, d
= ptr
, n
= c
->length
/sizeof(float); n
> 0; d
++, n
--) {
819 z
= PA_UINT32_SWAP(*d
);
821 t
*= linear
[channel
];
823 *d
= PA_UINT32_SWAP(z
);
825 if (PA_UNLIKELY(++channel
>= spec
->channels
))
834 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
835 /* If we cannot change the volume, we just don't do it */
838 pa_memblock_release(c
->memblock
);
841 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
846 fs
= pa_frame_size(ss
);
851 int pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
856 fs
= pa_frame_size(ss
);
861 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
866 pa_assert(channels
> 0);
873 for (c
= 0; c
< channels
; c
++) {
879 d
= (uint8_t*) dst
+ c
* ss
;
881 for (j
= 0; j
< n
; j
++) {
882 oil_memcpy(d
, s
, ss
);
883 s
= (uint8_t*) s
+ ss
;
884 d
= (uint8_t*) d
+ fs
;
889 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
895 pa_assert(channels
> 0);
901 for (c
= 0; c
< channels
; c
++) {
906 s
= (uint8_t*) src
+ c
* ss
;
909 for (j
= 0; j
< n
; j
++) {
910 oil_memcpy(d
, s
, ss
);
911 s
= (uint8_t*) s
+ fs
;
912 d
= (uint8_t*) d
+ ss
;
917 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
924 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
926 b
= pa_memblock_new(pool
, length
);
928 data
= pa_memblock_acquire(b
);
929 memset(data
, c
, length
);
930 pa_memblock_release(b
);
932 pa_memblock_set_is_silence(b
, TRUE
);
937 void pa_silence_cache_init(pa_silence_cache
*cache
) {
940 memset(cache
, 0, sizeof(pa_silence_cache
));
943 void pa_silence_cache_done(pa_silence_cache
*cache
) {
944 pa_sample_format_t f
;
947 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
948 if (cache
->blocks
[f
])
949 pa_memblock_unref(cache
->blocks
[f
]);
951 memset(cache
, 0, sizeof(pa_silence_cache
));
954 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
959 pa_assert(pa_sample_spec_valid(spec
));
961 if (!(b
= cache
->blocks
[spec
->format
]))
963 switch (spec
->format
) {
965 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
967 case PA_SAMPLE_S16LE
:
968 case PA_SAMPLE_S16BE
:
969 case PA_SAMPLE_S32LE
:
970 case PA_SAMPLE_S32BE
:
971 case PA_SAMPLE_FLOAT32LE
:
972 case PA_SAMPLE_FLOAT32BE
:
973 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
974 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
975 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
976 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
977 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
978 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
981 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
984 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
987 pa_assert_not_reached();
992 ret
->memblock
= pa_memblock_ref(b
);
994 l
= pa_memblock_get_length(b
);
995 if (length
> l
|| length
== 0)
998 ret
->length
= pa_frame_align(length
, spec
);
1004 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
1010 if (format
== PA_SAMPLE_FLOAT32NE
) {
1012 float minus_one
= -1.0, plus_one
= 1.0;
1013 oil_clip_f32(d
, dstr
, s
, sstr
, n
, &minus_one
, &plus_one
);
1016 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
1018 for (; n
> 0; n
--) {
1021 f
= PA_FLOAT32_SWAP(*s
);
1022 f
= PA_CLAMP_UNLIKELY(f
, -1.0, 1.0);
1023 *d
= PA_FLOAT32_SWAP(f
);
1025 s
= (const float*) ((const uint8_t*) s
+ sstr
);
1026 d
= (float*) ((uint8_t*) d
+ dstr
);