]>
code.delx.au - pulseaudio/blob - src/pulsecore/sample-util.c
4 This file is part of PulseAudio.
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
11 PulseAudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <liboil/liboilfuncs.h>
33 #include <pulsecore/log.h>
35 #include "sample-util.h"
36 #include "endianmacros.h"
38 pa_memblock
*pa_silence_memblock_new(pa_mempool
*pool
, const pa_sample_spec
*spec
, size_t length
) {
43 length
= pa_bytes_per_second(spec
)/20; /* 50 ms */
45 return pa_silence_memblock(pa_memblock_new(pool
, length
), spec
);
48 pa_memblock
*pa_silence_memblock(pa_memblock
* b
, const pa_sample_spec
*spec
) {
54 data
= pa_memblock_acquire(b
);
55 pa_silence_memory(data
, pa_memblock_get_length(b
), spec
);
56 pa_memblock_release(b
);
60 void pa_silence_memchunk(pa_memchunk
*c
, const pa_sample_spec
*spec
) {
67 data
= pa_memblock_acquire(c
->memblock
);
68 pa_silence_memory((uint8_t*) data
+c
->index
, c
->length
, spec
);
69 pa_memblock_release(c
->memblock
);
72 void pa_silence_memory(void *p
, size_t length
, const pa_sample_spec
*spec
) {
74 assert(p
&& length
&& spec
);
76 switch (spec
->format
) {
82 case PA_SAMPLE_FLOAT32
:
97 pa_mix_info streams
[],
101 const pa_sample_spec
*spec
,
102 const pa_cvolume
*volume
,
105 pa_cvolume full_volume
;
115 volume
= pa_cvolume_reset(&full_volume
, spec
->channels
);
117 for (k
= 0; k
< nstreams
; k
++)
118 streams
[k
].internal
= pa_memblock_acquire(streams
[k
].chunk
.memblock
);
120 switch (spec
->format
) {
121 case PA_SAMPLE_S16NE
:{
122 unsigned channel
= 0;
124 for (d
= 0;; d
+= sizeof(int16_t)) {
130 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
133 for (i
= 0; i
< nstreams
; i
++) {
135 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
137 if (d
>= streams
[i
].chunk
.length
)
140 if (cvolume
== PA_VOLUME_MUTED
)
143 v
= *((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
145 if (cvolume
!= PA_VOLUME_NORM
)
146 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
152 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
153 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
155 if (sum
< -0x8000) sum
= -0x8000;
156 if (sum
> 0x7FFF) sum
= 0x7FFF;
160 *((int16_t*) data
) = sum
;
161 data
= (uint8_t*) data
+ sizeof(int16_t);
163 if (++channel
>= spec
->channels
)
170 case PA_SAMPLE_S16RE
:{
171 unsigned channel
= 0;
173 for (d
= 0;; d
+= sizeof(int16_t)) {
179 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
182 for (i
= 0; i
< nstreams
; i
++) {
184 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
186 if (d
>= streams
[i
].chunk
.length
)
189 if (cvolume
== PA_VOLUME_MUTED
)
192 v
= INT16_SWAP(*((int16_t*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
)));
194 if (cvolume
!= PA_VOLUME_NORM
)
195 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
201 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
202 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
204 if (sum
< -0x8000) sum
= -0x8000;
205 if (sum
> 0x7FFF) sum
= 0x7FFF;
209 *((int16_t*) data
) = INT16_SWAP(sum
);
210 data
= (uint8_t*) data
+ sizeof(int16_t);
212 if (++channel
>= spec
->channels
)
220 unsigned channel
= 0;
228 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
231 for (i
= 0; i
< nstreams
; i
++) {
233 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
235 if (d
>= streams
[i
].chunk
.length
)
238 if (cvolume
== PA_VOLUME_MUTED
)
241 v
= (int32_t) *((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
) - 0x80;
243 if (cvolume
!= PA_VOLUME_NORM
)
244 v
= (int32_t) (v
* pa_sw_volume_to_linear(cvolume
));
250 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
251 sum
= (int32_t) (sum
* pa_sw_volume_to_linear(volume
->values
[channel
]));
253 if (sum
< -0x80) sum
= -0x80;
254 if (sum
> 0x7F) sum
= 0x7F;
258 *((uint8_t*) data
) = (uint8_t) (sum
+ 0x80);
259 data
= (uint8_t*) data
+ 1;
261 if (++channel
>= spec
->channels
)
268 case PA_SAMPLE_FLOAT32NE
: {
269 unsigned channel
= 0;
271 for (d
= 0;; d
+= sizeof(float)) {
277 if (!mute
&& volume
->values
[channel
] != PA_VOLUME_MUTED
) {
280 for (i
= 0; i
< nstreams
; i
++) {
282 pa_volume_t cvolume
= streams
[i
].volume
.values
[channel
];
284 if (d
>= streams
[i
].chunk
.length
)
287 if (cvolume
== PA_VOLUME_MUTED
)
290 v
= *((float*) ((uint8_t*) streams
[i
].internal
+ streams
[i
].chunk
.index
+ d
));
292 if (cvolume
!= PA_VOLUME_NORM
)
293 v
*= pa_sw_volume_to_linear(cvolume
);
299 if (volume
->values
[channel
] != PA_VOLUME_NORM
)
300 sum
*= pa_sw_volume_to_linear(volume
->values
[channel
]);
303 *((float*) data
) = sum
;
304 data
= (uint8_t*) data
+ sizeof(float);
306 if (++channel
>= spec
->channels
)
314 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec
->format
));
320 for (k
= 0; k
< nstreams
; k
++)
321 pa_memblock_release(streams
[k
].chunk
.memblock
);
327 void pa_volume_memchunk(
329 const pa_sample_spec
*spec
,
330 const pa_cvolume
*volume
) {
336 assert(c
->length
% pa_frame_size(spec
) == 0);
339 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_NORM
))
342 if (pa_cvolume_channels_equal_to(volume
, PA_VOLUME_MUTED
)) {
343 pa_silence_memchunk(c
, spec
);
347 ptr
= pa_memblock_acquire(c
->memblock
);
349 switch (spec
->format
) {
350 case PA_SAMPLE_S16NE
: {
354 double linear
[PA_CHANNELS_MAX
];
356 for (channel
= 0; channel
< spec
->channels
; channel
++)
357 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
359 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
360 int32_t t
= (int32_t)(*d
);
362 t
= (int32_t) (t
* linear
[channel
]);
364 if (t
< -0x8000) t
= -0x8000;
365 if (t
> 0x7FFF) t
= 0x7FFF;
369 if (++channel
>= spec
->channels
)
375 case PA_SAMPLE_S16RE
: {
379 double linear
[PA_CHANNELS_MAX
];
381 for (channel
= 0; channel
< spec
->channels
; channel
++)
382 linear
[channel
] = pa_sw_volume_to_linear(volume
->values
[channel
]);
384 for (channel
= 0, d
= (int16_t*) ((uint8_t*) ptr
+ c
->index
), n
= c
->length
/sizeof(int16_t); n
> 0; d
++, n
--) {
385 int32_t t
= (int32_t)(INT16_SWAP(*d
));
387 t
= (int32_t) (t
* linear
[channel
]);
389 if (t
< -0x8000) t
= -0x8000;
390 if (t
> 0x7FFF) t
= 0x7FFF;
392 *d
= INT16_SWAP((int16_t) t
);
394 if (++channel
>= spec
->channels
)
404 unsigned channel
= 0;
406 for (d
= (uint8_t*) ptr
+ c
->index
, n
= c
->length
; n
> 0; d
++, n
--) {
407 int32_t t
= (int32_t) *d
- 0x80;
409 t
= (int32_t) (t
* pa_sw_volume_to_linear(volume
->values
[channel
]));
411 if (t
< -0x80) t
= -0x80;
412 if (t
> 0x7F) t
= 0x7F;
414 *d
= (uint8_t) (t
+ 0x80);
416 if (++channel
>= spec
->channels
)
422 case PA_SAMPLE_FLOAT32NE
: {
428 d
= (float*) ((uint8_t*) ptr
+ c
->index
);
429 skip
= spec
->channels
* sizeof(float);
430 n
= c
->length
/sizeof(float)/spec
->channels
;
432 for (channel
= 0; channel
< spec
->channels
; channel
++) {
435 if (volume
->values
[channel
] == PA_VOLUME_NORM
)
438 v
= (float) pa_sw_volume_to_linear(volume
->values
[channel
]);
441 oil_scalarmult_f32(t
, skip
, t
, skip
, &v
, n
);
447 pa_log_error("ERROR: Unable to change volume of format %s.",
448 pa_sample_format_to_string(spec
->format
));
452 pa_memblock_release(c
->memblock
);