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.1 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
28 #include <pulsecore/macro.h>
29 #include <pulsecore/g711.h>
30 #include <pulsecore/endianmacros.h>
32 #include "sample-util.h"
34 static void pa_volume_u8_c(uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
37 for (channel
= 0; length
; length
--) {
40 hi
= volumes
[channel
] >> 16;
41 lo
= volumes
[channel
] & 0xFFFF;
43 t
= (int32_t) *samples
- 0x80;
44 t
= ((t
* lo
) >> 16) + (t
* hi
);
45 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
46 *samples
++ = (uint8_t) (t
+ 0x80);
48 if (PA_UNLIKELY(++channel
>= channels
))
53 static void pa_volume_alaw_c(uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
56 for (channel
= 0; length
; length
--) {
59 hi
= volumes
[channel
] >> 16;
60 lo
= volumes
[channel
] & 0xFFFF;
62 t
= (int32_t) st_alaw2linear16(*samples
);
63 t
= ((t
* lo
) >> 16) + (t
* hi
);
64 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
65 *samples
++ = (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
67 if (PA_UNLIKELY(++channel
>= channels
))
72 static void pa_volume_ulaw_c(uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
75 for (channel
= 0; length
; length
--) {
78 hi
= volumes
[channel
] >> 16;
79 lo
= volumes
[channel
] & 0xFFFF;
81 t
= (int32_t) st_ulaw2linear16(*samples
);
82 t
= ((t
* lo
) >> 16) + (t
* hi
);
83 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
84 *samples
++ = (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
86 if (PA_UNLIKELY(++channel
>= channels
))
91 static void pa_volume_s16ne_c(int16_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
94 length
/= sizeof(int16_t);
96 for (channel
= 0; length
; length
--) {
99 /* Multiplying the 32bit volume factor with the 16bit
100 * sample might result in an 48bit value. We want to
101 * do without 64 bit integers and hence do the
102 * multiplication independantly for the HI and LO part
105 hi
= volumes
[channel
] >> 16;
106 lo
= volumes
[channel
] & 0xFFFF;
108 t
= (int32_t)(*samples
);
109 t
= ((t
* lo
) >> 16) + (t
* hi
);
110 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
111 *samples
++ = (int16_t) t
;
113 if (PA_UNLIKELY(++channel
>= channels
))
118 static void pa_volume_s16re_c(int16_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
121 length
/= sizeof(int16_t);
123 for (channel
= 0; length
; length
--) {
126 hi
= volumes
[channel
] >> 16;
127 lo
= volumes
[channel
] & 0xFFFF;
129 t
= (int32_t) PA_INT16_SWAP(*samples
);
130 t
= ((t
* lo
) >> 16) + (t
* hi
);
131 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
132 *samples
++ = PA_INT16_SWAP((int16_t) t
);
134 if (PA_UNLIKELY(++channel
>= channels
))
139 static void pa_volume_float32ne_c(float *samples
, float *volumes
, unsigned channels
, unsigned length
) {
142 length
/= sizeof(float);
144 for (channel
= 0; length
; length
--) {
145 *samples
++ *= volumes
[channel
];
147 if (PA_UNLIKELY(++channel
>= channels
))
152 static void pa_volume_float32re_c(float *samples
, float *volumes
, unsigned channels
, unsigned length
) {
155 length
/= sizeof(float);
157 for (channel
= 0; length
; length
--) {
160 t
= PA_FLOAT32_SWAP(*samples
);
161 t
*= volumes
[channel
];
162 *samples
++ = PA_FLOAT32_SWAP(t
);
164 if (PA_UNLIKELY(++channel
>= channels
))
169 static void pa_volume_s32ne_c(int32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
172 length
/= sizeof(int32_t);
174 for (channel
= 0; length
; length
--) {
177 t
= (int64_t)(*samples
);
178 t
= (t
* volumes
[channel
]) >> 16;
179 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
180 *samples
++ = (int32_t) t
;
182 if (PA_UNLIKELY(++channel
>= channels
))
187 static void pa_volume_s32re_c(int32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
190 length
/= sizeof(int32_t);
192 for (channel
= 0; length
; length
--) {
195 t
= (int64_t) PA_INT32_SWAP(*samples
);
196 t
= (t
* volumes
[channel
]) >> 16;
197 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
198 *samples
++ = PA_INT32_SWAP((int32_t) t
);
200 if (PA_UNLIKELY(++channel
>= channels
))
205 static void pa_volume_s24ne_c(uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
209 e
= samples
+ length
;
211 for (channel
= 0; samples
< e
; samples
+= 3) {
214 t
= (int64_t)((int32_t) (PA_READ24NE(samples
) << 8));
215 t
= (t
* volumes
[channel
]) >> 16;
216 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
217 PA_WRITE24NE(samples
, ((uint32_t) (int32_t) t
) >> 8);
219 if (PA_UNLIKELY(++channel
>= channels
))
224 static void pa_volume_s24re_c(uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
228 e
= samples
+ length
;
230 for (channel
= 0; samples
< e
; samples
+= 3) {
233 t
= (int64_t)((int32_t) (PA_READ24RE(samples
) << 8));
234 t
= (t
* volumes
[channel
]) >> 16;
235 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
236 PA_WRITE24RE(samples
, ((uint32_t) (int32_t) t
) >> 8);
238 if (PA_UNLIKELY(++channel
>= channels
))
243 static void pa_volume_s24_32ne_c(uint32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
246 length
/= sizeof(uint32_t);
248 for (channel
= 0; length
; length
--) {
251 t
= (int64_t) ((int32_t) (*samples
<< 8));
252 t
= (t
* volumes
[channel
]) >> 16;
253 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
254 *samples
++ = ((uint32_t) ((int32_t) t
)) >> 8;
256 if (PA_UNLIKELY(++channel
>= channels
))
261 static void pa_volume_s24_32re_c(uint32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
) {
264 length
/= sizeof(uint32_t);
266 for (channel
= 0; length
; length
--) {
269 t
= (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples
) << 8));
270 t
= (t
* volumes
[channel
]) >> 16;
271 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
272 *samples
++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t
)) >> 8);
274 if (PA_UNLIKELY(++channel
>= channels
))
279 static pa_do_volume_func_t do_volume_table
[] = {
280 [PA_SAMPLE_U8
] = (pa_do_volume_func_t
) pa_volume_u8_c
,
281 [PA_SAMPLE_ALAW
] = (pa_do_volume_func_t
) pa_volume_alaw_c
,
282 [PA_SAMPLE_ULAW
] = (pa_do_volume_func_t
) pa_volume_ulaw_c
,
283 [PA_SAMPLE_S16NE
] = (pa_do_volume_func_t
) pa_volume_s16ne_c
,
284 [PA_SAMPLE_S16RE
] = (pa_do_volume_func_t
) pa_volume_s16re_c
,
285 [PA_SAMPLE_FLOAT32NE
] = (pa_do_volume_func_t
) pa_volume_float32ne_c
,
286 [PA_SAMPLE_FLOAT32RE
] = (pa_do_volume_func_t
) pa_volume_float32re_c
,
287 [PA_SAMPLE_S32NE
] = (pa_do_volume_func_t
) pa_volume_s32ne_c
,
288 [PA_SAMPLE_S32RE
] = (pa_do_volume_func_t
) pa_volume_s32re_c
,
289 [PA_SAMPLE_S24NE
] = (pa_do_volume_func_t
) pa_volume_s24ne_c
,
290 [PA_SAMPLE_S24RE
] = (pa_do_volume_func_t
) pa_volume_s24re_c
,
291 [PA_SAMPLE_S24_32NE
] = (pa_do_volume_func_t
) pa_volume_s24_32ne_c
,
292 [PA_SAMPLE_S24_32RE
] = (pa_do_volume_func_t
) pa_volume_s24_32re_c
295 pa_do_volume_func_t
pa_get_volume_func(pa_sample_format_t f
) {
297 pa_assert(f
< PA_SAMPLE_MAX
);
299 return do_volume_table
[f
];
302 void pa_set_volume_func(pa_sample_format_t f
, pa_do_volume_func_t func
) {
304 pa_assert(f
< PA_SAMPLE_MAX
);
306 do_volume_table
[f
] = func
;