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
31 #include <liboil/liboilfuncs.h>
32 #include <liboil/liboil.h>
34 #include <pulse/timeval.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/g711.h>
40 #include "sample-util.h"
41 #include "endianmacros.h"
43 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
45 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
51 data
= pa_memblock_acquire(b
);
52 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
53 pa_memblock_release(b
);
58 pa_memchunk
* pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
62 pa_assert(c
->memblock
);
65 data
= pa_memblock_acquire(c
->memblock
);
66 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
67 pa_memblock_release(c
->memblock
);
72 static uint8_t silence_byte(pa_sample_format_t format
) {
80 case PA_SAMPLE_FLOAT32LE
:
81 case PA_SAMPLE_FLOAT32BE
:
88 pa_assert_not_reached();
92 void* pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
94 pa_assert(length
> 0);
97 memset(p
, silence_byte(spec
->format
), length
);
101 static void calc_linear_integer_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
107 for (k
= 0; k
< nstreams
; k
++) {
110 for (channel
= 0; channel
< spec
->channels
; channel
++) {
111 pa_mix_info
*m
= streams
+ k
;
112 m
->linear
[channel
].i
= (int32_t) (pa_sw_volume_to_linear(m
->volume
.values
[channel
]) * 0x10000);
117 static void calc_linear_integer_volume(int32_t linear
[], const pa_cvolume
*volume
) {
123 for (channel
= 0; channel
< volume
->channels
; channel
++)
124 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
127 static void calc_linear_float_stream_volumes(pa_mix_info streams
[], unsigned nstreams
, const pa_sample_spec
*spec
) {
133 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
].f
= (float) pa_sw_volume_to_linear(m
->volume
.values
[channel
]);
143 static void calc_linear_float_volume(float linear
[], const pa_cvolume
*volume
) {
149 for (channel
= 0; channel
< volume
->channels
; channel
++)
150 linear
[channel
] = (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
154 pa_mix_info streams
[],
158 const pa_sample_spec
*spec
,
159 const pa_cvolume
*volume
,
162 pa_cvolume full_volume
;
173 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
175 if (mute
|| pa_cvolume_is_muted(volume
) || nstreams
<= 0) {
176 pa_silence_memory(data
, length
, spec
);
180 for (k
= 0; k
< nstreams
; k
++)
181 streams
[k
].ptr
= (uint8_t*) pa_memblock_acquire(streams
[k
].chunk
.memblock
) + streams
[k
].chunk
.index
;
183 for (z
= 0; z
< nstreams
; z
++)
184 if (length
> streams
[z
].chunk
.length
)
185 length
= streams
[z
].chunk
.length
;
187 end
= (uint8_t*) data
+ length
;
189 switch (spec
->format
) {
191 case PA_SAMPLE_S16NE
:{
192 unsigned channel
= 0;
193 int32_t linear
[PA_CHANNELS_MAX
];
195 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
196 calc_linear_integer_volume(linear
, volume
);
202 for (i
= 0; i
< nstreams
; i
++) {
203 pa_mix_info
*m
= streams
+ i
;
204 int32_t v
, cv
= m
->linear
[channel
].i
;
206 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
209 v
= *((int16_t*) m
->ptr
);
210 v
= (v
* cv
) / 0x10000;
214 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
217 sum
= (sum
* linear
[channel
]) / 0x10000;
218 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
219 *((int16_t*) data
) = (int16_t) sum
;
221 data
= (uint8_t*) data
+ sizeof(int16_t);
223 if (PA_UNLIKELY(++channel
>= spec
->channels
))
230 case PA_SAMPLE_S16RE
:{
231 unsigned channel
= 0;
232 int32_t linear
[PA_CHANNELS_MAX
];
234 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
235 calc_linear_integer_volume(linear
, volume
);
241 for (i
= 0; i
< nstreams
; i
++) {
242 pa_mix_info
*m
= streams
+ i
;
243 int32_t v
, cv
= m
->linear
[channel
].i
;
245 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
248 v
= PA_INT16_SWAP(*((int16_t*) m
->ptr
));
249 v
= (v
* cv
) / 0x10000;
253 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int16_t);
256 sum
= (sum
* linear
[channel
]) / 0x10000;
257 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
258 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
260 data
= (uint8_t*) data
+ sizeof(int16_t);
262 if (PA_UNLIKELY(++channel
>= spec
->channels
))
269 case PA_SAMPLE_S32NE
:{
270 unsigned channel
= 0;
271 int32_t linear
[PA_CHANNELS_MAX
];
273 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
274 calc_linear_integer_volume(linear
, volume
);
280 for (i
= 0; i
< nstreams
; i
++) {
281 pa_mix_info
*m
= streams
+ i
;
283 int32_t cv
= m
->linear
[channel
].i
;
285 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
288 v
= *((int32_t*) m
->ptr
);
289 v
= (v
* cv
) / 0x10000;
293 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
296 sum
= (sum
* linear
[channel
]) / 0x10000;
297 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
298 *((int32_t*) data
) = (int32_t) sum
;
300 data
= (uint8_t*) data
+ sizeof(int32_t);
302 if (PA_UNLIKELY(++channel
>= spec
->channels
))
309 case PA_SAMPLE_S32RE
:{
310 unsigned channel
= 0;
311 int32_t linear
[PA_CHANNELS_MAX
];
313 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
314 calc_linear_integer_volume(linear
, volume
);
320 for (i
= 0; i
< nstreams
; i
++) {
321 pa_mix_info
*m
= streams
+ i
;
323 int32_t cv
= m
->linear
[channel
].i
;
325 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
328 v
= PA_INT32_SWAP(*((int32_t*) m
->ptr
));
329 v
= (v
* cv
) / 0x10000;
333 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(int32_t);
336 sum
= (sum
* linear
[channel
]) / 0x10000;
337 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80000000LL
, 0x7FFFFFFFLL
);
338 *((int32_t*) data
) = PA_INT32_SWAP((int32_t) sum
);
340 data
= (uint8_t*) data
+ sizeof(int32_t);
342 if (PA_UNLIKELY(++channel
>= spec
->channels
))
350 unsigned channel
= 0;
351 int32_t linear
[PA_CHANNELS_MAX
];
353 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
354 calc_linear_integer_volume(linear
, volume
);
360 for (i
= 0; i
< nstreams
; i
++) {
361 pa_mix_info
*m
= streams
+ i
;
362 int32_t v
, cv
= m
->linear
[channel
].i
;
364 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
367 v
= (int32_t) *((uint8_t*) m
->ptr
) - 0x80;
368 v
= (v
* cv
) / 0x10000;
372 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
375 sum
= (sum
* linear
[channel
]) / 0x10000;
376 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
377 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
379 data
= (uint8_t*) data
+ 1;
381 if (PA_UNLIKELY(++channel
>= spec
->channels
))
388 case PA_SAMPLE_ULAW
: {
389 unsigned channel
= 0;
390 int32_t linear
[PA_CHANNELS_MAX
];
392 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
393 calc_linear_integer_volume(linear
, volume
);
399 for (i
= 0; i
< nstreams
; i
++) {
400 pa_mix_info
*m
= streams
+ i
;
401 int32_t v
, cv
= m
->linear
[channel
].i
;
403 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
406 v
= (int32_t) st_ulaw2linear16(*((uint8_t*) m
->ptr
));
407 v
= (v
* cv
) / 0x10000;
411 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
414 sum
= (sum
* linear
[channel
]) / 0x10000;
415 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
416 *((uint8_t*) data
) = (uint8_t) st_14linear2ulaw((int16_t) sum
>> 2);
418 data
= (uint8_t*) data
+ 1;
420 if (PA_UNLIKELY(++channel
>= spec
->channels
))
427 case PA_SAMPLE_ALAW
: {
428 unsigned channel
= 0;
429 int32_t linear
[PA_CHANNELS_MAX
];
431 calc_linear_integer_stream_volumes(streams
, nstreams
, spec
);
432 calc_linear_integer_volume(linear
, volume
);
438 for (i
= 0; i
< nstreams
; i
++) {
439 pa_mix_info
*m
= streams
+ i
;
440 int32_t v
, cv
= m
->linear
[channel
].i
;
442 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
445 v
= (int32_t) st_alaw2linear16(*((uint8_t*) m
->ptr
));
446 v
= (v
* cv
) / 0x10000;
450 m
->ptr
= (uint8_t*) m
->ptr
+ 1;
453 sum
= (sum
* linear
[channel
]) / 0x10000;
454 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
455 *((uint8_t*) data
) = (uint8_t) st_13linear2alaw((int16_t) sum
>> 3);
457 data
= (uint8_t*) data
+ 1;
459 if (PA_UNLIKELY(++channel
>= spec
->channels
))
466 case PA_SAMPLE_FLOAT32NE
: {
467 unsigned channel
= 0;
468 float linear
[PA_CHANNELS_MAX
];
470 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
471 calc_linear_float_volume(linear
, volume
);
477 for (i
= 0; i
< nstreams
; i
++) {
478 pa_mix_info
*m
= streams
+ i
;
479 float v
, cv
= m
->linear
[channel
].f
;
481 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
484 v
= *((float*) m
->ptr
);
489 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
492 sum
*= linear
[channel
];
493 *((float*) data
) = sum
;
495 data
= (uint8_t*) data
+ sizeof(float);
497 if (PA_UNLIKELY(++channel
>= spec
->channels
))
504 case PA_SAMPLE_FLOAT32RE
: {
505 unsigned channel
= 0;
506 float linear
[PA_CHANNELS_MAX
];
508 calc_linear_float_stream_volumes(streams
, nstreams
, spec
);
509 calc_linear_float_volume(linear
, volume
);
515 for (i
= 0; i
< nstreams
; i
++) {
516 pa_mix_info
*m
= streams
+ i
;
517 float v
, cv
= m
->linear
[channel
].f
;
519 if (PA_UNLIKELY(cv
<= 0) || PA_UNLIKELY(linear
[channel
] <= 0))
522 v
= PA_FLOAT32_SWAP(*(float*) m
->ptr
) *cv
;
525 m
->ptr
= (uint8_t*) m
->ptr
+ sizeof(float);
528 sum
*= linear
[channel
];
529 *((float*) data
) = PA_FLOAT32_SWAP(sum
);
531 data
= (uint8_t*) data
+ sizeof(float);
533 if (PA_UNLIKELY(++channel
>= spec
->channels
))
541 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
542 pa_assert_not_reached();
545 for (k
= 0; k
< nstreams
; k
++)
546 pa_memblock_release(streams
[k
].chunk
.memblock
);
552 void pa_volume_memchunk(
554 const pa_sample_spec
*spec
,
555 const pa_cvolume
*volume
) {
561 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
564 if (pa_memblock_is_silence(c
->memblock
))
567 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
570 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
571 pa_silence_memchunk(c
, spec
);
575 ptr
= (uint8_t*) pa_memblock_acquire(c
->memblock
) + c
->index
;
577 switch (spec
->format
) {
579 case PA_SAMPLE_S16NE
: {
582 int32_t linear
[PA_CHANNELS_MAX
];
584 calc_linear_integer_volume(linear
, volume
);
586 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
588 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
592 t
= (t
* linear
[channel
]) / 0x10000;
593 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
596 if (PA_UNLIKELY(++channel
>= spec
->channels
))
602 case PA_SAMPLE_S16RE
: {
605 int32_t linear
[PA_CHANNELS_MAX
];
607 calc_linear_integer_volume(linear
, volume
);
609 e
= (int16_t*) ptr
+ c
->length
/sizeof(int16_t);
611 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
614 t
= (int32_t) PA_INT16_SWAP(*d
);
615 t
= (t
* linear
[channel
]) / 0x10000;
616 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
617 *d
= PA_INT16_SWAP((int16_t) t
);
619 if (PA_UNLIKELY(++channel
>= spec
->channels
))
626 case PA_SAMPLE_S32NE
: {
629 int32_t linear
[PA_CHANNELS_MAX
];
631 calc_linear_integer_volume(linear
, volume
);
633 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
635 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
639 t
= (t
* linear
[channel
]) / 0x10000;
640 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
643 if (PA_UNLIKELY(++channel
>= spec
->channels
))
649 case PA_SAMPLE_S32RE
: {
652 int32_t linear
[PA_CHANNELS_MAX
];
654 calc_linear_integer_volume(linear
, volume
);
656 e
= (int32_t*) ptr
+ c
->length
/sizeof(int32_t);
658 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
661 t
= (int64_t) PA_INT32_SWAP(*d
);
662 t
= (t
* linear
[channel
]) / 0x10000;
663 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
664 *d
= PA_INT32_SWAP((int32_t) t
);
666 if (PA_UNLIKELY(++channel
>= spec
->channels
))
676 int32_t linear
[PA_CHANNELS_MAX
];
678 calc_linear_integer_volume(linear
, volume
);
680 e
= (uint8_t*) ptr
+ c
->length
;
682 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
685 t
= (int32_t) *d
- 0x80;
686 t
= (t
* linear
[channel
]) / 0x10000;
687 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
688 *d
= (uint8_t) (t
+ 0x80);
690 if (PA_UNLIKELY(++channel
>= spec
->channels
))
696 case PA_SAMPLE_ULAW
: {
699 int32_t linear
[PA_CHANNELS_MAX
];
701 calc_linear_integer_volume(linear
, volume
);
703 e
= (uint8_t*) ptr
+ c
->length
;
705 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
708 t
= (int32_t) st_ulaw2linear16(*d
);
709 t
= (t
* linear
[channel
]) / 0x10000;
710 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
711 *d
= (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
713 if (PA_UNLIKELY(++channel
>= spec
->channels
))
719 case PA_SAMPLE_ALAW
: {
722 int32_t linear
[PA_CHANNELS_MAX
];
724 calc_linear_integer_volume(linear
, volume
);
726 e
= (uint8_t*) ptr
+ c
->length
;
728 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
731 t
= (int32_t) st_alaw2linear16(*d
);
732 t
= (t
* linear
[channel
]) / 0x10000;
733 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
734 *d
= (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
736 if (PA_UNLIKELY(++channel
>= spec
->channels
))
742 case PA_SAMPLE_FLOAT32NE
: {
749 skip
= (int) (spec
->channels
* sizeof(float));
750 n
= (unsigned) (c
->length
/sizeof(float)/spec
->channels
);
752 for (channel
= 0; channel
< spec
->channels
; channel
++) {
755 if (PA_UNLIKELY(volume
->values
[channel
] == PA_VOLUME_NORM
))
758 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
760 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, (int) n
);
765 case PA_SAMPLE_FLOAT32RE
: {
768 float linear
[PA_CHANNELS_MAX
];
770 calc_linear_float_volume(linear
, volume
);
772 e
= (float*) ptr
+ c
->length
/sizeof(float);
774 for (channel
= 0, d
= ptr
; d
< e
; d
++) {
777 t
= PA_FLOAT32_SWAP(*d
);
778 t
*= linear
[channel
];
779 *d
= PA_FLOAT32_SWAP(t
);
781 if (PA_UNLIKELY(++channel
>= spec
->channels
))
790 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
791 /* If we cannot change the volume, we just don't do it */
794 pa_memblock_release(c
->memblock
);
797 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
802 fs
= pa_frame_size(ss
);
807 int pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
812 fs
= pa_frame_size(ss
);
817 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
822 pa_assert(channels
> 0);
829 for (c
= 0; c
< channels
; c
++) {
835 d
= (uint8_t*) dst
+ c
* ss
;
837 for (j
= 0; j
< n
; j
++) {
838 oil_memcpy(d
, s
, (int) ss
);
839 s
= (uint8_t*) s
+ ss
;
840 d
= (uint8_t*) d
+ fs
;
845 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
851 pa_assert(channels
> 0);
857 for (c
= 0; c
< channels
; c
++) {
862 s
= (uint8_t*) src
+ c
* ss
;
865 for (j
= 0; j
< n
; j
++) {
866 oil_memcpy(d
, s
, (int) ss
);
867 s
= (uint8_t*) s
+ fs
;
868 d
= (uint8_t*) d
+ ss
;
873 static pa_memblock
*silence_memblock_new(pa_mempool
*pool
, uint8_t c
) {
880 length
= PA_MIN(pa_mempool_block_size_max(pool
), PA_SILENCE_MAX
);
882 b
= pa_memblock_new(pool
, length
);
884 data
= pa_memblock_acquire(b
);
885 memset(data
, c
, length
);
886 pa_memblock_release(b
);
888 pa_memblock_set_is_silence(b
, TRUE
);
893 void pa_silence_cache_init(pa_silence_cache
*cache
) {
896 memset(cache
, 0, sizeof(pa_silence_cache
));
899 void pa_silence_cache_done(pa_silence_cache
*cache
) {
900 pa_sample_format_t f
;
903 for (f
= 0; f
< PA_SAMPLE_MAX
; f
++)
904 if (cache
->blocks
[f
])
905 pa_memblock_unref(cache
->blocks
[f
]);
907 memset(cache
, 0, sizeof(pa_silence_cache
));
910 pa_memchunk
* pa_silence_memchunk_get(pa_silence_cache
*cache
, pa_mempool
*pool
, pa_memchunk
* ret
, const pa_sample_spec
*spec
, size_t length
) {
915 pa_assert(pa_sample_spec_valid(spec
));
917 if (!(b
= cache
->blocks
[spec
->format
]))
919 switch (spec
->format
) {
921 cache
->blocks
[PA_SAMPLE_U8
] = b
= silence_memblock_new(pool
, 0x80);
923 case PA_SAMPLE_S16LE
:
924 case PA_SAMPLE_S16BE
:
925 case PA_SAMPLE_S32LE
:
926 case PA_SAMPLE_S32BE
:
927 case PA_SAMPLE_FLOAT32LE
:
928 case PA_SAMPLE_FLOAT32BE
:
929 cache
->blocks
[PA_SAMPLE_S16LE
] = b
= silence_memblock_new(pool
, 0);
930 cache
->blocks
[PA_SAMPLE_S16BE
] = pa_memblock_ref(b
);
931 cache
->blocks
[PA_SAMPLE_S32LE
] = pa_memblock_ref(b
);
932 cache
->blocks
[PA_SAMPLE_S32BE
] = pa_memblock_ref(b
);
933 cache
->blocks
[PA_SAMPLE_FLOAT32LE
] = pa_memblock_ref(b
);
934 cache
->blocks
[PA_SAMPLE_FLOAT32BE
] = pa_memblock_ref(b
);
937 cache
->blocks
[PA_SAMPLE_ALAW
] = b
= silence_memblock_new(pool
, 0xd5);
940 cache
->blocks
[PA_SAMPLE_ULAW
] = b
= silence_memblock_new(pool
, 0xff);
943 pa_assert_not_reached();
948 ret
->memblock
= pa_memblock_ref(b
);
950 l
= pa_memblock_get_length(b
);
951 if (length
> l
|| length
== 0)
954 ret
->length
= pa_frame_align(length
, spec
);
960 void pa_sample_clamp(pa_sample_format_t format
, void *dst
, size_t dstr
, const void *src
, size_t sstr
, unsigned n
) {
966 if (format
== PA_SAMPLE_FLOAT32NE
) {
968 float minus_one
= -1.0, plus_one
= 1.0;
969 oil_clip_f32(d
, (int) dstr
, s
, (int) sstr
, (int) n
, &minus_one
, &plus_one
);
972 pa_assert(format
== PA_SAMPLE_FLOAT32RE
);
977 f
= PA_FLOAT32_SWAP(*s
);
978 f
= PA_CLAMP_UNLIKELY(f
, -1.0f
, 1.0f
);
979 *d
= PA_FLOAT32_SWAP(f
);
981 s
= (const float*) ((const uint8_t*) s
+ sstr
);
982 d
= (float*) ((uint8_t*) d
+ dstr
);
987 /* Similar to pa_bytes_to_usec() but rounds up, not down */
989 pa_usec_t
pa_bytes_to_usec_round_up(uint64_t length
, const pa_sample_spec
*spec
) {
995 fs
= pa_frame_size(spec
);
996 length
= (length
+ fs
- 1) / fs
;
998 usec
= (pa_usec_t
) length
* PA_USEC_PER_SEC
;
1000 return (usec
+ spec
->rate
- 1) / spec
->rate
;
1003 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1005 size_t pa_usec_to_bytes_round_up(pa_usec_t t
, const pa_sample_spec
*spec
) {
1009 u
= (uint64_t) t
* (uint64_t) spec
->rate
;
1011 u
= (u
+ PA_USEC_PER_SEC
- 1) / PA_USEC_PER_SEC
;
1013 u
*= pa_frame_size(spec
);