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
34 #include <pulse/timeval.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/g711.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/endianmacros.h>
43 #include "sample-util.h"
45 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
47 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
53 data
= pa_memblock_acquire(b
);
54 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
55 pa_memblock_release(b
);
60 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
64 pa_assert(c
->memblock
);
67 data
= pa_memblock_acquire(c
->memblock
);
68 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
69 pa_memblock_release(c
->memblock
);
74 static uint8_t silence_byte(pa_sample_format_t format
) {
82 case PA_SAMPLE_FLOAT32LE
:
83 case PA_SAMPLE_FLOAT32BE
:
86 case PA_SAMPLE_S24_32LE
:
87 case PA_SAMPLE_S24_32BE
:
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 #define VOLUME_PADDING 32
109 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
110 unsigned channel
, nchannels
, padding
;
115 nchannels
= volume
->channels
;
117 for (channel
= 0; channel
< nchannels
; channel
++)
118 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
120 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
121 linear
[channel
] = linear
[padding
];
124 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
125 unsigned channel
, nchannels
, padding
;
130 nchannels
= volume
->channels
;
132 for (channel
= 0; channel
< nchannels
; channel
++)
133 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
135 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
136 linear
[channel
] = linear
[padding
];
139 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
141 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
147 calc_linear_float_volume(linear
, volume
);
149 for (k
= 0; k
< nstreams
; k
++) {
151 for (channel
= 0; channel
< spec
->channels
; channel
++) {
152 pa_mix_info
*m
= streams
+ k
;
153 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
158 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
160 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
166 calc_linear_float_volume(linear
, volume
);
168 for (k
= 0; k
< nstreams
; k
++) {
170 for (channel
= 0; channel
< spec
->channels
; channel
++) {
171 pa_mix_info
*m
= streams
+ k
;
172 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
178 pa_mix_info streams
[],
182 const pa_sample_spec
*spec
,
183 const pa_cvolume
*volume
,
186 pa_cvolume full_volume
;
197 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
199 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
200 pa_silence_memory(data
, length
, spec
);
204 for (k
= 0; k
< nstreams
; k
++)
205 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
207 for (z
= 0; z
< nstreams
; z
++)
208 if (length
> streams
[z
].chunk
.length
)
209 length
= streams
[z
].chunk
.length
;
211 end
= (uint8_t*) data
+ length
;
213 switch (spec
->format
) {
215 case PA_SAMPLE_S16NE
:{
216 unsigned channel
= 0;
218 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
224 for (i
= 0; i
< nstreams
; i
++) {
225 pa_mix_info
*m
= streams
+ i
;
226 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
228 if (PA_UNLIKELY(cv
<= 0))
231 /* Multiplying the 32bit volume factor with the
232 * 16bit sample might result in an 48bit value. We
233 * want to do without 64 bit integers and hence do
234 * the multiplication independantly for the HI and
235 * LO part of the volume. */
240 v
= *((int16_t*) m
->ptr
);
241 v
= ((v
* lo
) >> 16) + (v
* hi
);
244 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
247 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
248 *((int16_t*) data
) = (int16_t) sum
;
250 data
= (uint8_t*) data
+ sizeof(int16_t);
252 if (PA_UNLIKELY(++channel
>= spec
->channels
))
259 case PA_SAMPLE_S16RE
:{
260 unsigned channel
= 0;
262 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
268 for (i
= 0; i
< nstreams
; i
++) {
269 pa_mix_info
*m
= streams
+ i
;
270 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
272 if (PA_UNLIKELY(cv
<= 0))
278 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
279 v
= ((v
* lo
) >> 16) + (v
* hi
);
282 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
285 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
286 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
288 data
= (uint8_t*) data
+ sizeof(int16_t);
290 if (PA_UNLIKELY(++channel
>= spec
->channels
))
297 case PA_SAMPLE_S32NE
:{
298 unsigned channel
= 0;
300 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
306 for (i
= 0; i
< nstreams
; i
++) {
307 pa_mix_info
*m
= streams
+ i
;
308 int32_t cv
= m
->linear
[channel
].i
;
311 if (PA_UNLIKELY(cv
<= 0))
314 v
= *((int32_t*) m
->ptr
);
318 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
321 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
322 *((int32_t*) data
) = (int32_t) sum
;
324 data
= (uint8_t*) data
+ sizeof(int32_t);
326 if (PA_UNLIKELY(++channel
>= spec
->channels
))
333 case PA_SAMPLE_S32RE
:{
334 unsigned channel
= 0;
336 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
342 for (i
= 0; i
< nstreams
; i
++) {
343 pa_mix_info
*m
= streams
+ i
;
344 int32_t cv
= m
->linear
[channel
].i
;
347 if (PA_UNLIKELY(cv
<= 0))
350 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
354 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
357 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
358 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
360 data
= (uint8_t*) data
+ sizeof(int32_t);
362 if (PA_UNLIKELY(++channel
>= spec
->channels
))
369 case PA_SAMPLE_S24NE
: {
370 unsigned channel
= 0;
372 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
378 for (i
= 0; i
< nstreams
; i
++) {
379 pa_mix_info
*m
= streams
+ i
;
380 int32_t cv
= m
->linear
[channel
].i
;
383 if (PA_UNLIKELY(cv
<= 0))
386 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
390 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
393 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
394 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
396 data
= (uint8_t*) data
+ 3;
398 if (PA_UNLIKELY(++channel
>= spec
->channels
))
405 case PA_SAMPLE_S24RE
: {
406 unsigned channel
= 0;
408 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
414 for (i
= 0; i
< nstreams
; i
++) {
415 pa_mix_info
*m
= streams
+ i
;
416 int32_t cv
= m
->linear
[channel
].i
;
419 if (PA_UNLIKELY(cv
<= 0))
422 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
426 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
429 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
430 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
432 data
= (uint8_t*) data
+ 3;
434 if (PA_UNLIKELY(++channel
>= spec
->channels
))
441 case PA_SAMPLE_S24_32NE
: {
442 unsigned channel
= 0;
444 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
450 for (i
= 0; i
< nstreams
; i
++) {
451 pa_mix_info
*m
= streams
+ i
;
452 int32_t cv
= m
->linear
[channel
].i
;
455 if (PA_UNLIKELY(cv
<= 0))
458 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
462 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
465 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
466 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
468 data
= (uint8_t*) data
+ sizeof(uint32_t);
470 if (PA_UNLIKELY(++channel
>= spec
->channels
))
477 case PA_SAMPLE_S24_32RE
: {
478 unsigned channel
= 0;
480 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
486 for (i
= 0; i
< nstreams
; i
++) {
487 pa_mix_info
*m
= streams
+ i
;
488 int32_t cv
= m
->linear
[channel
].i
;
491 if (PA_UNLIKELY(cv
<= 0))
494 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
498 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
501 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
502 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
504 data
= (uint8_t*) data
+ sizeof(uint32_t);
506 if (PA_UNLIKELY(++channel
>= spec
->channels
))
514 unsigned channel
= 0;
516 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
522 for (i
= 0; i
< nstreams
; i
++) {
523 pa_mix_info
*m
= streams
+ i
;
524 int32_t v
, cv
= m
->linear
[channel
].i
;
526 if (PA_UNLIKELY(cv
<= 0))
529 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
533 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
536 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
537 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
539 data
= (uint8_t*) data
+ 1;
541 if (PA_UNLIKELY(++channel
>= spec
->channels
))
548 case PA_SAMPLE_ULAW
: {
549 unsigned channel
= 0;
551 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
557 for (i
= 0; i
< nstreams
; i
++) {
558 pa_mix_info
*m
= streams
+ i
;
559 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
561 if (PA_UNLIKELY(cv
<= 0))
567 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
568 v
= ((v
* lo
) >> 16) + (v
* hi
);
571 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
574 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
575 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
577 data
= (uint8_t*) data
+ 1;
579 if (PA_UNLIKELY(++channel
>= spec
->channels
))
586 case PA_SAMPLE_ALAW
: {
587 unsigned channel
= 0;
589 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
595 for (i
= 0; i
< nstreams
; i
++) {
596 pa_mix_info
*m
= streams
+ i
;
597 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
599 if (PA_UNLIKELY(cv
<= 0))
605 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
606 v
= ((v
* lo
) >> 16) + (v
* hi
);
609 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
612 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
613 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
615 data
= (uint8_t*) data
+ 1;
617 if (PA_UNLIKELY(++channel
>= spec
->channels
))
624 case PA_SAMPLE_FLOAT32NE
: {
625 unsigned channel
= 0;
627 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
633 for (i
= 0; i
< nstreams
; i
++) {
634 pa_mix_info
*m
= streams
+ i
;
635 float v
, cv
= m
->linear
[channel
].f
;
637 if (PA_UNLIKELY(cv
<= 0))
640 v
= *((float*) m
->ptr
);
644 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
647 *((float*) data
) = sum
;
649 data
= (uint8_t*) data
+ sizeof(float);
651 if (PA_UNLIKELY(++channel
>= spec
->channels
))
658 case PA_SAMPLE_FLOAT32RE
: {
659 unsigned channel
= 0;
661 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
667 for (i
= 0; i
< nstreams
; i
++) {
668 pa_mix_info
*m
= streams
+ i
;
669 float v
, cv
= m
->linear
[channel
].f
;
671 if (PA_UNLIKELY(cv
<= 0))
674 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
678 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
681 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
683 data
= (uint8_t*) data
+ sizeof(float);
685 if (PA_UNLIKELY(++channel
>= spec
->channels
))
693 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
694 pa_assert_not_reached();
697 for (k
= 0; k
< nstreams
; k
++)
698 pa_memblock_release(streams
[k
].chunk
.memblock
);
708 typedef void (*pa_calc_volume_func_t
) (void *volumes
, const pa_cvolume
*volume
);
710 static const pa_calc_volume_func_t calc_volume_table
[] = {
711 [PA_SAMPLE_U8
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
712 [PA_SAMPLE_ALAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
713 [PA_SAMPLE_ULAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
714 [PA_SAMPLE_S16LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
715 [PA_SAMPLE_S16BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
716 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
717 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
718 [PA_SAMPLE_S32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
719 [PA_SAMPLE_S32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
720 [PA_SAMPLE_S24LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
721 [PA_SAMPLE_S24BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
722 [PA_SAMPLE_S24_32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
723 [PA_SAMPLE_S24_32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
726 void pa_volume_memchunk(
728 const pa_sample_spec
*spec
,
729 const pa_cvolume
*volume
) {
732 volume_val linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
733 pa_do_volume_func_t do_volume
;
737 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
740 if (pa_memblock_is_silence(c
->memblock
))
743 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
746 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
747 pa_silence_memchunk(c
, spec
);
751 if (spec
->format
< 0 || spec
->format
> PA_SAMPLE_MAX
) {
752 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
756 do_volume
= pa_get_volume_func(spec
->format
);
757 pa_assert(do_volume
);
759 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
761 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
763 do_volume (ptr
, (void *)linear
, spec
->channels
, c
->length
);
765 pa_memblock_release(c
->memblock
);
768 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
773 fs
= pa_frame_size(ss
);
778 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
783 fs
= pa_frame_size(ss
);
788 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
793 pa_assert(channels
> 0);
800 for (c
= 0; c
< channels
; c
++) {
806 d
= (uint8_t*) dst
+ c
* ss
;
808 for (j
= 0; j
< n
; j
++) {
809 memcpy(d
, s
, (int) ss
);
810 s
= (uint8_t*) s
+ ss
;
811 d
= (uint8_t*) d
+ fs
;
816 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
822 pa_assert(channels
> 0);
828 for (c
= 0; c
< channels
; c
++) {
833 s
= (uint8_t*) src
+ c
* ss
;
836 for (j
= 0; j
< n
; j
++) {
837 memcpy(d
, s
, (int) ss
);
838 s
= (uint8_t*) s
+ fs
;
839 d
= (uint8_t*) d
+ ss
;
844 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
851 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
853 b
= pa_memblock_new(pool
, length
);
855 data
= pa_memblock_acquire(b
);
856 memset(data
, c
, length
);
857 pa_memblock_release(b
);
859 pa_memblock_set_is_silence(b
, TRUE
);
864 void pa_silence_cache_init(pa_silence_cache
*cache
) {
867 memset(cache
, 0, sizeof(pa_silence_cache
));
870 void pa_silence_cache_done(pa_silence_cache
*cache
) {
871 pa_sample_format_t f
;
874 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
875 if (cache
->blocks
[f
])
876 pa_memblock_unref(cache
->blocks
[f
]);
878 memset(cache
, 0, sizeof(pa_silence_cache
));
881 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
886 pa_assert(pa_sample_spec_valid(spec
));
888 if (!(b
= cache
->blocks
[spec
->format
]))
890 switch (spec
->format
) {
892 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
894 case PA_SAMPLE_S16LE
:
895 case PA_SAMPLE_S16BE
:
896 case PA_SAMPLE_S32LE
:
897 case PA_SAMPLE_S32BE
:
898 case PA_SAMPLE_S24LE
:
899 case PA_SAMPLE_S24BE
:
900 case PA_SAMPLE_S24_32LE
:
901 case PA_SAMPLE_S24_32BE
:
902 case PA_SAMPLE_FLOAT32LE
:
903 case PA_SAMPLE_FLOAT32BE
:
904 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
905 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
906 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
907 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
908 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
909 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
910 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
911 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
912 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
913 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
916 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
919 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
922 pa_assert_not_reached();
927 ret
->memblock
= pa_memblock_ref(b
);
929 l
= pa_memblock_get_length(b
);
930 if (length
> l
|| length
== 0)
933 ret
->length
= pa_frame_align(length
, spec
);
939 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
945 if (format
== PA_SAMPLE_FLOAT32NE
) {
950 *d
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
952 s
= (const float*) ((const uint8_t*) s
+ sstr
);
953 d
= (float*) ((uint8_t*) d
+ dstr
);
956 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
961 f
= PA_FLOAT32_SWAP(*s
);
962 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
963 *d
= PA_FLOAT32_SWAP(f
);
965 s
= (const float*) ((const uint8_t*) s
+ sstr
);
966 d
= (float*) ((uint8_t*) d
+ dstr
);
971 /* Similar to pa_bytes_to_usec() but rounds up, not down */
973 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
979 fs
= pa_frame_size(spec
);
980 length
= (length
+ fs
- 1) / fs
;
982 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
984 return (usec
+ spec
->rate
- 1) / spec
->rate
;
987 /* Similar to pa_usec_to_bytes() but rounds up, not down */
989 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
993 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
995 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
997 u
*= pa_frame_size(spec
);
1002 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1009 /* Only for debugging purposes */
1011 f
= pa_fopen_cloexec(fn
, "a");
1014 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1018 p
= pa_memblock_acquire(c
->memblock
);
1020 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1021 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1023 pa_memblock_release(c
->memblock
);
1028 static void calc_sine(float *f
, size_t l
, double freq
) {
1033 for (i
= 0; i
< l
; i
++)
1034 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1037 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1042 pa_memchunk_reset(c
);
1044 gcd
= pa_gcd(rate
, freq
);
1047 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1053 c
->length
= l
* sizeof(float);
1054 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1056 p
= pa_memblock_acquire(c
->memblock
);
1057 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1058 pa_memblock_release(c
->memblock
);
1061 size_t pa_convert_size(size_t size
, const pa_sample_spec
*from
, const pa_sample_spec
*to
) {
1067 usec
= pa_bytes_to_usec_round_up(size
, from
);
1068 return pa_usec_to_bytes_round_up(usec
, to
);