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
33 #include <pulse/timeval.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/core-error.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/g711.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/endianmacros.h>
42 #include "sample-util.h"
44 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
46 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
52 data
= pa_memblock_acquire(b
);
53 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
54 pa_memblock_release(b
);
59 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
63 pa_assert(c
->memblock
);
66 data
= pa_memblock_acquire(c
->memblock
);
67 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
68 pa_memblock_release(c
->memblock
);
73 static uint8_t silence_byte(pa_sample_format_t format
) {
81 case PA_SAMPLE_FLOAT32LE
:
82 case PA_SAMPLE_FLOAT32BE
:
85 case PA_SAMPLE_S24_32LE
:
86 case PA_SAMPLE_S24_32BE
:
93 pa_assert_not_reached();
97 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
99 pa_assert(length
> 0);
102 memset(p
, silence_byte(spec
->format
), length
);
106 #define VOLUME_PADDING 32
108 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
109 unsigned channel
, nchannels
, padding
;
114 nchannels
= volume
->channels
;
116 for (channel
= 0; channel
< nchannels
; channel
++)
117 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
119 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
120 linear
[channel
] = linear
[padding
];
123 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
124 unsigned channel
, nchannels
, padding
;
129 nchannels
= volume
->channels
;
131 for (channel
= 0; channel
< nchannels
; channel
++)
132 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
134 for (padding
= 0; padding
< VOLUME_PADDING
; padding
++, channel
++)
135 linear
[channel
] = linear
[padding
];
138 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
140 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
146 calc_linear_float_volume(linear
, volume
);
148 for (k
= 0; k
< nstreams
; k
++) {
150 for (channel
= 0; channel
< spec
->channels
; channel
++) {
151 pa_mix_info
*m
= streams
+ k
;
152 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
157 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
159 float linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
165 calc_linear_float_volume(linear
, volume
);
167 for (k
= 0; k
< nstreams
; k
++) {
169 for (channel
= 0; channel
< spec
->channels
; channel
++) {
170 pa_mix_info
*m
= streams
+ k
;
171 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
177 pa_mix_info streams
[],
181 const pa_sample_spec
*spec
,
182 const pa_cvolume
*volume
,
185 pa_cvolume full_volume
;
196 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
198 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
199 pa_silence_memory(data
, length
, spec
);
203 for (k
= 0; k
< nstreams
; k
++)
204 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
206 for (z
= 0; z
< nstreams
; z
++)
207 if (length
> streams
[z
].chunk
.length
)
208 length
= streams
[z
].chunk
.length
;
210 end
= (uint8_t*) data
+ length
;
212 switch (spec
->format
) {
214 case PA_SAMPLE_S16NE
:{
215 unsigned channel
= 0;
217 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
223 for (i
= 0; i
< nstreams
; i
++) {
224 pa_mix_info
*m
= streams
+ i
;
225 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
227 if (PA_UNLIKELY(cv
<= 0))
230 /* Multiplying the 32bit volume factor with the
231 * 16bit sample might result in an 48bit value. We
232 * want to do without 64 bit integers and hence do
233 * the multiplication independantly for the HI and
234 * LO part of the volume. */
239 v
= *((int16_t*) m
->ptr
);
240 v
= ((v
* lo
) >> 16) + (v
* hi
);
243 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
246 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
247 *((int16_t*) data
) = (int16_t) sum
;
249 data
= (uint8_t*) data
+ sizeof(int16_t);
251 if (PA_UNLIKELY(++channel
>= spec
->channels
))
258 case PA_SAMPLE_S16RE
:{
259 unsigned channel
= 0;
261 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
267 for (i
= 0; i
< nstreams
; i
++) {
268 pa_mix_info
*m
= streams
+ i
;
269 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
271 if (PA_UNLIKELY(cv
<= 0))
277 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
278 v
= ((v
* lo
) >> 16) + (v
* hi
);
281 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
284 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
285 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
287 data
= (uint8_t*) data
+ sizeof(int16_t);
289 if (PA_UNLIKELY(++channel
>= spec
->channels
))
296 case PA_SAMPLE_S32NE
:{
297 unsigned channel
= 0;
299 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
305 for (i
= 0; i
< nstreams
; i
++) {
306 pa_mix_info
*m
= streams
+ i
;
307 int32_t cv
= m
->linear
[channel
].i
;
310 if (PA_UNLIKELY(cv
<= 0))
313 v
= *((int32_t*) m
->ptr
);
317 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
320 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
321 *((int32_t*) data
) = (int32_t) sum
;
323 data
= (uint8_t*) data
+ sizeof(int32_t);
325 if (PA_UNLIKELY(++channel
>= spec
->channels
))
332 case PA_SAMPLE_S32RE
:{
333 unsigned channel
= 0;
335 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
341 for (i
= 0; i
< nstreams
; i
++) {
342 pa_mix_info
*m
= streams
+ i
;
343 int32_t cv
= m
->linear
[channel
].i
;
346 if (PA_UNLIKELY(cv
<= 0))
349 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
353 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
356 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
357 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
359 data
= (uint8_t*) data
+ sizeof(int32_t);
361 if (PA_UNLIKELY(++channel
>= spec
->channels
))
368 case PA_SAMPLE_S24NE
: {
369 unsigned channel
= 0;
371 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
377 for (i
= 0; i
< nstreams
; i
++) {
378 pa_mix_info
*m
= streams
+ i
;
379 int32_t cv
= m
->linear
[channel
].i
;
382 if (PA_UNLIKELY(cv
<= 0))
385 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
389 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
392 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
393 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
395 data
= (uint8_t*) data
+ 3;
397 if (PA_UNLIKELY(++channel
>= spec
->channels
))
404 case PA_SAMPLE_S24RE
: {
405 unsigned channel
= 0;
407 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
413 for (i
= 0; i
< nstreams
; i
++) {
414 pa_mix_info
*m
= streams
+ i
;
415 int32_t cv
= m
->linear
[channel
].i
;
418 if (PA_UNLIKELY(cv
<= 0))
421 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
425 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
428 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
429 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
431 data
= (uint8_t*) data
+ 3;
433 if (PA_UNLIKELY(++channel
>= spec
->channels
))
440 case PA_SAMPLE_S24_32NE
: {
441 unsigned channel
= 0;
443 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
449 for (i
= 0; i
< nstreams
; i
++) {
450 pa_mix_info
*m
= streams
+ i
;
451 int32_t cv
= m
->linear
[channel
].i
;
454 if (PA_UNLIKELY(cv
<= 0))
457 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
461 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
464 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
465 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
467 data
= (uint8_t*) data
+ sizeof(uint32_t);
469 if (PA_UNLIKELY(++channel
>= spec
->channels
))
476 case PA_SAMPLE_S24_32RE
: {
477 unsigned channel
= 0;
479 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
485 for (i
= 0; i
< nstreams
; i
++) {
486 pa_mix_info
*m
= streams
+ i
;
487 int32_t cv
= m
->linear
[channel
].i
;
490 if (PA_UNLIKELY(cv
<= 0))
493 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
497 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
500 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
501 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
503 data
= (uint8_t*) data
+ sizeof(uint32_t);
505 if (PA_UNLIKELY(++channel
>= spec
->channels
))
513 unsigned channel
= 0;
515 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
521 for (i
= 0; i
< nstreams
; i
++) {
522 pa_mix_info
*m
= streams
+ i
;
523 int32_t v
, cv
= m
->linear
[channel
].i
;
525 if (PA_UNLIKELY(cv
<= 0))
528 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
532 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
535 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
536 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
538 data
= (uint8_t*) data
+ 1;
540 if (PA_UNLIKELY(++channel
>= spec
->channels
))
547 case PA_SAMPLE_ULAW
: {
548 unsigned channel
= 0;
550 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
556 for (i
= 0; i
< nstreams
; i
++) {
557 pa_mix_info
*m
= streams
+ i
;
558 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
560 if (PA_UNLIKELY(cv
<= 0))
566 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
567 v
= ((v
* lo
) >> 16) + (v
* hi
);
570 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
573 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
574 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
576 data
= (uint8_t*) data
+ 1;
578 if (PA_UNLIKELY(++channel
>= spec
->channels
))
585 case PA_SAMPLE_ALAW
: {
586 unsigned channel
= 0;
588 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
594 for (i
= 0; i
< nstreams
; i
++) {
595 pa_mix_info
*m
= streams
+ i
;
596 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
598 if (PA_UNLIKELY(cv
<= 0))
604 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
605 v
= ((v
* lo
) >> 16) + (v
* hi
);
608 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
611 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
612 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
614 data
= (uint8_t*) data
+ 1;
616 if (PA_UNLIKELY(++channel
>= spec
->channels
))
623 case PA_SAMPLE_FLOAT32NE
: {
624 unsigned channel
= 0;
626 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
632 for (i
= 0; i
< nstreams
; i
++) {
633 pa_mix_info
*m
= streams
+ i
;
634 float v
, cv
= m
->linear
[channel
].f
;
636 if (PA_UNLIKELY(cv
<= 0))
639 v
= *((float*) m
->ptr
);
643 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
646 *((float*) data
) = sum
;
648 data
= (uint8_t*) data
+ sizeof(float);
650 if (PA_UNLIKELY(++channel
>= spec
->channels
))
657 case PA_SAMPLE_FLOAT32RE
: {
658 unsigned channel
= 0;
660 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
666 for (i
= 0; i
< nstreams
; i
++) {
667 pa_mix_info
*m
= streams
+ i
;
668 float v
, cv
= m
->linear
[channel
].f
;
670 if (PA_UNLIKELY(cv
<= 0))
673 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
677 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
680 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
682 data
= (uint8_t*) data
+ sizeof(float);
684 if (PA_UNLIKELY(++channel
>= spec
->channels
))
692 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
693 pa_assert_not_reached();
696 for (k
= 0; k
< nstreams
; k
++)
697 pa_memblock_release(streams
[k
].chunk
.memblock
);
707 typedef void (*pa_calc_volume_func_t
) (void *volumes
, const pa_cvolume
*volume
);
709 static const pa_calc_volume_func_t calc_volume_table
[] = {
710 [PA_SAMPLE_U8
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
711 [PA_SAMPLE_ALAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
712 [PA_SAMPLE_ULAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
713 [PA_SAMPLE_S16LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
714 [PA_SAMPLE_S16BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
715 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
716 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
717 [PA_SAMPLE_S32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
718 [PA_SAMPLE_S32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
719 [PA_SAMPLE_S24LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
720 [PA_SAMPLE_S24BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
721 [PA_SAMPLE_S24_32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
722 [PA_SAMPLE_S24_32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
725 void pa_volume_memchunk(
727 const pa_sample_spec
*spec
,
728 const pa_cvolume
*volume
) {
731 volume_val linear
[PA_CHANNELS_MAX
+ VOLUME_PADDING
];
732 pa_do_volume_func_t do_volume
;
736 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
739 if (pa_memblock_is_silence(c
->memblock
))
742 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
745 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
746 pa_silence_memchunk(c
, spec
);
750 if (spec
->format
< 0 || spec
->format
> PA_SAMPLE_MAX
) {
751 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
755 do_volume
= pa_get_volume_func(spec
->format
);
756 pa_assert(do_volume
);
758 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
760 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
762 do_volume (ptr
, (void *)linear
, spec
->channels
, c
->length
);
764 pa_memblock_release(c
->memblock
);
767 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
772 fs
= pa_frame_size(ss
);
777 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
782 fs
= pa_frame_size(ss
);
787 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
792 pa_assert(channels
> 0);
799 for (c
= 0; c
< channels
; c
++) {
805 d
= (uint8_t*) dst
+ c
* ss
;
807 for (j
= 0; j
< n
; j
++) {
808 memcpy(d
, s
, (int) ss
);
809 s
= (uint8_t*) s
+ ss
;
810 d
= (uint8_t*) d
+ fs
;
815 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
821 pa_assert(channels
> 0);
827 for (c
= 0; c
< channels
; c
++) {
832 s
= (uint8_t*) src
+ c
* ss
;
835 for (j
= 0; j
< n
; j
++) {
836 memcpy(d
, s
, (int) ss
);
837 s
= (uint8_t*) s
+ fs
;
838 d
= (uint8_t*) d
+ ss
;
843 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
850 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
852 b
= pa_memblock_new(pool
, length
);
854 data
= pa_memblock_acquire(b
);
855 memset(data
, c
, length
);
856 pa_memblock_release(b
);
858 pa_memblock_set_is_silence(b
, TRUE
);
863 void pa_silence_cache_init(pa_silence_cache
*cache
) {
866 memset(cache
, 0, sizeof(pa_silence_cache
));
869 void pa_silence_cache_done(pa_silence_cache
*cache
) {
870 pa_sample_format_t f
;
873 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
874 if (cache
->blocks
[f
])
875 pa_memblock_unref(cache
->blocks
[f
]);
877 memset(cache
, 0, sizeof(pa_silence_cache
));
880 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
885 pa_assert(pa_sample_spec_valid(spec
));
887 if (!(b
= cache
->blocks
[spec
->format
]))
889 switch (spec
->format
) {
891 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
893 case PA_SAMPLE_S16LE
:
894 case PA_SAMPLE_S16BE
:
895 case PA_SAMPLE_S32LE
:
896 case PA_SAMPLE_S32BE
:
897 case PA_SAMPLE_S24LE
:
898 case PA_SAMPLE_S24BE
:
899 case PA_SAMPLE_S24_32LE
:
900 case PA_SAMPLE_S24_32BE
:
901 case PA_SAMPLE_FLOAT32LE
:
902 case PA_SAMPLE_FLOAT32BE
:
903 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
904 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
905 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
906 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
907 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
908 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
909 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
910 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
911 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
912 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
915 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
918 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
921 pa_assert_not_reached();
926 ret
->memblock
= pa_memblock_ref(b
);
928 l
= pa_memblock_get_length(b
);
929 if (length
> l
|| length
== 0)
932 ret
->length
= pa_frame_align(length
, spec
);
938 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
944 if (format
== PA_SAMPLE_FLOAT32NE
) {
949 *d
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
951 s
= (const float*) ((const uint8_t*) s
+ sstr
);
952 d
= (float*) ((uint8_t*) d
+ dstr
);
955 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
960 f
= PA_FLOAT32_SWAP(*s
);
961 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
962 *d
= PA_FLOAT32_SWAP(f
);
964 s
= (const float*) ((const uint8_t*) s
+ sstr
);
965 d
= (float*) ((uint8_t*) d
+ dstr
);
970 /* Similar to pa_bytes_to_usec() but rounds up, not down */
972 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
978 fs
= pa_frame_size(spec
);
979 length
= (length
+ fs
- 1) / fs
;
981 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
983 return (usec
+ spec
->rate
- 1) / spec
->rate
;
986 /* Similar to pa_usec_to_bytes() but rounds up, not down */
988 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
992 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
994 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
996 u
*= pa_frame_size(spec
);
1001 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1008 /* Only for debugging purposes */
1010 f
= pa_fopen_cloexec(fn
, "a");
1013 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1017 p
= pa_memblock_acquire(c
->memblock
);
1019 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1020 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1022 pa_memblock_release(c
->memblock
);
1027 static void calc_sine(float *f
, size_t l
, double freq
) {
1032 for (i
= 0; i
< l
; i
++)
1033 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1036 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1041 pa_memchunk_reset(c
);
1043 gcd
= pa_gcd(rate
, freq
);
1046 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1052 c
->length
= l
* sizeof(float);
1053 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1055 p
= pa_memblock_acquire(c
->memblock
);
1056 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1057 pa_memblock_release(c
->memblock
);
1060 size_t pa_convert_size(size_t size
, const pa_sample_spec
*from
, const pa_sample_spec
*to
) {
1066 usec
= pa_bytes_to_usec_round_up(size
, from
);
1067 return pa_usec_to_bytes_round_up(usec
, to
);