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/core-util.h>
32 #include "sample-util.h"
33 #include "endianmacros.h"
36 pa_volume_u8_c (uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
40 for (channel
= 0; length
; length
--) {
43 hi
= volumes
[channel
] >> 16;
44 lo
= volumes
[channel
] & 0xFFFF;
46 t
= (int32_t) *samples
- 0x80;
47 t
= ((t
* lo
) >> 16) + (t
* hi
);
48 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
49 *samples
++ = (uint8_t) (t
+ 0x80);
51 if (PA_UNLIKELY(++channel
>= channels
))
57 pa_volume_alaw_c (uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
61 for (channel
= 0; length
; length
--) {
64 hi
= volumes
[channel
] >> 16;
65 lo
= volumes
[channel
] & 0xFFFF;
67 t
= (int32_t) st_alaw2linear16(*samples
);
68 t
= ((t
* lo
) >> 16) + (t
* hi
);
69 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
70 *samples
++ = (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
72 if (PA_UNLIKELY(++channel
>= channels
))
78 pa_volume_ulaw_c (uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
82 for (channel
= 0; length
; length
--) {
85 hi
= volumes
[channel
] >> 16;
86 lo
= volumes
[channel
] & 0xFFFF;
88 t
= (int32_t) st_ulaw2linear16(*samples
);
89 t
= ((t
* lo
) >> 16) + (t
* hi
);
90 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
91 *samples
++ = (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
93 if (PA_UNLIKELY(++channel
>= channels
))
99 pa_volume_s16ne_c (int16_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
103 length
/= sizeof (int16_t);
105 for (channel
= 0; length
; length
--) {
108 /* Multiplying the 32bit volume factor with the 16bit
109 * sample might result in an 48bit value. We want to
110 * do without 64 bit integers and hence do the
111 * multiplication independantly for the HI and LO part
114 hi
= volumes
[channel
] >> 16;
115 lo
= volumes
[channel
] & 0xFFFF;
117 t
= (int32_t)(*samples
);
118 t
= ((t
* lo
) >> 16) + (t
* hi
);
119 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
120 *samples
++ = (int16_t) t
;
122 if (PA_UNLIKELY(++channel
>= channels
))
128 pa_volume_s16re_c (int16_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
132 length
/= sizeof (int16_t);
134 for (channel
= 0; length
; length
--) {
137 hi
= volumes
[channel
] >> 16;
138 lo
= volumes
[channel
] & 0xFFFF;
140 t
= (int32_t) PA_INT16_SWAP(*samples
);
141 t
= ((t
* lo
) >> 16) + (t
* hi
);
142 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
143 *samples
++ = PA_INT16_SWAP((int16_t) t
);
145 if (PA_UNLIKELY(++channel
>= channels
))
151 pa_volume_float32ne_c (float *samples
, float *volumes
, unsigned channels
, unsigned length
)
155 length
/= sizeof (float);
157 for (channel
= 0; length
; length
--) {
158 *samples
++ *= volumes
[channel
];
160 if (PA_UNLIKELY(++channel
>= channels
))
166 pa_volume_float32re_c (float *samples
, float *volumes
, unsigned channels
, unsigned length
)
170 length
/= sizeof (float);
172 for (channel
= 0; length
; length
--) {
175 t
= PA_FLOAT32_SWAP(*samples
);
176 t
*= volumes
[channel
];
177 *samples
++ = PA_FLOAT32_SWAP(t
);
179 if (PA_UNLIKELY(++channel
>= channels
))
185 pa_volume_s32ne_c (int32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
189 length
/= sizeof (int32_t);
191 for (channel
= 0; length
; length
--) {
194 t
= (int64_t)(*samples
);
195 t
= (t
* volumes
[channel
]) >> 16;
196 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
197 *samples
++ = (int32_t) t
;
199 if (PA_UNLIKELY(++channel
>= channels
))
205 pa_volume_s32re_c (int32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
209 length
/= sizeof (int32_t);
211 for (channel
= 0; length
; length
--) {
214 t
= (int64_t) PA_INT32_SWAP(*samples
);
215 t
= (t
* volumes
[channel
]) >> 16;
216 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
217 *samples
++ = PA_INT32_SWAP((int32_t) t
);
219 if (PA_UNLIKELY(++channel
>= channels
))
225 pa_volume_s24ne_c (uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
230 e
= samples
+ length
;
232 for (channel
= 0; samples
< e
; samples
+= 3) {
235 t
= (int64_t)((int32_t) (PA_READ24NE(samples
) << 8));
236 t
= (t
* volumes
[channel
]) >> 16;
237 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
238 PA_WRITE24NE(samples
, ((uint32_t) (int32_t) t
) >> 8);
240 if (PA_UNLIKELY(++channel
>= channels
))
246 pa_volume_s24re_c (uint8_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
251 e
= samples
+ length
;
253 for (channel
= 0; samples
< e
; samples
+= 3) {
256 t
= (int64_t)((int32_t) (PA_READ24RE(samples
) << 8));
257 t
= (t
* volumes
[channel
]) >> 16;
258 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
259 PA_WRITE24RE(samples
, ((uint32_t) (int32_t) t
) >> 8);
261 if (PA_UNLIKELY(++channel
>= channels
))
267 pa_volume_s24_32ne_c (uint32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
271 length
/= sizeof (uint32_t);
273 for (channel
= 0; length
; length
--) {
276 t
= (int64_t) ((int32_t) (*samples
<< 8));
277 t
= (t
* volumes
[channel
]) >> 16;
278 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
279 *samples
++ = ((uint32_t) ((int32_t) t
)) >> 8;
281 if (PA_UNLIKELY(++channel
>= channels
))
287 pa_volume_s24_32re_c (uint32_t *samples
, int32_t *volumes
, unsigned channels
, unsigned length
)
291 length
/= sizeof (uint32_t);
293 for (channel
= 0; length
; length
--) {
296 t
= (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples
) << 8));
297 t
= (t
* volumes
[channel
]) >> 16;
298 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
299 *samples
++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t
)) >> 8);
301 if (PA_UNLIKELY(++channel
>= channels
))
306 static pa_do_volume_func_t do_volume_table
[] =
308 [PA_SAMPLE_U8
] = (pa_do_volume_func_t
) pa_volume_u8_c
,
309 [PA_SAMPLE_ALAW
] = (pa_do_volume_func_t
) pa_volume_alaw_c
,
310 [PA_SAMPLE_ULAW
] = (pa_do_volume_func_t
) pa_volume_ulaw_c
,
311 [PA_SAMPLE_S16NE
] = (pa_do_volume_func_t
) pa_volume_s16ne_c
,
312 [PA_SAMPLE_S16RE
] = (pa_do_volume_func_t
) pa_volume_s16re_c
,
313 [PA_SAMPLE_FLOAT32NE
] = (pa_do_volume_func_t
) pa_volume_float32ne_c
,
314 [PA_SAMPLE_FLOAT32RE
] = (pa_do_volume_func_t
) pa_volume_float32re_c
,
315 [PA_SAMPLE_S32NE
] = (pa_do_volume_func_t
) pa_volume_s32ne_c
,
316 [PA_SAMPLE_S32RE
] = (pa_do_volume_func_t
) pa_volume_s32re_c
,
317 [PA_SAMPLE_S24NE
] = (pa_do_volume_func_t
) pa_volume_s24ne_c
,
318 [PA_SAMPLE_S24RE
] = (pa_do_volume_func_t
) pa_volume_s24re_c
,
319 [PA_SAMPLE_S24_32NE
] = (pa_do_volume_func_t
) pa_volume_s24_32ne_c
,
320 [PA_SAMPLE_S24_32RE
] = (pa_do_volume_func_t
) pa_volume_s24_32re_c
323 pa_do_volume_func_t
pa_get_volume_func(pa_sample_format_t f
) {
325 pa_assert(f
< PA_SAMPLE_MAX
);
327 return do_volume_table
[f
];
330 void pa_set_volume_func(pa_sample_format_t f
, pa_do_volume_func_t func
) {
332 pa_assert(f
< PA_SAMPLE_MAX
);
334 do_volume_table
[f
] = func
;