]>
code.delx.au - pulseaudio/blob - src/pulsecore/sample-util.c
a99714080b97d4114e7c4a699206cfbdd4d7e5b1
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
34 #include <liboil/liboilfuncs.h>
36 #include <pulsecore/log.h>
38 #include "sample-util.h"
39 #include "endianmacros.h"
41 #define PA_SILENCE_MAX (1024*1024*1)
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
);
55 length
= ((PA_SILENCE_MAX
+fs
-1) / fs
) * fs
;
60 return pa_silence_memblock(pa_memblock_new(pool
, length
), spec
);
63 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
64 assert(b
&& b
->data
&& spec
);
65 pa_silence_memory(b
->data
, b
->length
, spec
);
69 void pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
70 assert(c
&& c
->memblock
&& c
->memblock
->data
&& spec
&& c
->length
);
72 pa_silence_memory((uint8_t*) c
->memblock
->data
+c
->index
, c
->length
, spec
);
75 void pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
77 assert(p
&& length
&& spec
);
79 switch (spec
->format
) {
85 case PA_SAMPLE_FLOAT32
:
86 case PA_SAMPLE_FLOAT32RE
:
101 const pa_mix_info streams
[],
105 const pa_sample_spec
*spec
,
106 const pa_cvolume
*volume
,
109 assert(streams
&& data
&& length
&& spec
);
111 switch (spec
->format
) {
112 case PA_SAMPLE_S16NE
:{
114 unsigned channel
= 0;
116 for (d
= 0;; d
+= sizeof(int16_t)) {
122 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
125 for (i
= 0; i
< nstreams
; i
++) {
127 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
129 if (d
>= streams
[i
].chunk
.length
)
132 if (cvolume
== PA_VOLUME_MUTED
)
135 v
= *((int16_t*) ((uint8_t*) streams
[i
].chunk
.memblock
->data
+ streams
[i
].chunk
.index
+ d
));
137 if (cvolume
!= PA_VOLUME_NORM
)
138 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
144 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
145 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
147 if (sum
< -0x8000) sum
= -0x8000;
148 if (sum
> 0x7FFF) sum
= 0x7FFF;
152 *((int16_t*) data
) = sum
;
153 data
= (uint8_t*) data
+ sizeof(int16_t);
155 if (++channel
>= spec
->channels
)
160 case PA_SAMPLE_S16RE
:{
162 unsigned channel
= 0;
164 for (d
= 0;; d
+= sizeof(int16_t)) {
170 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
173 for (i
= 0; i
< nstreams
; i
++) {
175 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
177 if (d
>= streams
[i
].chunk
.length
)
180 if (cvolume
== PA_VOLUME_MUTED
)
183 v
= INT16_SWAP(*((int16_t*) ((uint8_t*) streams
[i
].chunk
.memblock
->data
+ streams
[i
].chunk
.index
+ d
)));
185 if (cvolume
!= PA_VOLUME_NORM
)
186 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
192 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
193 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
195 if (sum
< -0x8000) sum
= -0x8000;
196 if (sum
> 0x7FFF) sum
= 0x7FFF;
200 *((int16_t*) data
) = INT16_SWAP(sum
);
201 data
= (uint8_t*) data
+ sizeof(int16_t);
203 if (++channel
>= spec
->channels
)
210 unsigned channel
= 0;
218 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
221 for (i
= 0; i
< nstreams
; i
++) {
223 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
225 if (d
>= streams
[i
].chunk
.length
)
228 if (cvolume
== PA_VOLUME_MUTED
)
231 v
= (int32_t) *((uint8_t*) streams
[i
].chunk
.memblock
->data
+ streams
[i
].chunk
.index
+ d
) - 0x80;
233 if (cvolume
!= PA_VOLUME_NORM
)
234 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
240 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
241 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
243 if (sum
< -0x80) sum
= -0x80;
244 if (sum
> 0x7F) sum
= 0x7F;
248 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
249 data
= (uint8_t*) data
+ 1;
251 if (++channel
>= spec
->channels
)
256 case PA_SAMPLE_FLOAT32NE
: {
258 unsigned channel
= 0;
260 for (d
= 0;; d
+= sizeof(float)) {
266 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
269 for (i
= 0; i
< nstreams
; i
++) {
271 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
273 if (d
>= streams
[i
].chunk
.length
)
276 if (cvolume
== PA_VOLUME_MUTED
)
279 v
= *((float*) ((uint8_t*) streams
[i
].chunk
.memblock
->data
+ streams
[i
].chunk
.index
+ d
));
281 if (cvolume
!= PA_VOLUME_NORM
)
282 v
*= pa_sw_volume_to_linear(cvolume
);
288 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
289 sum
*= pa_sw_volume_to_linear(volume
->values
[channel
]);
292 *((float*) data
) = sum
;
293 data
= (uint8_t*) data
+ sizeof(float);
295 if (++channel
>= spec
->channels
)
301 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
307 void pa_volume_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
, const pa_cvolume
*volume
) {
308 assert(c
&& spec
&& (c
->length
% pa_frame_size(spec
) == 0));
311 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
314 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
315 pa_silence_memchunk(c
, spec
);
319 switch (spec
->format
) {
320 case PA_SAMPLE_S16NE
: {
324 double linear
[PA_CHANNELS_MAX
];
326 for (channel
= 0; channel
< spec
->channels
; channel
++)
327 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
329 for (channel
= 0, d
= (int16_t*) ((uint8_t*) c
->memblock
->data
+c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
330 int32_t t
= (int32_t)(*d
);
332 t
= (int32_t) (t
* linear
[channel
]);
334 if (t
< -0x8000) t
= -0x8000;
335 if (t
> 0x7FFF) t
= 0x7FFF;
339 if (++channel
>= spec
->channels
)
345 case PA_SAMPLE_S16RE
: {
349 double linear
[PA_CHANNELS_MAX
];
351 for (channel
= 0; channel
< spec
->channels
; channel
++)
352 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
354 for (channel
= 0, d
= (int16_t*) ((uint8_t*) c
->memblock
->data
+c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
355 int32_t t
= (int32_t)(INT16_SWAP(*d
));
357 t
= (int32_t) (t
* linear
[channel
]);
359 if (t
< -0x8000) t
= -0x8000;
360 if (t
> 0x7FFF) t
= 0x7FFF;
362 *d
= INT16_SWAP((int16_t) t
);
364 if (++channel
>= spec
->channels
)
374 unsigned channel
= 0;
376 for (d
= (uint8_t*) c
->memblock
->data
+ c
->index
, n
= c
->length
; n
> 0; d
++, n
--) {
377 int32_t t
= (int32_t) *d
- 0x80;
379 t
= (int32_t) (t
* pa_sw_volume_to_linear(volume
->values
[channel
]));
381 if (t
< -0x80) t
= -0x80;
382 if (t
> 0x7F) t
= 0x7F;
384 *d
= (uint8_t) (t
+ 0x80);
386 if (++channel
>= spec
->channels
)
392 case PA_SAMPLE_FLOAT32NE
: {
398 d
= (float*) ((uint8_t*) c
->memblock
->data
+ c
->index
);
399 skip
= spec
->channels
* sizeof(float);
400 n
= c
->length
/sizeof(float)/spec
->channels
;
402 for (channel
= 0; channel
< spec
->channels
; channel
++) {
405 if (volume
->values
[channel
] == PA_VOLUME_NORM
)
408 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
411 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
417 pa_log_error("ERROR: Unable to change volume of format %s.",
418 pa_sample_format_to_string(spec
->format
));