]>
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>
35 #include <pulsecore/log.h>
36 #include <pulsecore/macro.h>
38 #include "sample-util.h"
39 #include "endianmacros.h"
41 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
43 pa_memblock
*pa_silence_memblock_new(pa_mempool
*pool
, const pa_sample_spec
*spec
, size_t length
) {
49 length
= pa_bytes_per_second(spec
)/20; /* 50 ms */
51 if (length
> PA_SILENCE_MAX
)
52 length
= PA_SILENCE_MAX
;
54 fs
= pa_frame_size(spec
);
56 length
= (length
+fs
-1)/fs
;
63 return pa_silence_memblock(pa_memblock_new(pool
, length
), spec
);
66 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
72 data
= pa_memblock_acquire(b
);
73 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
74 pa_memblock_release(b
);
78 void pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
82 pa_assert(c
->memblock
);
85 data
= pa_memblock_acquire(c
->memblock
);
86 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
87 pa_memblock_release(c
->memblock
);
90 void pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
93 pa_assert(length
> 0);
96 switch (spec
->format
) {
100 case PA_SAMPLE_S16LE
:
101 case PA_SAMPLE_S16BE
:
102 case PA_SAMPLE_FLOAT32
:
103 case PA_SAMPLE_FLOAT32RE
:
113 pa_assert_not_reached();
116 memset(p
, c
, length
);
120 pa_mix_info streams
[],
124 const pa_sample_spec
*spec
,
125 const pa_cvolume
*volume
,
128 pa_cvolume full_volume
;
138 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
140 for (k
= 0; k
< nstreams
; k
++)
141 streams
[k
].internal
= pa_memblock_acquire(streams
[k
].chunk
.memblock
);
143 switch (spec
->format
) {
144 case PA_SAMPLE_S16NE
:{
145 unsigned channel
= 0;
147 for (d
= 0;; d
+= sizeof(int16_t)) {
153 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
156 for (i
= 0; i
< nstreams
; i
++) {
158 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
160 if (d
>= streams
[i
].chunk
.length
)
163 if (cvolume
== PA_VOLUME_MUTED
)
166 v
= *((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
168 if (cvolume
!= PA_VOLUME_NORM
)
169 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
175 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
176 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
178 sum
= CLAMP(sum
, -0x8000, 0x7FFF);
181 *((int16_t*) data
) = (int16_t) sum
;
182 data
= (uint8_t*) data
+ sizeof(int16_t);
184 if (++channel
>= spec
->channels
)
191 case PA_SAMPLE_S16RE
:{
192 unsigned channel
= 0;
194 for (d
= 0;; d
+= sizeof(int16_t)) {
200 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
203 for (i
= 0; i
< nstreams
; i
++) {
205 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
207 if (d
>= streams
[i
].chunk
.length
)
210 if (cvolume
== PA_VOLUME_MUTED
)
213 v
= PA_INT16_SWAP(*((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
)));
215 if (cvolume
!= PA_VOLUME_NORM
)
216 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
222 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
223 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
225 sum
= CLAMP(sum
, -0x8000, 0x7FFF);
228 *((int16_t*) data
) = PA_INT16_SWAP((int16_t) sum
);
229 data
= (uint8_t*) data
+ sizeof(int16_t);
231 if (++channel
>= spec
->channels
)
239 unsigned channel
= 0;
247 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
250 for (i
= 0; i
< nstreams
; i
++) {
252 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
254 if (d
>= streams
[i
].chunk
.length
)
257 if (cvolume
== PA_VOLUME_MUTED
)
260 v
= (int32_t) *((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
) - 0x80;
262 if (cvolume
!= PA_VOLUME_NORM
)
263 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
269 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
270 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
272 sum
= CLAMP(sum
, -0x80, 0x7F);
275 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
276 data
= (uint8_t*) data
+ 1;
278 if (++channel
>= spec
->channels
)
285 case PA_SAMPLE_FLOAT32NE
: {
286 unsigned channel
= 0;
288 for (d
= 0;; d
+= sizeof(float)) {
294 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
297 for (i
= 0; i
< nstreams
; i
++) {
299 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
301 if (d
>= streams
[i
].chunk
.length
)
304 if (cvolume
== PA_VOLUME_MUTED
)
307 v
= *((float*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
309 if (cvolume
!= PA_VOLUME_NORM
)
310 v
*= pa_sw_volume_to_linear(cvolume
);
316 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
317 sum
*= pa_sw_volume_to_linear(volume
->values
[channel
]);
320 *((float*) data
) = sum
;
321 data
= (uint8_t*) data
+ sizeof(float);
323 if (++channel
>= spec
->channels
)
331 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
337 for (k
= 0; k
< nstreams
; k
++)
338 pa_memblock_release(streams
[k
].chunk
.memblock
);
344 void pa_volume_memchunk(
346 const pa_sample_spec
*spec
,
347 const pa_cvolume
*volume
) {
353 pa_assert(c
->length
% pa_frame_size(spec
) == 0);
356 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
359 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
360 pa_silence_memchunk(c
, spec
);
364 ptr
= pa_memblock_acquire(c
->memblock
);
366 switch (spec
->format
) {
368 case PA_SAMPLE_S16NE
: {
372 int32_t linear
[PA_CHANNELS_MAX
];
374 for (channel
= 0; channel
< spec
->channels
; channel
++)
375 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
377 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
381 t
= (t
* linear
[channel
]) / 0x10000;
382 t
= CLAMP(t
, -0x8000, 0x7FFF);
385 if (++channel
>= spec
->channels
)
391 case PA_SAMPLE_S16RE
: {
395 int32_t linear
[PA_CHANNELS_MAX
];
397 for (channel
= 0; channel
< spec
->channels
; channel
++)
398 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
400 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
403 t
= (int32_t)(PA_INT16_SWAP(*d
));
404 t
= (t
* linear
[channel
]) / 0x10000;
405 t
= CLAMP(t
, -0x8000, 0x7FFF);
406 *d
= PA_INT16_SWAP((int16_t) t
);
408 if (++channel
>= spec
->channels
)
419 int32_t linear
[PA_CHANNELS_MAX
];
421 for (channel
= 0; channel
< spec
->channels
; channel
++)
422 linear
[channel
] = (int32_t) (pa_sw_volume_to_linear(volume
->values
[channel
]) * 0x10000);
424 for (channel
= 0, d
= (uint8_t*) ptr
+ c
->index
, n
= c
->length
; n
> 0; d
++, n
--) {
427 t
= (int32_t) *d
- 0x80;
428 t
= (t
* linear
[channel
]) / 0x10000;
429 t
= CLAMP(t
, -0x80, 0x7F);
430 *d
= (uint8_t) (t
+ 0x80);
432 if (++channel
>= spec
->channels
)
438 case PA_SAMPLE_FLOAT32NE
: {
444 d
= (float*) ((uint8_t*) ptr
+ c
->index
);
445 skip
= spec
->channels
* sizeof(float);
446 n
= c
->length
/sizeof(float)/spec
->channels
;
448 for (channel
= 0; channel
< spec
->channels
; channel
++) {
451 if (volume
->values
[channel
] == PA_VOLUME_NORM
)
454 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
456 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
462 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec
->format
));
463 /* If we cannot change the volume, we just don't do it */
466 pa_memblock_release(c
->memblock
);
469 size_t pa_frame_align(size_t l
, const pa_sample_spec
*ss
) {
474 fs
= pa_frame_size(ss
);
479 int pa_frame_aligned(size_t l
, const pa_sample_spec
*ss
) {
484 fs
= pa_frame_size(ss
);