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
27 #include <pulsecore/macro.h>
28 #include <pulsecore/g711.h>
29 #include <pulsecore/endianmacros.h>
31 #include "sample-util.h"
33 static void pa_volume_u8_c(uint8_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
36 for (channel
= 0; length
; length
--) {
37 int32_t t
= pa_mult_s16_volume(*samples
- 0x80, volumes
[channel
]);
39 t
= PA_CLAMP_UNLIKELY(t
, -0x80, 0x7F);
40 *samples
++ = (uint8_t) (t
+ 0x80);
42 if (PA_UNLIKELY(++channel
>= channels
))
47 static void pa_volume_alaw_c(uint8_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
50 for (channel
= 0; length
; length
--) {
51 int32_t t
= pa_mult_s16_volume(st_alaw2linear16(*samples
), volumes
[channel
]);
53 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
54 *samples
++ = (uint8_t) st_13linear2alaw((int16_t) t
>> 3);
56 if (PA_UNLIKELY(++channel
>= channels
))
61 static void pa_volume_ulaw_c(uint8_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
64 for (channel
= 0; length
; length
--) {
65 int32_t t
= pa_mult_s16_volume(st_ulaw2linear16(*samples
), volumes
[channel
]);
67 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
68 *samples
++ = (uint8_t) st_14linear2ulaw((int16_t) t
>> 2);
70 if (PA_UNLIKELY(++channel
>= channels
))
75 static void pa_volume_s16ne_c(int16_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
78 length
/= sizeof(int16_t);
80 for (channel
= 0; length
; length
--) {
81 int32_t t
= pa_mult_s16_volume(*samples
, volumes
[channel
]);
83 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
84 *samples
++ = (int16_t) t
;
86 if (PA_UNLIKELY(++channel
>= channels
))
91 static void pa_volume_s16re_c(int16_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
94 length
/= sizeof(int16_t);
96 for (channel
= 0; length
; length
--) {
97 int32_t t
= pa_mult_s16_volume(PA_INT16_SWAP(*samples
), volumes
[channel
]);
99 t
= PA_CLAMP_UNLIKELY(t
, -0x8000, 0x7FFF);
100 *samples
++ = PA_INT16_SWAP((int16_t) t
);
102 if (PA_UNLIKELY(++channel
>= channels
))
107 static void pa_volume_float32ne_c(float *samples
, const float *volumes
, unsigned channels
, unsigned length
) {
110 length
/= sizeof(float);
112 for (channel
= 0; length
; length
--) {
113 *samples
++ *= volumes
[channel
];
115 if (PA_UNLIKELY(++channel
>= channels
))
120 static void pa_volume_float32re_c(float *samples
, float *volumes
, unsigned channels
, unsigned length
) {
123 length
/= sizeof(float);
125 for (channel
= 0; length
; length
--) {
128 t
= PA_FLOAT32_SWAP(*samples
);
129 t
*= volumes
[channel
];
130 *samples
++ = PA_FLOAT32_SWAP(t
);
132 if (PA_UNLIKELY(++channel
>= channels
))
137 static void pa_volume_s32ne_c(int32_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
140 length
/= sizeof(int32_t);
142 for (channel
= 0; length
; length
--) {
145 t
= (int64_t)(*samples
);
146 t
= (t
* volumes
[channel
]) >> 16;
147 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
148 *samples
++ = (int32_t) t
;
150 if (PA_UNLIKELY(++channel
>= channels
))
155 static void pa_volume_s32re_c(int32_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
158 length
/= sizeof(int32_t);
160 for (channel
= 0; length
; length
--) {
163 t
= (int64_t) PA_INT32_SWAP(*samples
);
164 t
= (t
* volumes
[channel
]) >> 16;
165 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
166 *samples
++ = PA_INT32_SWAP((int32_t) t
);
168 if (PA_UNLIKELY(++channel
>= channels
))
173 static void pa_volume_s24ne_c(uint8_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
177 e
= samples
+ length
;
179 for (channel
= 0; samples
< e
; samples
+= 3) {
182 t
= (int64_t)((int32_t) (PA_READ24NE(samples
) << 8));
183 t
= (t
* volumes
[channel
]) >> 16;
184 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
185 PA_WRITE24NE(samples
, ((uint32_t) (int32_t) t
) >> 8);
187 if (PA_UNLIKELY(++channel
>= channels
))
192 static void pa_volume_s24re_c(uint8_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
196 e
= samples
+ length
;
198 for (channel
= 0; samples
< e
; samples
+= 3) {
201 t
= (int64_t)((int32_t) (PA_READ24RE(samples
) << 8));
202 t
= (t
* volumes
[channel
]) >> 16;
203 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
204 PA_WRITE24RE(samples
, ((uint32_t) (int32_t) t
) >> 8);
206 if (PA_UNLIKELY(++channel
>= channels
))
211 static void pa_volume_s24_32ne_c(uint32_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
214 length
/= sizeof(uint32_t);
216 for (channel
= 0; length
; length
--) {
219 t
= (int64_t) ((int32_t) (*samples
<< 8));
220 t
= (t
* volumes
[channel
]) >> 16;
221 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
222 *samples
++ = ((uint32_t) ((int32_t) t
)) >> 8;
224 if (PA_UNLIKELY(++channel
>= channels
))
229 static void pa_volume_s24_32re_c(uint32_t *samples
, const int32_t *volumes
, unsigned channels
, unsigned length
) {
232 length
/= sizeof(uint32_t);
234 for (channel
= 0; length
; length
--) {
237 t
= (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples
) << 8));
238 t
= (t
* volumes
[channel
]) >> 16;
239 t
= PA_CLAMP_UNLIKELY(t
, -0x80000000LL
, 0x7FFFFFFFLL
);
240 *samples
++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t
)) >> 8);
242 if (PA_UNLIKELY(++channel
>= channels
))
247 static pa_do_volume_func_t do_volume_table
[] = {
248 [PA_SAMPLE_U8
] = (pa_do_volume_func_t
) pa_volume_u8_c
,
249 [PA_SAMPLE_ALAW
] = (pa_do_volume_func_t
) pa_volume_alaw_c
,
250 [PA_SAMPLE_ULAW
] = (pa_do_volume_func_t
) pa_volume_ulaw_c
,
251 [PA_SAMPLE_S16NE
] = (pa_do_volume_func_t
) pa_volume_s16ne_c
,
252 [PA_SAMPLE_S16RE
] = (pa_do_volume_func_t
) pa_volume_s16re_c
,
253 [PA_SAMPLE_FLOAT32NE
] = (pa_do_volume_func_t
) pa_volume_float32ne_c
,
254 [PA_SAMPLE_FLOAT32RE
] = (pa_do_volume_func_t
) pa_volume_float32re_c
,
255 [PA_SAMPLE_S32NE
] = (pa_do_volume_func_t
) pa_volume_s32ne_c
,
256 [PA_SAMPLE_S32RE
] = (pa_do_volume_func_t
) pa_volume_s32re_c
,
257 [PA_SAMPLE_S24NE
] = (pa_do_volume_func_t
) pa_volume_s24ne_c
,
258 [PA_SAMPLE_S24RE
] = (pa_do_volume_func_t
) pa_volume_s24re_c
,
259 [PA_SAMPLE_S24_32NE
] = (pa_do_volume_func_t
) pa_volume_s24_32ne_c
,
260 [PA_SAMPLE_S24_32RE
] = (pa_do_volume_func_t
) pa_volume_s24_32re_c
263 pa_do_volume_func_t
pa_get_volume_func(pa_sample_format_t f
) {
264 pa_assert(pa_sample_format_valid(f
));
266 return do_volume_table
[f
];
269 void pa_set_volume_func(pa_sample_format_t f
, pa_do_volume_func_t func
) {
270 pa_assert(pa_sample_format_valid(f
));
272 do_volume_table
[f
] = func
;