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>
42 #include <pulsecore/core-util.h>
44 #include "sample-util.h"
45 #include "endianmacros.h"
47 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
49 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
55 data
= pa_memblock_acquire(b
);
56 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
57 pa_memblock_release(b
);
62 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
66 pa_assert(c
->memblock
);
69 data
= pa_memblock_acquire(c
->memblock
);
70 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
71 pa_memblock_release(c
->memblock
);
76 static uint8_t silence_byte(pa_sample_format_t format
) {
84 case PA_SAMPLE_FLOAT32LE
:
85 case PA_SAMPLE_FLOAT32BE
:
92 pa_assert_not_reached();
96 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
98 pa_assert(length
> 0);
101 memset(p
, silence_byte(spec
->format
), length
);
105 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
111 for (channel
= 0; channel
< volume
->channels
; channel
++)
112 linear
[channel
] = (int32_t) lrint(pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
115 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
121 for (channel
= 0; channel
< volume
->channels
; channel
++)
122 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
125 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
127 float linear
[PA_CHANNELS_MAX
];
133 calc_linear_float_volume(linear
, volume
);
135 for (k
= 0; k
< nstreams
; k
++) {
137 for (channel
= 0; channel
< spec
->channels
; channel
++) {
138 pa_mix_info
*m
= streams
+ k
;
139 m
->linear
[channel
].i
= (int32_t) lrint(pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
] * 0x10000);
144 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_cvolume
*volume
, const pa_sample_spec
*spec
) {
146 float linear
[PA_CHANNELS_MAX
];
152 calc_linear_float_volume(linear
, volume
);
154 for (k
= 0; k
< nstreams
; k
++) {
156 for (channel
= 0; channel
< spec
->channels
; channel
++) {
157 pa_mix_info
*m
= streams
+ k
;
158 m
->linear
[channel
].f
= (float) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * linear
[channel
]);
164 pa_mix_info streams
[],
168 const pa_sample_spec
*spec
,
169 const pa_cvolume
*volume
,
172 pa_cvolume full_volume
;
183 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
185 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
186 pa_silence_memory(data
, length
, spec
);
190 for (k
= 0; k
< nstreams
; k
++)
191 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
193 for (z
= 0; z
< nstreams
; z
++)
194 if (length
> streams
[z
].chunk
.length
)
195 length
= streams
[z
].chunk
.length
;
197 end
= (uint8_t*) data
+ length
;
199 switch (spec
->format
) {
201 case PA_SAMPLE_S16NE
:{
202 unsigned channel
= 0;
204 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
210 for (i
= 0; i
< nstreams
; i
++) {
211 pa_mix_info
*m
= streams
+ i
;
212 int32_t v
, cv
= m
->linear
[channel
].i
;
214 if (PA_UNLIKELY(cv
<= 0))
217 v
= *((int16_t*) m
->ptr
);
218 v
= (v
* cv
) / 0x10000;
221 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
224 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
225 *((int16_t*) data
) = (int16_t) sum
;
227 data
= (uint8_t*) data
+ sizeof(int16_t);
229 if (PA_UNLIKELY(++channel
>= spec
->channels
))
236 case PA_SAMPLE_S16RE
:{
237 unsigned channel
= 0;
239 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
245 for (i
= 0; i
< nstreams
; i
++) {
246 pa_mix_info
*m
= streams
+ i
;
247 int32_t v
, cv
= m
->linear
[channel
].i
;
249 if (PA_UNLIKELY(cv
<= 0))
252 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
253 v
= (v
* cv
) / 0x10000;
256 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
259 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
260 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
262 data
= (uint8_t*) data
+ sizeof(int16_t);
264 if (PA_UNLIKELY(++channel
>= spec
->channels
))
271 case PA_SAMPLE_S32NE
:{
272 unsigned channel
= 0;
274 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
280 for (i
= 0; i
< nstreams
; i
++) {
281 pa_mix_info
*m
= streams
+ i
;
282 int32_t cv
= m
->linear
[channel
].i
;
285 if (PA_UNLIKELY(cv
<= 0))
288 v
= *((int32_t*) m
->ptr
);
289 v
= (v
* cv
) / 0x10000;
292 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
295 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
296 *((int32_t*) data
) = (int32_t) sum
;
298 data
= (uint8_t*) data
+ sizeof(int32_t);
300 if (PA_UNLIKELY(++channel
>= spec
->channels
))
307 case PA_SAMPLE_S32RE
:{
308 unsigned channel
= 0;
310 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
316 for (i
= 0; i
< nstreams
; i
++) {
317 pa_mix_info
*m
= streams
+ i
;
318 int32_t cv
= m
->linear
[channel
].i
;
321 if (PA_UNLIKELY(cv
<= 0))
324 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
325 v
= (v
* cv
) / 0x10000;
328 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
331 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
332 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
334 data
= (uint8_t*) data
+ sizeof(int32_t);
336 if (PA_UNLIKELY(++channel
>= spec
->channels
))
344 unsigned channel
= 0;
346 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
352 for (i
= 0; i
< nstreams
; i
++) {
353 pa_mix_info
*m
= streams
+ i
;
354 int32_t v
, cv
= m
->linear
[channel
].i
;
356 if (PA_UNLIKELY(cv
<= 0))
359 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
360 v
= (v
* cv
) / 0x10000;
363 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
366 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
367 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
369 data
= (uint8_t*) data
+ 1;
371 if (PA_UNLIKELY(++channel
>= spec
->channels
))
378 case PA_SAMPLE_ULAW
: {
379 unsigned channel
= 0;
381 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
387 for (i
= 0; i
< nstreams
; i
++) {
388 pa_mix_info
*m
= streams
+ i
;
389 int32_t v
, cv
= m
->linear
[channel
].i
;
391 if (PA_UNLIKELY(cv
<= 0))
394 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
395 v
= (v
* cv
) / 0x10000;
398 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
401 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
402 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
404 data
= (uint8_t*) data
+ 1;
406 if (PA_UNLIKELY(++channel
>= spec
->channels
))
413 case PA_SAMPLE_ALAW
: {
414 unsigned channel
= 0;
416 calc_linear_integer_stream_volumes(streams
, nstreams
, volume
, spec
);
422 for (i
= 0; i
< nstreams
; i
++) {
423 pa_mix_info
*m
= streams
+ i
;
424 int32_t v
, cv
= m
->linear
[channel
].i
;
426 if (PA_UNLIKELY(cv
<= 0))
429 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
430 v
= (v
* cv
) / 0x10000;
433 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
436 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
437 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
439 data
= (uint8_t*) data
+ 1;
441 if (PA_UNLIKELY(++channel
>= spec
->channels
))
448 case PA_SAMPLE_FLOAT32NE
: {
449 unsigned channel
= 0;
451 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
457 for (i
= 0; i
< nstreams
; i
++) {
458 pa_mix_info
*m
= streams
+ i
;
459 float v
, cv
= m
->linear
[channel
].f
;
461 if (PA_UNLIKELY(cv
<= 0))
464 v
= *((float*) m
->ptr
);
468 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
471 *((float*) data
) = sum
;
473 data
= (uint8_t*) data
+ sizeof(float);
475 if (PA_UNLIKELY(++channel
>= spec
->channels
))
482 case PA_SAMPLE_FLOAT32RE
: {
483 unsigned channel
= 0;
485 calc_linear_float_stream_volumes(streams
, nstreams
, volume
, spec
);
491 for (i
= 0; i
< nstreams
; i
++) {
492 pa_mix_info
*m
= streams
+ i
;
493 float v
, cv
= m
->linear
[channel
].f
;
495 if (PA_UNLIKELY(cv
<= 0))
498 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
);
502 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
505 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
507 data
= (uint8_t*) data
+ sizeof(float);
509 if (PA_UNLIKELY(++channel
>= spec
->channels
))
517 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
518 pa_assert_not_reached();
521 for (k
= 0; k
< nstreams
; k
++)
522 pa_memblock_release(streams
[k
].chunk
.memblock
);
528 void pa_volume_memchunk(
530 const pa_sample_spec
*spec
,
531 const pa_cvolume
*volume
) {
537 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
540 if (pa_memblock_is_silence(c
->memblock
))
543 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
546 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
547 pa_silence_memchunk(c
, spec
);
551 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
553 switch (spec
->format
) {
555 case PA_SAMPLE_S16NE
: {
558 int32_t linear
[PA_CHANNELS_MAX
];
560 calc_linear_integer_volume(linear
, volume
);
562 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
564 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
568 t
= (t
* linear
[channel
]) / 0x10000;
569 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
572 if (PA_UNLIKELY(++channel
>= spec
->channels
))
578 case PA_SAMPLE_S16RE
: {
581 int32_t linear
[PA_CHANNELS_MAX
];
583 calc_linear_integer_volume(linear
, volume
);
585 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
587 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
590 t
= (int32_t) PA_INT16_SWAP(*d
);
591 t
= (t
* linear
[channel
]) / 0x10000;
592 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
593 *d
= PA_INT16_SWAP((int16_t) t
);
595 if (PA_UNLIKELY(++channel
>= spec
->channels
))
602 case PA_SAMPLE_S32NE
: {
605 int32_t linear
[PA_CHANNELS_MAX
];
607 calc_linear_integer_volume(linear
, volume
);
609 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
611 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
615 t
= (t
* linear
[channel
]) / 0x10000;
616 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
619 if (PA_UNLIKELY(++channel
>= spec
->channels
))
625 case PA_SAMPLE_S32RE
: {
628 int32_t linear
[PA_CHANNELS_MAX
];
630 calc_linear_integer_volume(linear
, volume
);
632 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
634 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
637 t
= (int64_t) PA_INT32_SWAP(*d
);
638 t
= (t
* linear
[channel
]) / 0x10000;
639 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
640 *d
= PA_INT32_SWAP((int32_t) t
);
642 if (PA_UNLIKELY(++channel
>= spec
->channels
))
652 int32_t linear
[PA_CHANNELS_MAX
];
654 calc_linear_integer_volume(linear
, volume
);
656 e
= (uint8_t*) ptr
+ c
->length
;
658 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
661 t
= (int32_t) *d
- 0x80;
662 t
= (t
* linear
[channel
]) / 0x10000;
663 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
664 *d
= (uint8_t) (t
+ 0x80);
666 if (PA_UNLIKELY(++channel
>= spec
->channels
))
672 case PA_SAMPLE_ULAW
: {
675 int32_t linear
[PA_CHANNELS_MAX
];
677 calc_linear_integer_volume(linear
, volume
);
679 e
= (uint8_t*) ptr
+ c
->length
;
681 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
684 t
= (int32_t) st_ulaw2linear16(*d
);
685 t
= (t
* linear
[channel
]) / 0x10000;
686 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
687 *d
= (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
689 if (PA_UNLIKELY(++channel
>= spec
->channels
))
695 case PA_SAMPLE_ALAW
: {
698 int32_t linear
[PA_CHANNELS_MAX
];
700 calc_linear_integer_volume(linear
, volume
);
702 e
= (uint8_t*) ptr
+ c
->length
;
704 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
707 t
= (int32_t) st_alaw2linear16(*d
);
708 t
= (t
* linear
[channel
]) / 0x10000;
709 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
710 *d
= (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
712 if (PA_UNLIKELY(++channel
>= spec
->channels
))
718 case PA_SAMPLE_FLOAT32NE
: {
725 skip
= (int) (spec
->channels
* sizeof(float));
726 n
= (unsigned) (c
->length
/sizeof(float)/spec
->channels
);
728 for (channel
= 0; channel
< spec
->channels
; channel
++) {
731 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
734 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
736 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, (int) n
);
741 case PA_SAMPLE_FLOAT32RE
: {
744 float linear
[PA_CHANNELS_MAX
];
746 calc_linear_float_volume(linear
, volume
);
748 e
= (float*) ptr
+ c
->length
/sizeof(float);
750 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
753 t
= PA_FLOAT32_SWAP(*d
);
754 t
*= linear
[channel
];
755 *d
= PA_FLOAT32_SWAP(t
);
757 if (PA_UNLIKELY(++channel
>= spec
->channels
))
766 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
767 /* If we cannot change the volume, we just don't do it */
770 pa_memblock_release(c
->memblock
);
773 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
778 fs
= pa_frame_size(ss
);
783 pa_bool_t
pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
788 fs
= pa_frame_size(ss
);
793 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
798 pa_assert(channels
> 0);
805 for (c
= 0; c
< channels
; c
++) {
811 d
= (uint8_t*) dst
+ c
* ss
;
813 for (j
= 0; j
< n
; j
++) {
814 oil_memcpy(d
, s
, (int) ss
);
815 s
= (uint8_t*) s
+ ss
;
816 d
= (uint8_t*) d
+ fs
;
821 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
827 pa_assert(channels
> 0);
833 for (c
= 0; c
< channels
; c
++) {
838 s
= (uint8_t*) src
+ c
* ss
;
841 for (j
= 0; j
< n
; j
++) {
842 oil_memcpy(d
, s
, (int) ss
);
843 s
= (uint8_t*) s
+ fs
;
844 d
= (uint8_t*) d
+ ss
;
849 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
856 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
858 b
= pa_memblock_new(pool
, length
);
860 data
= pa_memblock_acquire(b
);
861 memset(data
, c
, length
);
862 pa_memblock_release(b
);
864 pa_memblock_set_is_silence(b
, TRUE
);
869 void pa_silence_cache_init(pa_silence_cache
*cache
) {
872 memset(cache
, 0, sizeof(pa_silence_cache
));
875 void pa_silence_cache_done(pa_silence_cache
*cache
) {
876 pa_sample_format_t f
;
879 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
880 if (cache
->blocks
[f
])
881 pa_memblock_unref(cache
->blocks
[f
]);
883 memset(cache
, 0, sizeof(pa_silence_cache
));
886 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
891 pa_assert(pa_sample_spec_valid(spec
));
893 if (!(b
= cache
->blocks
[spec
->format
]))
895 switch (spec
->format
) {
897 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
899 case PA_SAMPLE_S16LE
:
900 case PA_SAMPLE_S16BE
:
901 case PA_SAMPLE_S32LE
:
902 case PA_SAMPLE_S32BE
:
903 case PA_SAMPLE_FLOAT32LE
:
904 case PA_SAMPLE_FLOAT32BE
:
905 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
906 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
907 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
908 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
909 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
910 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
913 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
916 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
919 pa_assert_not_reached();
924 ret
->memblock
= pa_memblock_ref(b
);
926 l
= pa_memblock_get_length(b
);
927 if (length
> l
|| length
== 0)
930 ret
->length
= pa_frame_align(length
, spec
);
936 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
942 if (format
== PA_SAMPLE_FLOAT32NE
) {
944 float minus_one
= -1.0, plus_one
= 1.0;
945 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
948 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
953 f
= PA_FLOAT32_SWAP(*s
);
954 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
955 *d
= PA_FLOAT32_SWAP(f
);
957 s
= (const float*) ((const uint8_t*) s
+ sstr
);
958 d
= (float*) ((uint8_t*) d
+ dstr
);
963 /* Similar to pa_bytes_to_usec() but rounds up, not down */
965 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
971 fs
= pa_frame_size(spec
);
972 length
= (length
+ fs
- 1) / fs
;
974 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
976 return (usec
+ spec
->rate
- 1) / spec
->rate
;
979 /* Similar to pa_usec_to_bytes() but rounds up, not down */
981 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
985 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
987 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
989 u
*= pa_frame_size(spec
);
994 void pa_memchunk_dump_to_file(pa_memchunk
*c
, const char *fn
) {
1001 /* Only for debugging purposes */
1006 pa_log_warn("Failed to open '%s': %s", fn
, pa_cstrerror(errno
));
1010 p
= pa_memblock_acquire(c
->memblock
);
1012 if (fwrite((uint8_t*) p
+ c
->index
, 1, c
->length
, f
) != c
->length
)
1013 pa_log_warn("Failed to write to '%s': %s", fn
, pa_cstrerror(errno
));
1015 pa_memblock_release(c
->memblock
);
1020 static void calc_sine(float *f
, size_t l
, double freq
) {
1025 for (i
= 0; i
< l
; i
++)
1026 *(f
++) = (float) 0.5f
* sin((double) i
*M_PI
*2*freq
/ (double) l
);
1029 void pa_memchunk_sine(pa_memchunk
*c
, pa_mempool
*pool
, unsigned rate
, unsigned freq
) {
1034 pa_memchunk_reset(c
);
1036 gcd
= pa_gcd(rate
, freq
);
1039 l
= pa_mempool_block_size_max(pool
) / sizeof(float);
1045 c
->length
= l
* sizeof(float);
1046 c
->memblock
= pa_memblock_new(pool
, c
->length
);
1048 p
= pa_memblock_acquire(c
->memblock
);
1049 calc_sine(p
, c
->length
, freq
* l
/ rate
);
1050 pa_memblock_release(c
->memblock
);