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 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 <liboil/liboilfuncs.h>
34 #include <liboil/liboil.h>
36 #include <pulse/timeval.h>
38 #include <pulsecore/log.h>
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/macro.h>
41 #include <pulsecore/g711.h>
43 #include "sample-util.h"
44 #include "endianmacros.h"
46 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
48 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
54 data
= pa_memblock_acquire(b
);
55 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
56 pa_memblock_release(b
);
61 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
65 pa_assert(c
->memblock
);
68 data
= pa_memblock_acquire(c
->memblock
);
69 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
70 pa_memblock_release(c
->memblock
);
75 static uint8_t silence_byte(pa_sample_format_t format
) {
83 case PA_SAMPLE_FLOAT32LE
:
84 case PA_SAMPLE_FLOAT32BE
:
91 pa_assert_not_reached();
95 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
97 pa_assert(length
> 0);
100 memset(p
, silence_byte(spec
->format
), length
);
104 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
110 for (channel
= 0; channel
< volume
->channels
; channel
++)
111 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
114 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
120 for (channel
= 0; channel
< volume
->channels
; channel
++)
121 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
124 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
126 float linear
[PA_CHANNELS_MAX
];
132 calc_linear_float_volume(linear
, volume
);
134 for (k
= 0; k
< nstreams
; k
++) {
136 for (channel
= 0; channel
< spec
->channels
; channel
++) {
137 pa_mix_info
*m
= streams
+ k
;
138 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
143 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
145 float linear
[PA_CHANNELS_MAX
];
151 calc_linear_float_volume(linear
, volume
);
153 for (k
= 0; k
< nstreams
; k
++) {
155 for (channel
= 0; channel
< spec
->channels
; channel
++) {
156 pa_mix_info
*m
= streams
+ k
;
157 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
163 pa_mix_info streams
[],
167 const pa_sample_spec
*spec
,
168 const pa_cvolume
*volume
,
171 pa_cvolume full_volume
;
182 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
184 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
185 pa_silence_memory(data
, length
, spec
);
189 for (k
= 0; k
< nstreams
; k
++)
190 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
192 for (z
= 0; z
< nstreams
; z
++)
193 if (length
> streams
[z
].chunk
.length
)
194 length
= streams
[z
].chunk
.length
;
196 end
= (uint8_t*) data
+ length
;
198 switch (spec
->format
) {
200 case PA_SAMPLE_S16NE
:{
201 unsigned channel
= 0;
203 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
209 for (i
= 0; i
< nstreams
; i
++) {
210 pa_mix_info
*m
= streams
+ i
;
211 int32_t v
, cv
= m
->linear
[channel
].i
;
213 if (PA_UNLIKELY(cv
<= 0))
216 v
= *((int16_t*) m
->ptr
);
217 v
= (v
* cv
) / 0x10000;
220 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
223 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
224 *((int16_t*) data
) = (int16_t) sum
;
226 data
= (uint8_t*) data
+ sizeof(int16_t);
228 if (PA_UNLIKELY(++channel
>= spec
->channels
))
235 case PA_SAMPLE_S16RE
:{
236 unsigned channel
= 0;
238 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
244 for (i
= 0; i
< nstreams
; i
++) {
245 pa_mix_info
*m
= streams
+ i
;
246 int32_t v
, cv
= m
->linear
[channel
].i
;
248 if (PA_UNLIKELY(cv
<= 0))
251 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
252 v
= (v
* cv
) / 0x10000;
255 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
258 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
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;
273 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
279 for (i
= 0; i
< nstreams
; i
++) {
280 pa_mix_info
*m
= streams
+ i
;
281 int32_t cv
= m
->linear
[channel
].i
;
284 if (PA_UNLIKELY(cv
<= 0))
287 v
= *((int32_t*) m
->ptr
);
288 v
= (v
* cv
) / 0x10000;
291 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
294 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
295 *((int32_t*) data
) = (int32_t) sum
;
297 data
= (uint8_t*) data
+ sizeof(int32_t);
299 if (PA_UNLIKELY(++channel
>= spec
->channels
))
306 case PA_SAMPLE_S32RE
:{
307 unsigned channel
= 0;
309 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
315 for (i
= 0; i
< nstreams
; i
++) {
316 pa_mix_info
*m
= streams
+ i
;
317 int32_t cv
= m
->linear
[channel
].i
;
320 if (PA_UNLIKELY(cv
<= 0))
323 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
324 v
= (v
* cv
) / 0x10000;
327 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
330 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
331 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
333 data
= (uint8_t*) data
+ sizeof(int32_t);
335 if (PA_UNLIKELY(++channel
>= spec
->channels
))
343 unsigned channel
= 0;
345 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
351 for (i
= 0; i
< nstreams
; i
++) {
352 pa_mix_info
*m
= streams
+ i
;
353 int32_t v
, cv
= m
->linear
[channel
].i
;
355 if (PA_UNLIKELY(cv
<= 0))
358 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
359 v
= (v
* cv
) / 0x10000;
362 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
365 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
366 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
368 data
= (uint8_t*) data
+ 1;
370 if (PA_UNLIKELY(++channel
>= spec
->channels
))
377 case PA_SAMPLE_ULAW
: {
378 unsigned channel
= 0;
380 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
386 for (i
= 0; i
< nstreams
; i
++) {
387 pa_mix_info
*m
= streams
+ i
;
388 int32_t v
, cv
= m
->linear
[channel
].i
;
390 if (PA_UNLIKELY(cv
<= 0))
393 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
394 v
= (v
* cv
) / 0x10000;
397 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
400 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
401 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
403 data
= (uint8_t*) data
+ 1;
405 if (PA_UNLIKELY(++channel
>= spec
->channels
))
412 case PA_SAMPLE_ALAW
: {
413 unsigned channel
= 0;
415 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
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(cv
<= 0))
428 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
429 v
= (v
* cv
) / 0x10000;
432 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
435 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
436 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
438 data
= (uint8_t*) data
+ 1;
440 if (PA_UNLIKELY(++channel
>= spec
->channels
))
447 case PA_SAMPLE_FLOAT32NE
: {
448 unsigned channel
= 0;
450 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
456 for (i
= 0; i
< nstreams
; i
++) {
457 pa_mix_info
*m
= streams
+ i
;
458 float v
, cv
= m
->linear
[channel
].f
;
460 if (PA_UNLIKELY(cv
<= 0))
463 v
= *((float*) m
->ptr
);
467 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
470 *((float*) data
) = sum
;
472 data
= (uint8_t*) data
+ sizeof(float);
474 if (PA_UNLIKELY(++channel
>= spec
->channels
))
481 case PA_SAMPLE_FLOAT32RE
: {
482 unsigned channel
= 0;
484 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
490 for (i
= 0; i
< nstreams
; i
++) {
491 pa_mix_info
*m
= streams
+ i
;
492 float v
, cv
= m
->linear
[channel
].f
;
494 if (PA_UNLIKELY(cv
<= 0))
497 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
501 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
504 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
506 data
= (uint8_t*) data
+ sizeof(float);
508 if (PA_UNLIKELY(++channel
>= spec
->channels
))
516 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
517 pa_assert_not_reached();
520 for (k
= 0; k
< nstreams
; k
++)
521 pa_memblock_release(streams
[k
].chunk
.memblock
);
527 void pa_volume_memchunk(
529 const pa_sample_spec
*spec
,
530 const pa_cvolume
*volume
) {
536 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
539 if (pa_memblock_is_silence(c
->memblock
))
542 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
545 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
546 pa_silence_memchunk(c
, spec
);
550 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
552 switch (spec
->format
) {
554 case PA_SAMPLE_S16NE
: {
557 int32_t linear
[PA_CHANNELS_MAX
];
559 calc_linear_integer_volume(linear
, volume
);
561 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
563 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
567 t
= (t
* linear
[channel
]) / 0x10000;
568 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
571 if (PA_UNLIKELY(++channel
>= spec
->channels
))
577 case PA_SAMPLE_S16RE
: {
580 int32_t linear
[PA_CHANNELS_MAX
];
582 calc_linear_integer_volume(linear
, volume
);
584 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
586 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
589 t
= (int32_t) PA_INT16_SWAP(*d
);
590 t
= (t
* linear
[channel
]) / 0x10000;
591 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
592 *d
= PA_INT16_SWAP((int16_t) t
);
594 if (PA_UNLIKELY(++channel
>= spec
->channels
))
601 case PA_SAMPLE_S32NE
: {
604 int32_t linear
[PA_CHANNELS_MAX
];
606 calc_linear_integer_volume(linear
, volume
);
608 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
610 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
614 t
= (t
* linear
[channel
]) / 0x10000;
615 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
618 if (PA_UNLIKELY(++channel
>= spec
->channels
))
624 case PA_SAMPLE_S32RE
: {
627 int32_t linear
[PA_CHANNELS_MAX
];
629 calc_linear_integer_volume(linear
, volume
);
631 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
633 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
636 t
= (int64_t) PA_INT32_SWAP(*d
);
637 t
= (t
* linear
[channel
]) / 0x10000;
638 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
639 *d
= PA_INT32_SWAP((int32_t) t
);
641 if (PA_UNLIKELY(++channel
>= spec
->channels
))
651 int32_t linear
[PA_CHANNELS_MAX
];
653 calc_linear_integer_volume(linear
, volume
);
655 e
= (uint8_t*) ptr
+ c
->length
;
657 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
660 t
= (int32_t) *d
- 0x80;
661 t
= (t
* linear
[channel
]) / 0x10000;
662 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
663 *d
= (uint8_t) (t
+ 0x80);
665 if (PA_UNLIKELY(++channel
>= spec
->channels
))
671 case PA_SAMPLE_ULAW
: {
674 int32_t linear
[PA_CHANNELS_MAX
];
676 calc_linear_integer_volume(linear
, volume
);
678 e
= (uint8_t*) ptr
+ c
->length
;
680 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
683 t
= (int32_t) st_ulaw2linear16(*d
);
684 t
= (t
* linear
[channel
]) / 0x10000;
685 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
686 *d
= (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
688 if (PA_UNLIKELY(++channel
>= spec
->channels
))
694 case PA_SAMPLE_ALAW
: {
697 int32_t linear
[PA_CHANNELS_MAX
];
699 calc_linear_integer_volume(linear
, volume
);
701 e
= (uint8_t*) ptr
+ c
->length
;
703 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
706 t
= (int32_t) st_alaw2linear16(*d
);
707 t
= (t
* linear
[channel
]) / 0x10000;
708 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
709 *d
= (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
711 if (PA_UNLIKELY(++channel
>= spec
->channels
))
717 case PA_SAMPLE_FLOAT32NE
: {
724 skip
= (int) (spec
->channels
* sizeof(float));
725 n
= (unsigned) (c
->length
/sizeof(float)/spec
->channels
);
727 for (channel
= 0; channel
< spec
->channels
; channel
++) {
730 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
733 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
735 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, (int) n
);
740 case PA_SAMPLE_FLOAT32RE
: {
743 float linear
[PA_CHANNELS_MAX
];
745 calc_linear_float_volume(linear
, volume
);
747 e
= (float*) ptr
+ c
->length
/sizeof(float);
749 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
752 t
= PA_FLOAT32_SWAP(*d
);
753 t
*= linear
[channel
];
754 *d
= PA_FLOAT32_SWAP(t
);
756 if (PA_UNLIKELY(++channel
>= spec
->channels
))
765 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
766 /* If we cannot change the volume, we just don't do it */
769 pa_memblock_release(c
->memblock
);
772 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
777 fs
= pa_frame_size(ss
);
782 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
787 fs
= pa_frame_size(ss
);
792 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
797 pa_assert(channels
> 0);
804 for (c
= 0; c
< channels
; c
++) {
810 d
= (uint8_t*) dst
+ c
* ss
;
812 for (j
= 0; j
< n
; j
++) {
813 oil_memcpy(d
, s
, (int) ss
);
814 s
= (uint8_t*) s
+ ss
;
815 d
= (uint8_t*) d
+ fs
;
820 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
826 pa_assert(channels
> 0);
832 for (c
= 0; c
< channels
; c
++) {
837 s
= (uint8_t*) src
+ c
* ss
;
840 for (j
= 0; j
< n
; j
++) {
841 oil_memcpy(d
, s
, (int) ss
);
842 s
= (uint8_t*) s
+ fs
;
843 d
= (uint8_t*) d
+ ss
;
848 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
855 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
857 b
= pa_memblock_new(pool
, length
);
859 data
= pa_memblock_acquire(b
);
860 memset(data
, c
, length
);
861 pa_memblock_release(b
);
863 pa_memblock_set_is_silence(b
, TRUE
);
868 void pa_silence_cache_init(pa_silence_cache
*cache
) {
871 memset(cache
, 0, sizeof(pa_silence_cache
));
874 void pa_silence_cache_done(pa_silence_cache
*cache
) {
875 pa_sample_format_t f
;
878 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
879 if (cache
->blocks
[f
])
880 pa_memblock_unref(cache
->blocks
[f
]);
882 memset(cache
, 0, sizeof(pa_silence_cache
));
885 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
890 pa_assert(pa_sample_spec_valid(spec
));
892 if (!(b
= cache
->blocks
[spec
->format
]))
894 switch (spec
->format
) {
896 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
898 case PA_SAMPLE_S16LE
:
899 case PA_SAMPLE_S16BE
:
900 case PA_SAMPLE_S32LE
:
901 case PA_SAMPLE_S32BE
:
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_FLOAT32LE
] = pa_memblock_ref(b
);
909 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
912 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
915 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
918 pa_assert_not_reached();
923 ret
->memblock
= pa_memblock_ref(b
);
925 l
= pa_memblock_get_length(b
);
926 if (length
> l
|| length
== 0)
929 ret
->length
= pa_frame_align(length
, spec
);
935 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
941 if (format
== PA_SAMPLE_FLOAT32NE
) {
943 float minus_one
= -1.0, plus_one
= 1.0;
944 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
947 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
952 f
= PA_FLOAT32_SWAP(*s
);
953 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
954 *d
= PA_FLOAT32_SWAP(f
);
956 s
= (const float*) ((const uint8_t*) s
+ sstr
);
957 d
= (float*) ((uint8_t*) d
+ dstr
);
962 /* Similar to pa_bytes_to_usec() but rounds up, not down */
964 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
970 fs
= pa_frame_size(spec
);
971 length
= (length
+ fs
- 1) / fs
;
973 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
975 return (usec
+ spec
->rate
- 1) / spec
->rate
;
978 /* Similar to pa_usec_to_bytes() but rounds up, not down */
980 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
984 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
986 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
988 u
*= pa_frame_size(spec
);
993 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1000 /* Only for debugging purposes */
1005 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1009 p
= pa_memblock_acquire(c
->memblock
);
1011 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1012 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1014 pa_memblock_release(c
->memblock
);