]>
code.delx.au - pulseaudio/blob - src/pulsecore/sample-util.c
4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
33 #include <liboil/liboilfuncs.h>
34 #include <liboil/liboil.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/macro.h>
39 #include "sample-util.h"
40 #include "endianmacros.h"
42 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
44 pa_memblock
*pa_silence_memblock_new(pa_mempool
*pool
, const pa_sample_spec
*spec
, size_t length
) {
50 length
= pa_bytes_per_second(spec
)/20; /* 50 ms */
52 if (length
> PA_SILENCE_MAX
)
53 length
= PA_SILENCE_MAX
;
55 fs
= pa_frame_size(spec
);
57 length
= (length
+fs
-1)/fs
;
64 return pa_silence_memblock(pa_memblock_new(pool
, length
), spec
);
67 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
73 data
= pa_memblock_acquire(b
);
74 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
75 pa_memblock_release(b
);
79 void pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
83 pa_assert(c
->memblock
);
86 data
= pa_memblock_acquire(c
->memblock
);
87 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
88 pa_memblock_release(c
->memblock
);
91 void pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
94 pa_assert(length
> 0);
97 switch (spec
->format
) {
101 case PA_SAMPLE_S16LE
:
102 case PA_SAMPLE_S16BE
:
103 case PA_SAMPLE_S32LE
:
104 case PA_SAMPLE_S32BE
:
105 case PA_SAMPLE_FLOAT32
:
106 case PA_SAMPLE_FLOAT32RE
:
116 pa_assert_not_reached();
119 memset(p
, c
, length
);
123 pa_mix_info streams
[],
127 const pa_sample_spec
*spec
,
128 const pa_cvolume
*volume
,
131 pa_cvolume full_volume
;
141 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
143 for (k
= 0; k
< nstreams
; k
++)
144 streams
[k
].internal
= pa_memblock_acquire(streams
[k
].chunk
.memblock
);
146 switch (spec
->format
) {
147 case PA_SAMPLE_S16NE
:{
148 unsigned channel
= 0;
150 for (d
= 0;; d
+= sizeof(int16_t)) {
156 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
159 for (i
= 0; i
< nstreams
; i
++) {
161 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
163 if (d
>= streams
[i
].chunk
.length
)
166 if (cvolume
== PA_VOLUME_MUTED
)
169 v
= *((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
171 if (cvolume
!= PA_VOLUME_NORM
)
172 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
178 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
179 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
181 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
184 *((int16_t*) data
) = (int16_t) sum
;
185 data
= (uint8_t*) data
+ sizeof(int16_t);
187 if (++channel
>= spec
->channels
)
194 case PA_SAMPLE_S16RE
:{
195 unsigned channel
= 0;
197 for (d
= 0;; d
+= sizeof(int16_t)) {
203 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
206 for (i
= 0; i
< nstreams
; i
++) {
208 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
210 if (d
>= streams
[i
].chunk
.length
)
213 if (cvolume
== PA_VOLUME_MUTED
)
216 v
= PA_INT16_SWAP(*((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
)));
218 if (cvolume
!= PA_VOLUME_NORM
)
219 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
225 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
226 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
228 sum
= PA_CLAMP_UNLIKELY(sum
, -0x8000, 0x7FFF);
231 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
232 data
= (uint8_t*) data
+ sizeof(int16_t);
234 if (++channel
>= spec
->channels
)
242 unsigned channel
= 0;
250 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
253 for (i
= 0; i
< nstreams
; i
++) {
255 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
257 if (d
>= streams
[i
].chunk
.length
)
260 if (cvolume
== PA_VOLUME_MUTED
)
263 v
= (int32_t) *((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
) - 0x80;
265 if (cvolume
!= PA_VOLUME_NORM
)
266 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
272 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
273 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
275 sum
= PA_CLAMP_UNLIKELY(sum
, -0x80, 0x7F);
278 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
279 data
= (uint8_t*) data
+ 1;
281 if (++channel
>= spec
->channels
)
288 case PA_SAMPLE_FLOAT32NE
: {
289 unsigned channel
= 0;
291 for (d
= 0;; d
+= sizeof(float)) {
297 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
300 for (i
= 0; i
< nstreams
; i
++) {
302 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
304 if (d
>= streams
[i
].chunk
.length
)
307 if (cvolume
== PA_VOLUME_MUTED
)
310 v
= *((float*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
312 if (cvolume
!= PA_VOLUME_NORM
)
313 v
*= pa_sw_volume_to_linear(cvolume
);
319 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
320 sum
*= pa_sw_volume_to_linear(volume
->values
[channel
]);
323 *((float*) data
) = sum
;
324 data
= (uint8_t*) data
+ sizeof(float);
326 if (++channel
>= spec
->channels
)
334 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
340 for (k
= 0; k
< nstreams
; k
++)
341 pa_memblock_release(streams
[k
].chunk
.memblock
);
347 void pa_volume_memchunk(
349 const pa_sample_spec
*spec
,
350 const pa_cvolume
*volume
) {
356 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
359 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
362 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
363 pa_silence_memchunk(c
, spec
);
367 ptr
= pa_memblock_acquire(c
->memblock
);
369 switch (spec
->format
) {
371 case PA_SAMPLE_S16NE
: {
375 int32_t linear
[PA_CHANNELS_MAX
];
377 for (channel
= 0; channel
< spec
->channels
; channel
++)
378 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
380 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
384 t
= (t
* linear
[channel
]) / 0x10000;
385 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
388 if (PA_UNLIKELY(++channel
>= spec
->channels
))
394 case PA_SAMPLE_S16RE
: {
398 int32_t linear
[PA_CHANNELS_MAX
];
400 for (channel
= 0; channel
< spec
->channels
; channel
++)
401 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
403 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
406 t
= (int32_t)(PA_INT16_SWAP(*d
));
407 t
= (t
* linear
[channel
]) / 0x10000;
408 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
409 *d
= PA_INT16_SWAP((int16_t) t
);
411 if (PA_UNLIKELY(++channel
>= spec
->channels
))
418 case PA_SAMPLE_S32NE
: {
422 int32_t linear
[PA_CHANNELS_MAX
];
424 for (channel
= 0; channel
< spec
->channels
; channel
++)
425 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
427 for (channel
= 0, d
= (int32_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
431 t
= (t
* linear
[channel
]) / 0x10000;
432 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
435 if (PA_UNLIKELY(++channel
>= spec
->channels
))
441 case PA_SAMPLE_S32RE
: {
445 int32_t linear
[PA_CHANNELS_MAX
];
447 for (channel
= 0; channel
< spec
->channels
; channel
++)
448 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
450 for (channel
= 0, d
= (int32_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int32_t); n
> 0; d
++, n
--) {
453 t
= (int64_t)(PA_INT32_SWAP(*d
));
454 t
= (t
* linear
[channel
]) / 0x10000;
455 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
456 *d
= PA_INT32_SWAP((int32_t) t
);
458 if (PA_UNLIKELY(++channel
>= spec
->channels
))
469 int32_t linear
[PA_CHANNELS_MAX
];
471 for (channel
= 0; channel
< spec
->channels
; channel
++)
472 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
474 for (channel
= 0, d
= (uint8_t*) ptr
+ c
->index
, n
= c
->length
; n
> 0; d
++, n
--) {
477 t
= (int32_t) *d
- 0x80;
478 t
= (t
* linear
[channel
]) / 0x10000;
479 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
480 *d
= (uint8_t) (t
+ 0x80);
482 if (PA_UNLIKELY(++channel
>= spec
->channels
))
488 case PA_SAMPLE_FLOAT32NE
: {
494 d
= (float*) ((uint8_t*) ptr
+ c
->index
);
495 skip
= spec
->channels
* sizeof(float);
496 n
= c
->length
/sizeof(float)/spec
->channels
;
498 for (channel
= 0; channel
< spec
->channels
; channel
++) {
501 if (volume
->values
[channel
] == PA_VOLUME_NORM
)
504 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
506 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
512 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
513 /* If we cannot change the volume, we just don't do it */
516 pa_memblock_release(c
->memblock
);
519 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
524 fs
= pa_frame_size(ss
);
529 int pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
534 fs
= pa_frame_size(ss
);
539 void pa_interleave(const void *src
[], unsigned channels
, void *dst
, size_t ss
, unsigned n
) {
544 pa_assert(channels
> 0);
551 for (c
= 0; c
< channels
; c
++) {
557 d
= (uint8_t*) dst
+ c
* ss
;
559 for (j
= 0; j
< n
; j
++) {
560 oil_memcpy(d
, s
, ss
);
561 s
= (uint8_t*) s
+ ss
;
562 d
= (uint8_t*) d
+ fs
;
567 void pa_deinterleave(const void *src
, void *dst
[], unsigned channels
, size_t ss
, unsigned n
) {
573 pa_assert(channels
> 0);
579 for (c
= 0; c
< channels
; c
++) {
584 s
= (uint8_t*) src
+ c
* ss
;
587 for (j
= 0; j
< n
; j
++) {
588 oil_memcpy(d
, s
, ss
);
589 s
= (uint8_t*) s
+ fs
;
590 d
= (uint8_t*) d
+ ss
;