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>
41 #include "sample-util.h"
42 #include "endianmacros.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 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
112 for (channel
= 0; channel
< volume
->channels
; channel
++)
113 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
116 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
122 for (channel
= 0; channel
< volume
->channels
; channel
++)
123 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
126 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
128 float linear
[PA_CHANNELS_MAX
];
134 calc_linear_float_volume(linear
, volume
);
136 for (k
= 0; k
< nstreams
; k
++) {
138 for (channel
= 0; channel
< spec
->channels
; channel
++) {
139 pa_mix_info
*m
= streams
+ k
;
140 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
145 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
147 float linear
[PA_CHANNELS_MAX
];
153 calc_linear_float_volume(linear
, volume
);
155 for (k
= 0; k
< nstreams
; k
++) {
157 for (channel
= 0; channel
< spec
->channels
; channel
++) {
158 pa_mix_info
*m
= streams
+ k
;
159 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
165 pa_mix_info streams
[],
169 const pa_sample_spec
*spec
,
170 const pa_cvolume
*volume
,
173 pa_cvolume full_volume
;
184 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
186 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
187 pa_silence_memory(data
, length
, spec
);
191 for (k
= 0; k
< nstreams
; k
++)
192 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
194 for (z
= 0; z
< nstreams
; z
++)
195 if (length
> streams
[z
].chunk
.length
)
196 length
= streams
[z
].chunk
.length
;
198 end
= (uint8_t*) data
+ length
;
200 switch (spec
->format
) {
202 case PA_SAMPLE_S16NE
:{
203 unsigned channel
= 0;
205 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
211 for (i
= 0; i
< nstreams
; i
++) {
212 pa_mix_info
*m
= streams
+ i
;
213 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
215 if (PA_UNLIKELY(cv
<= 0))
218 /* Multiplying the 32bit volume factor with the
219 * 16bit sample might result in an 48bit value. We
220 * want to do without 64 bit integers and hence do
221 * the multiplication independantly for the HI and
222 * LO part of the volume. */
227 v
= *((int16_t*) m
->ptr
);
228 v
= ((v
* lo
) >> 16) + (v
* hi
);
231 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
234 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
235 *((int16_t*) data
) = (int16_t) sum
;
237 data
= (uint8_t*) data
+ sizeof(int16_t);
239 if (PA_UNLIKELY(++channel
>= spec
->channels
))
246 case PA_SAMPLE_S16RE
:{
247 unsigned channel
= 0;
249 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
255 for (i
= 0; i
< nstreams
; i
++) {
256 pa_mix_info
*m
= streams
+ i
;
257 int32_t v
, lo
, hi
, cv
= m
->linear
[channel
].i
;
259 if (PA_UNLIKELY(cv
<= 0))
265 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
266 v
= ((v
* lo
) >> 16) + (v
* hi
);
269 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
272 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
273 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
275 data
= (uint8_t*) data
+ sizeof(int16_t);
277 if (PA_UNLIKELY(++channel
>= spec
->channels
))
284 case PA_SAMPLE_S32NE
:{
285 unsigned channel
= 0;
287 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
293 for (i
= 0; i
< nstreams
; i
++) {
294 pa_mix_info
*m
= streams
+ i
;
295 int32_t cv
= m
->linear
[channel
].i
;
298 if (PA_UNLIKELY(cv
<= 0))
301 v
= *((int32_t*) m
->ptr
);
305 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
308 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
309 *((int32_t*) data
) = (int32_t) sum
;
311 data
= (uint8_t*) data
+ sizeof(int32_t);
313 if (PA_UNLIKELY(++channel
>= spec
->channels
))
320 case PA_SAMPLE_S32RE
:{
321 unsigned channel
= 0;
323 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
329 for (i
= 0; i
< nstreams
; i
++) {
330 pa_mix_info
*m
= streams
+ i
;
331 int32_t cv
= m
->linear
[channel
].i
;
334 if (PA_UNLIKELY(cv
<= 0))
337 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
341 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
344 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
345 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
347 data
= (uint8_t*) data
+ sizeof(int32_t);
349 if (PA_UNLIKELY(++channel
>= spec
->channels
))
356 case PA_SAMPLE_S24NE
: {
357 unsigned channel
= 0;
359 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
365 for (i
= 0; i
< nstreams
; i
++) {
366 pa_mix_info
*m
= streams
+ i
;
367 int32_t cv
= m
->linear
[channel
].i
;
370 if (PA_UNLIKELY(cv
<= 0))
373 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
377 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
380 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
381 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
383 data
= (uint8_t*) data
+ 3;
385 if (PA_UNLIKELY(++channel
>= spec
->channels
))
392 case PA_SAMPLE_S24RE
: {
393 unsigned channel
= 0;
395 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
401 for (i
= 0; i
< nstreams
; i
++) {
402 pa_mix_info
*m
= streams
+ i
;
403 int32_t cv
= m
->linear
[channel
].i
;
406 if (PA_UNLIKELY(cv
<= 0))
409 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
413 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
416 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
417 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
419 data
= (uint8_t*) data
+ 3;
421 if (PA_UNLIKELY(++channel
>= spec
->channels
))
428 case PA_SAMPLE_S24_32NE
: {
429 unsigned channel
= 0;
431 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
437 for (i
= 0; i
< nstreams
; i
++) {
438 pa_mix_info
*m
= streams
+ i
;
439 int32_t cv
= m
->linear
[channel
].i
;
442 if (PA_UNLIKELY(cv
<= 0))
445 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
449 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
452 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
453 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
455 data
= (uint8_t*) data
+ sizeof(uint32_t);
457 if (PA_UNLIKELY(++channel
>= spec
->channels
))
464 case PA_SAMPLE_S24_32RE
: {
465 unsigned channel
= 0;
467 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
473 for (i
= 0; i
< nstreams
; i
++) {
474 pa_mix_info
*m
= streams
+ i
;
475 int32_t cv
= m
->linear
[channel
].i
;
478 if (PA_UNLIKELY(cv
<= 0))
481 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
485 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
488 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
489 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
491 data
= (uint8_t*) data
+ sizeof(uint32_t);
493 if (PA_UNLIKELY(++channel
>= spec
->channels
))
501 unsigned channel
= 0;
503 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
509 for (i
= 0; i
< nstreams
; i
++) {
510 pa_mix_info
*m
= streams
+ i
;
511 int32_t v
, cv
= m
->linear
[channel
].i
;
513 if (PA_UNLIKELY(cv
<= 0))
516 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
520 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
523 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
524 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
526 data
= (uint8_t*) data
+ 1;
528 if (PA_UNLIKELY(++channel
>= spec
->channels
))
535 case PA_SAMPLE_ULAW
: {
536 unsigned channel
= 0;
538 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
544 for (i
= 0; i
< nstreams
; i
++) {
545 pa_mix_info
*m
= streams
+ i
;
546 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
548 if (PA_UNLIKELY(cv
<= 0))
554 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
555 v
= ((v
* lo
) >> 16) + (v
* hi
);
558 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
561 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
562 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
564 data
= (uint8_t*) data
+ 1;
566 if (PA_UNLIKELY(++channel
>= spec
->channels
))
573 case PA_SAMPLE_ALAW
: {
574 unsigned channel
= 0;
576 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
582 for (i
= 0; i
< nstreams
; i
++) {
583 pa_mix_info
*m
= streams
+ i
;
584 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
586 if (PA_UNLIKELY(cv
<= 0))
592 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
593 v
= ((v
* lo
) >> 16) + (v
* hi
);
596 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
599 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
600 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
602 data
= (uint8_t*) data
+ 1;
604 if (PA_UNLIKELY(++channel
>= spec
->channels
))
611 case PA_SAMPLE_FLOAT32NE
: {
612 unsigned channel
= 0;
614 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
620 for (i
= 0; i
< nstreams
; i
++) {
621 pa_mix_info
*m
= streams
+ i
;
622 float v
, cv
= m
->linear
[channel
].f
;
624 if (PA_UNLIKELY(cv
<= 0))
627 v
= *((float*) m
->ptr
);
631 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
634 *((float*) data
) = sum
;
636 data
= (uint8_t*) data
+ sizeof(float);
638 if (PA_UNLIKELY(++channel
>= spec
->channels
))
645 case PA_SAMPLE_FLOAT32RE
: {
646 unsigned channel
= 0;
648 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
654 for (i
= 0; i
< nstreams
; i
++) {
655 pa_mix_info
*m
= streams
+ i
;
656 float v
, cv
= m
->linear
[channel
].f
;
658 if (PA_UNLIKELY(cv
<= 0))
661 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
665 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
668 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
670 data
= (uint8_t*) data
+ sizeof(float);
672 if (PA_UNLIKELY(++channel
>= spec
->channels
))
680 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
681 pa_assert_not_reached();
684 for (k
= 0; k
< nstreams
; k
++)
685 pa_memblock_release(streams
[k
].chunk
.memblock
);
695 typedef void (*pa_calc_volume_func_t
) (void *volumes
, const pa_cvolume
*volume
);
697 static const pa_calc_volume_func_t calc_volume_table
[] = {
698 [PA_SAMPLE_U8
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
699 [PA_SAMPLE_ALAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
700 [PA_SAMPLE_ULAW
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
701 [PA_SAMPLE_S16LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
702 [PA_SAMPLE_S16BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
703 [PA_SAMPLE_FLOAT32LE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
704 [PA_SAMPLE_FLOAT32BE
] = (pa_calc_volume_func_t
) calc_linear_float_volume
,
705 [PA_SAMPLE_S32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
706 [PA_SAMPLE_S32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
707 [PA_SAMPLE_S24LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
708 [PA_SAMPLE_S24BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
709 [PA_SAMPLE_S24_32LE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
,
710 [PA_SAMPLE_S24_32BE
] = (pa_calc_volume_func_t
) calc_linear_integer_volume
713 void pa_volume_memchunk(
715 const pa_sample_spec
*spec
,
716 const pa_cvolume
*volume
) {
719 volume_val linear
[PA_CHANNELS_MAX
];
720 pa_do_volume_func_t do_volume
;
724 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
727 if (pa_memblock_is_silence(c
->memblock
))
730 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
733 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
734 pa_silence_memchunk(c
, spec
);
738 if (spec
->format
< 0 || spec
->format
> PA_SAMPLE_MAX
) {
739 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
743 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
745 do_volume
= pa_get_volume_func (spec
->format
);
746 pa_assert(do_volume
);
748 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
749 do_volume (ptr
, (void *)linear
, spec
->channels
, c
->length
);
751 pa_memblock_release(c
->memblock
);
754 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
759 fs
= pa_frame_size(ss
);
764 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
769 fs
= pa_frame_size(ss
);
774 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
779 pa_assert(channels
> 0);
786 for (c
= 0; c
< channels
; c
++) {
792 d
= (uint8_t*) dst
+ c
* ss
;
794 for (j
= 0; j
< n
; j
++) {
795 memcpy(d
, s
, (int) ss
);
796 s
= (uint8_t*) s
+ ss
;
797 d
= (uint8_t*) d
+ fs
;
802 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
808 pa_assert(channels
> 0);
814 for (c
= 0; c
< channels
; c
++) {
819 s
= (uint8_t*) src
+ c
* ss
;
822 for (j
= 0; j
< n
; j
++) {
823 memcpy(d
, s
, (int) ss
);
824 s
= (uint8_t*) s
+ fs
;
825 d
= (uint8_t*) d
+ ss
;
830 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
837 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
839 b
= pa_memblock_new(pool
, length
);
841 data
= pa_memblock_acquire(b
);
842 memset(data
, c
, length
);
843 pa_memblock_release(b
);
845 pa_memblock_set_is_silence(b
, TRUE
);
850 void pa_silence_cache_init(pa_silence_cache
*cache
) {
853 memset(cache
, 0, sizeof(pa_silence_cache
));
856 void pa_silence_cache_done(pa_silence_cache
*cache
) {
857 pa_sample_format_t f
;
860 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
861 if (cache
->blocks
[f
])
862 pa_memblock_unref(cache
->blocks
[f
]);
864 memset(cache
, 0, sizeof(pa_silence_cache
));
867 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
872 pa_assert(pa_sample_spec_valid(spec
));
874 if (!(b
= cache
->blocks
[spec
->format
]))
876 switch (spec
->format
) {
878 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
880 case PA_SAMPLE_S16LE
:
881 case PA_SAMPLE_S16BE
:
882 case PA_SAMPLE_S32LE
:
883 case PA_SAMPLE_S32BE
:
884 case PA_SAMPLE_S24LE
:
885 case PA_SAMPLE_S24BE
:
886 case PA_SAMPLE_S24_32LE
:
887 case PA_SAMPLE_S24_32BE
:
888 case PA_SAMPLE_FLOAT32LE
:
889 case PA_SAMPLE_FLOAT32BE
:
890 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
891 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
892 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
893 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
894 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
895 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
896 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
897 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
898 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
899 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
902 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
905 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
908 pa_assert_not_reached();
913 ret
->memblock
= pa_memblock_ref(b
);
915 l
= pa_memblock_get_length(b
);
916 if (length
> l
|| length
== 0)
919 ret
->length
= pa_frame_align(length
, spec
);
925 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
931 if (format
== PA_SAMPLE_FLOAT32NE
) {
936 *d
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
938 s
= (const float*) ((const uint8_t*) s
+ sstr
);
939 d
= (float*) ((uint8_t*) d
+ dstr
);
942 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
947 f
= PA_FLOAT32_SWAP(*s
);
948 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
949 *d
= PA_FLOAT32_SWAP(f
);
951 s
= (const float*) ((const uint8_t*) s
+ sstr
);
952 d
= (float*) ((uint8_t*) d
+ dstr
);
957 /* Similar to pa_bytes_to_usec() but rounds up, not down */
959 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
965 fs
= pa_frame_size(spec
);
966 length
= (length
+ fs
- 1) / fs
;
968 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
970 return (usec
+ spec
->rate
- 1) / spec
->rate
;
973 /* Similar to pa_usec_to_bytes() but rounds up, not down */
975 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
979 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
981 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
983 u
*= pa_frame_size(spec
);
988 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
995 /* Only for debugging purposes */
1000 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1004 p
= pa_memblock_acquire(c
->memblock
);
1006 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1007 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1009 pa_memblock_release(c
->memblock
);
1014 static void calc_sine(float *f
, size_t l
, double freq
) {
1019 for (i
= 0; i
< l
; i
++)
1020 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1023 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1028 pa_memchunk_reset(c
);
1030 gcd
= pa_gcd(rate
, freq
);
1033 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1039 c
->length
= l
* sizeof(float);
1040 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1042 p
= pa_memblock_acquire(c
->memblock
);
1043 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1044 pa_memblock_release(c
->memblock
);