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
= pa_memblock_acquire_chunk(&streams
[k
].chunk
);
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_LIKELY(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 independently 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_LIKELY(cv
> 0)) {
276 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
277 v
= ((v
* lo
) >> 16) + (v
* hi
);
280 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
283 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
284 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
286 data
= (uint8_t*) data
+ sizeof(int16_t);
288 if (PA_UNLIKELY(++channel
>= spec
->channels
))
295 case PA_SAMPLE_S32NE
:{
296 unsigned channel
= 0;
298 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
304 for (i
= 0; i
< nstreams
; i
++) {
305 pa_mix_info
*m
= streams
+ i
;
306 int32_t cv
= m
->linear
[channel
].i
;
309 if (PA_LIKELY(cv
> 0)) {
311 v
= *((int32_t*) m
->ptr
);
315 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
318 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
319 *((int32_t*) data
) = (int32_t) sum
;
321 data
= (uint8_t*) data
+ sizeof(int32_t);
323 if (PA_UNLIKELY(++channel
>= spec
->channels
))
330 case PA_SAMPLE_S32RE
:{
331 unsigned channel
= 0;
333 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
339 for (i
= 0; i
< nstreams
; i
++) {
340 pa_mix_info
*m
= streams
+ i
;
341 int32_t cv
= m
->linear
[channel
].i
;
344 if (PA_LIKELY(cv
> 0)) {
346 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
350 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
353 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
354 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
356 data
= (uint8_t*) data
+ sizeof(int32_t);
358 if (PA_UNLIKELY(++channel
>= spec
->channels
))
365 case PA_SAMPLE_S24NE
: {
366 unsigned channel
= 0;
368 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
374 for (i
= 0; i
< nstreams
; i
++) {
375 pa_mix_info
*m
= streams
+ i
;
376 int32_t cv
= m
->linear
[channel
].i
;
379 if (PA_LIKELY(cv
> 0)) {
381 v
= (int32_t) (PA_READ24NE(m
->ptr
) << 8);
385 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
388 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
389 PA_WRITE24NE(data
, ((uint32_t) sum
) >> 8);
391 data
= (uint8_t*) data
+ 3;
393 if (PA_UNLIKELY(++channel
>= spec
->channels
))
400 case PA_SAMPLE_S24RE
: {
401 unsigned channel
= 0;
403 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
409 for (i
= 0; i
< nstreams
; i
++) {
410 pa_mix_info
*m
= streams
+ i
;
411 int32_t cv
= m
->linear
[channel
].i
;
414 if (PA_LIKELY(cv
> 0)) {
416 v
= (int32_t) (PA_READ24RE(m
->ptr
) << 8);
420 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
423 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
424 PA_WRITE24RE(data
, ((uint32_t) sum
) >> 8);
426 data
= (uint8_t*) data
+ 3;
428 if (PA_UNLIKELY(++channel
>= spec
->channels
))
435 case PA_SAMPLE_S24_32NE
: {
436 unsigned channel
= 0;
438 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
444 for (i
= 0; i
< nstreams
; i
++) {
445 pa_mix_info
*m
= streams
+ i
;
446 int32_t cv
= m
->linear
[channel
].i
;
449 if (PA_LIKELY(cv
> 0)) {
451 v
= (int32_t) (*((uint32_t*)m
->ptr
) << 8);
455 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
458 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
459 *((uint32_t*) data
) = ((uint32_t) (int32_t) sum
) >> 8;
461 data
= (uint8_t*) data
+ sizeof(uint32_t);
463 if (PA_UNLIKELY(++channel
>= spec
->channels
))
470 case PA_SAMPLE_S24_32RE
: {
471 unsigned channel
= 0;
473 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
479 for (i
= 0; i
< nstreams
; i
++) {
480 pa_mix_info
*m
= streams
+ i
;
481 int32_t cv
= m
->linear
[channel
].i
;
484 if (PA_LIKELY(cv
> 0)) {
486 v
= (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m
->ptr
)) << 8);
490 m
->ptr
= (uint8_t*) m
->ptr
+ 3;
493 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
494 *((uint32_t*) data
) = PA_INT32_SWAP(((uint32_t) (int32_t) sum
) >> 8);
496 data
= (uint8_t*) data
+ sizeof(uint32_t);
498 if (PA_UNLIKELY(++channel
>= spec
->channels
))
506 unsigned channel
= 0;
508 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
514 for (i
= 0; i
< nstreams
; i
++) {
515 pa_mix_info
*m
= streams
+ i
;
516 int32_t v
, cv
= m
->linear
[channel
].i
;
518 if (PA_LIKELY(cv
> 0)) {
520 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
524 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
527 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
528 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
530 data
= (uint8_t*) data
+ 1;
532 if (PA_UNLIKELY(++channel
>= spec
->channels
))
539 case PA_SAMPLE_ULAW
: {
540 unsigned channel
= 0;
542 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
548 for (i
= 0; i
< nstreams
; i
++) {
549 pa_mix_info
*m
= streams
+ i
;
550 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
552 if (PA_LIKELY(cv
> 0)) {
557 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
558 v
= ((v
* lo
) >> 16) + (v
* hi
);
561 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
564 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
565 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
567 data
= (uint8_t*) data
+ 1;
569 if (PA_UNLIKELY(++channel
>= spec
->channels
))
576 case PA_SAMPLE_ALAW
: {
577 unsigned channel
= 0;
579 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
585 for (i
= 0; i
< nstreams
; i
++) {
586 pa_mix_info
*m
= streams
+ i
;
587 int32_t v
, hi
, lo
, cv
= m
->linear
[channel
].i
;
589 if (PA_LIKELY(cv
> 0)) {
594 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
595 v
= ((v
* lo
) >> 16) + (v
* hi
);
598 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
601 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
602 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
604 data
= (uint8_t*) data
+ 1;
606 if (PA_UNLIKELY(++channel
>= spec
->channels
))
613 case PA_SAMPLE_FLOAT32NE
: {
614 unsigned channel
= 0;
616 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
622 for (i
= 0; i
< nstreams
; i
++) {
623 pa_mix_info
*m
= streams
+ i
;
624 float v
, cv
= m
->linear
[channel
].f
;
626 if (PA_LIKELY(cv
> 0)) {
628 v
= *((float*) m
->ptr
);
632 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
635 *((float*) data
) = sum
;
637 data
= (uint8_t*) data
+ sizeof(float);
639 if (PA_UNLIKELY(++channel
>= spec
->channels
))
646 case PA_SAMPLE_FLOAT32RE
: {
647 unsigned channel
= 0;
649 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
655 for (i
= 0; i
< nstreams
; i
++) {
656 pa_mix_info
*m
= streams
+ i
;
657 float v
, cv
= m
->linear
[channel
].f
;
659 if (PA_LIKELY(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
+ VOLUME_PADDING
];
720 pa_do_volume_func_t do_volume
;
724 pa_assert(pa_sample_spec_valid(spec
));
725 pa_assert(pa_frame_aligned(c
->length
, spec
));
728 if (pa_memblock_is_silence(c
->memblock
))
731 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
734 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
735 pa_silence_memchunk(c
, spec
);
739 do_volume
= pa_get_volume_func(spec
->format
);
740 pa_assert(do_volume
);
742 calc_volume_table
[spec
->format
] ((void *)linear
, volume
);
744 ptr
= pa_memblock_acquire_chunk(c
);
746 do_volume (ptr
, (void *)linear
, spec
->channels
, c
->length
);
748 pa_memblock_release(c
->memblock
);
751 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
756 fs
= pa_frame_size(ss
);
761 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
766 fs
= pa_frame_size(ss
);
771 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
776 pa_assert(channels
> 0);
783 for (c
= 0; c
< channels
; c
++) {
789 d
= (uint8_t*) dst
+ c
* ss
;
791 for (j
= 0; j
< n
; j
++) {
792 memcpy(d
, s
, (int) ss
);
793 s
= (uint8_t*) s
+ ss
;
794 d
= (uint8_t*) d
+ fs
;
799 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
805 pa_assert(channels
> 0);
811 for (c
= 0; c
< channels
; c
++) {
816 s
= (uint8_t*) src
+ c
* ss
;
819 for (j
= 0; j
< n
; j
++) {
820 memcpy(d
, s
, (int) ss
);
821 s
= (uint8_t*) s
+ fs
;
822 d
= (uint8_t*) d
+ ss
;
827 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
834 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
836 b
= pa_memblock_new(pool
, length
);
838 data
= pa_memblock_acquire(b
);
839 memset(data
, c
, length
);
840 pa_memblock_release(b
);
842 pa_memblock_set_is_silence(b
, TRUE
);
847 void pa_silence_cache_init(pa_silence_cache
*cache
) {
850 memset(cache
, 0, sizeof(pa_silence_cache
));
853 void pa_silence_cache_done(pa_silence_cache
*cache
) {
854 pa_sample_format_t f
;
857 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
858 if (cache
->blocks
[f
])
859 pa_memblock_unref(cache
->blocks
[f
]);
861 memset(cache
, 0, sizeof(pa_silence_cache
));
864 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
869 pa_assert(pa_sample_spec_valid(spec
));
871 if (!(b
= cache
->blocks
[spec
->format
]))
873 switch (spec
->format
) {
875 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
877 case PA_SAMPLE_S16LE
:
878 case PA_SAMPLE_S16BE
:
879 case PA_SAMPLE_S32LE
:
880 case PA_SAMPLE_S32BE
:
881 case PA_SAMPLE_S24LE
:
882 case PA_SAMPLE_S24BE
:
883 case PA_SAMPLE_S24_32LE
:
884 case PA_SAMPLE_S24_32BE
:
885 case PA_SAMPLE_FLOAT32LE
:
886 case PA_SAMPLE_FLOAT32BE
:
887 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
888 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
889 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
890 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
891 cache
->blocks
[PA_SAMPLE_S24LE
] = pa_memblock_ref(b
);
892 cache
->blocks
[PA_SAMPLE_S24BE
] = pa_memblock_ref(b
);
893 cache
->blocks
[PA_SAMPLE_S24_32LE
] = pa_memblock_ref(b
);
894 cache
->blocks
[PA_SAMPLE_S24_32BE
] = pa_memblock_ref(b
);
895 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
896 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
899 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
902 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
905 pa_assert_not_reached();
910 ret
->memblock
= pa_memblock_ref(b
);
912 l
= pa_memblock_get_length(b
);
913 if (length
> l
|| length
== 0)
916 ret
->length
= pa_frame_align(length
, spec
);
922 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
928 if (format
== PA_SAMPLE_FLOAT32NE
) {
933 *d
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
935 s
= (const float*) ((const uint8_t*) s
+ sstr
);
936 d
= (float*) ((uint8_t*) d
+ dstr
);
939 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
944 f
= PA_FLOAT32_SWAP(*s
);
945 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
946 *d
= PA_FLOAT32_SWAP(f
);
948 s
= (const float*) ((const uint8_t*) s
+ sstr
);
949 d
= (float*) ((uint8_t*) d
+ dstr
);
954 /* Similar to pa_bytes_to_usec() but rounds up, not down */
956 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
962 fs
= pa_frame_size(spec
);
963 length
= (length
+ fs
- 1) / fs
;
965 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
967 return (usec
+ spec
->rate
- 1) / spec
->rate
;
970 /* Similar to pa_usec_to_bytes() but rounds up, not down */
972 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
976 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
978 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
980 u
*= pa_frame_size(spec
);
985 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
992 /* Only for debugging purposes */
994 f
= pa_fopen_cloexec(fn
, "a");
997 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1001 p
= pa_memblock_acquire(c
->memblock
);
1003 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1004 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1006 pa_memblock_release(c
->memblock
);
1011 static void calc_sine(float *f
, size_t l
, double freq
) {
1016 for (i
= 0; i
< l
; i
++)
1017 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1020 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1025 pa_memchunk_reset(c
);
1027 gcd
= pa_gcd(rate
, freq
);
1030 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1036 c
->length
= l
* sizeof(float);
1037 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1039 p
= pa_memblock_acquire(c
->memblock
);
1040 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1041 pa_memblock_release(c
->memblock
);
1044 size_t pa_convert_size(size_t size
, const pa_sample_spec
*from
, const pa_sample_spec
*to
) {
1050 usec
= pa_bytes_to_usec_round_up(size
, from
);
1051 return pa_usec_to_bytes_round_up(usec
, to
);