]> code.delx.au - pulseaudio/blob - src/pulsecore/svolume_c.c
core: Set volumes const in pa_do_volume_func_t
[pulseaudio] / src / pulsecore / svolume_c.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27
28 #include <pulsecore/macro.h>
29 #include <pulsecore/g711.h>
30 #include <pulsecore/endianmacros.h>
31
32 #include "sample-util.h"
33
34 static void pa_volume_u8_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
35 unsigned channel;
36
37 for (channel = 0; length; length--) {
38 int32_t t, hi, lo;
39
40 hi = volumes[channel] >> 16;
41 lo = volumes[channel] & 0xFFFF;
42
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);
47
48 if (PA_UNLIKELY(++channel >= channels))
49 channel = 0;
50 }
51 }
52
53 static void pa_volume_alaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
54 unsigned channel;
55
56 for (channel = 0; length; length--) {
57 int32_t t, hi, lo;
58
59 hi = volumes[channel] >> 16;
60 lo = volumes[channel] & 0xFFFF;
61
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);
66
67 if (PA_UNLIKELY(++channel >= channels))
68 channel = 0;
69 }
70 }
71
72 static void pa_volume_ulaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
73 unsigned channel;
74
75 for (channel = 0; length; length--) {
76 int32_t t, hi, lo;
77
78 hi = volumes[channel] >> 16;
79 lo = volumes[channel] & 0xFFFF;
80
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);
85
86 if (PA_UNLIKELY(++channel >= channels))
87 channel = 0;
88 }
89 }
90
91 static void pa_volume_s16ne_c(int16_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
92 unsigned channel;
93
94 length /= sizeof(int16_t);
95
96 for (channel = 0; length; length--) {
97 int32_t t, hi, lo;
98
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 independently for the HI and LO part
103 * of the volume. */
104
105 hi = volumes[channel] >> 16;
106 lo = volumes[channel] & 0xFFFF;
107
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;
112
113 if (PA_UNLIKELY(++channel >= channels))
114 channel = 0;
115 }
116 }
117
118 static void pa_volume_s16re_c(int16_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
119 unsigned channel;
120
121 length /= sizeof(int16_t);
122
123 for (channel = 0; length; length--) {
124 int32_t t, hi, lo;
125
126 hi = volumes[channel] >> 16;
127 lo = volumes[channel] & 0xFFFF;
128
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);
133
134 if (PA_UNLIKELY(++channel >= channels))
135 channel = 0;
136 }
137 }
138
139 static void pa_volume_float32ne_c(float *samples, const float *volumes, unsigned channels, unsigned length) {
140 unsigned channel;
141
142 length /= sizeof(float);
143
144 for (channel = 0; length; length--) {
145 *samples++ *= volumes[channel];
146
147 if (PA_UNLIKELY(++channel >= channels))
148 channel = 0;
149 }
150 }
151
152 static void pa_volume_float32re_c(float *samples, float *volumes, unsigned channels, unsigned length) {
153 unsigned channel;
154
155 length /= sizeof(float);
156
157 for (channel = 0; length; length--) {
158 float t;
159
160 t = PA_FLOAT32_SWAP(*samples);
161 t *= volumes[channel];
162 *samples++ = PA_FLOAT32_SWAP(t);
163
164 if (PA_UNLIKELY(++channel >= channels))
165 channel = 0;
166 }
167 }
168
169 static void pa_volume_s32ne_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
170 unsigned channel;
171
172 length /= sizeof(int32_t);
173
174 for (channel = 0; length; length--) {
175 int64_t t;
176
177 t = (int64_t)(*samples);
178 t = (t * volumes[channel]) >> 16;
179 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
180 *samples++ = (int32_t) t;
181
182 if (PA_UNLIKELY(++channel >= channels))
183 channel = 0;
184 }
185 }
186
187 static void pa_volume_s32re_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
188 unsigned channel;
189
190 length /= sizeof(int32_t);
191
192 for (channel = 0; length; length--) {
193 int64_t t;
194
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);
199
200 if (PA_UNLIKELY(++channel >= channels))
201 channel = 0;
202 }
203 }
204
205 static void pa_volume_s24ne_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
206 unsigned channel;
207 uint8_t *e;
208
209 e = samples + length;
210
211 for (channel = 0; samples < e; samples += 3) {
212 int64_t t;
213
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);
218
219 if (PA_UNLIKELY(++channel >= channels))
220 channel = 0;
221 }
222 }
223
224 static void pa_volume_s24re_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
225 unsigned channel;
226 uint8_t *e;
227
228 e = samples + length;
229
230 for (channel = 0; samples < e; samples += 3) {
231 int64_t t;
232
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);
237
238 if (PA_UNLIKELY(++channel >= channels))
239 channel = 0;
240 }
241 }
242
243 static void pa_volume_s24_32ne_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
244 unsigned channel;
245
246 length /= sizeof(uint32_t);
247
248 for (channel = 0; length; length--) {
249 int64_t t;
250
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;
255
256 if (PA_UNLIKELY(++channel >= channels))
257 channel = 0;
258 }
259 }
260
261 static void pa_volume_s24_32re_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
262 unsigned channel;
263
264 length /= sizeof(uint32_t);
265
266 for (channel = 0; length; length--) {
267 int64_t t;
268
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);
273
274 if (PA_UNLIKELY(++channel >= channels))
275 channel = 0;
276 }
277 }
278
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
293 };
294
295 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
296 pa_assert(f >= 0);
297 pa_assert(f < PA_SAMPLE_MAX);
298
299 return do_volume_table[f];
300 }
301
302 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func) {
303 pa_assert(f >= 0);
304 pa_assert(f < PA_SAMPLE_MAX);
305
306 do_volume_table[f] = func;
307 }