Merge branch 'master' of git://0pointer.de/pulseaudio into dbus-work
[platform/upstream/pulseaudio.git] / 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/core-util.h>
31
32 #include "sample-util.h"
33 #include "endianmacros.h"
34
35 static void
36 pa_volume_u8_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
37 {
38     unsigned channel;
39
40     for (channel = 0; length; length--) {
41         int32_t t, hi, lo;
42
43         hi = volumes[channel] >> 16;
44         lo = volumes[channel] & 0xFFFF;
45
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);
50
51         if (PA_UNLIKELY(++channel >= channels))
52             channel = 0;
53     }
54 }
55
56 static void
57 pa_volume_alaw_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
58 {
59     unsigned channel;
60
61     for (channel = 0; length; length--) {
62         int32_t t, hi, lo;
63
64         hi = volumes[channel] >> 16;
65         lo = volumes[channel] & 0xFFFF;
66
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);
71
72         if (PA_UNLIKELY(++channel >= channels))
73             channel = 0;
74     }
75 }
76
77 static void
78 pa_volume_ulaw_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
79 {
80     unsigned channel;
81
82     for (channel = 0; length; length--) {
83         int32_t t, hi, lo;
84
85         hi = volumes[channel] >> 16;
86         lo = volumes[channel] & 0xFFFF;
87
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);
92
93         if (PA_UNLIKELY(++channel >= channels))
94             channel = 0;
95     }
96 }
97
98 static void
99 pa_volume_s16ne_c (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
100 {
101     unsigned channel;
102
103     length /= sizeof (int16_t);
104
105     for (channel = 0; length; length--) {
106         int32_t t, hi, lo;
107
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
112          * of the volume. */
113
114         hi = volumes[channel] >> 16;
115         lo = volumes[channel] & 0xFFFF;
116
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;
121
122         if (PA_UNLIKELY(++channel >= channels))
123             channel = 0;
124     }
125 }
126
127 static void
128 pa_volume_s16re_c (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
129 {
130     unsigned channel;
131
132     length /= sizeof (int16_t);
133
134     for (channel = 0; length; length--) {
135         int32_t t, hi, lo;
136
137         hi = volumes[channel] >> 16;
138         lo = volumes[channel] & 0xFFFF;
139
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);
144
145         if (PA_UNLIKELY(++channel >= channels))
146             channel = 0;
147     }
148 }
149
150 static void
151 pa_volume_float32ne_c (float *samples, float *volumes, unsigned channels, unsigned length)
152 {
153     unsigned channel;
154
155     length /= sizeof (float);
156
157     for (channel = 0; length; length--) {
158         *samples++ *= volumes[channel];
159
160         if (PA_UNLIKELY(++channel >= channels))
161             channel = 0;
162     }
163 }
164
165 static void
166 pa_volume_float32re_c (float *samples, float *volumes, unsigned channels, unsigned length)
167 {
168     unsigned channel;
169
170     length /= sizeof (float);
171
172     for (channel = 0; length; length--) {
173         float t;
174
175         t = PA_FLOAT32_SWAP(*samples);
176         t *= volumes[channel];
177         *samples++ = PA_FLOAT32_SWAP(t);
178
179         if (PA_UNLIKELY(++channel >= channels))
180             channel = 0;
181     }
182 }
183
184 static void
185 pa_volume_s32ne_c (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
186 {
187     unsigned channel;
188
189     length /= sizeof (int32_t);
190
191     for (channel = 0; length; length--) {
192         int64_t t;
193
194         t = (int64_t)(*samples);
195         t = (t * volumes[channel]) >> 16;
196         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
197         *samples++ = (int32_t) t;
198
199         if (PA_UNLIKELY(++channel >= channels))
200             channel = 0;
201     }
202 }
203
204 static void
205 pa_volume_s32re_c (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
206 {
207     unsigned channel;
208
209     length /= sizeof (int32_t);
210
211     for (channel = 0; length; length--) {
212         int64_t t;
213
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);
218
219         if (PA_UNLIKELY(++channel >= channels))
220             channel = 0;
221     }
222 }
223
224 static void
225 pa_volume_s24ne_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
226 {
227     unsigned channel;
228     uint8_t *e;
229
230     e = samples + length;
231
232     for (channel = 0; samples < e; samples += 3) {
233         int64_t t;
234
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);
239
240         if (PA_UNLIKELY(++channel >= channels))
241             channel = 0;
242     }
243 }
244
245 static void
246 pa_volume_s24re_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
247 {
248     unsigned channel;
249     uint8_t *e;
250
251     e = samples + length;
252
253     for (channel = 0; samples < e; samples += 3) {
254         int64_t t;
255
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);
260
261         if (PA_UNLIKELY(++channel >= channels))
262             channel = 0;
263     }
264 }
265
266 static void
267 pa_volume_s24_32ne_c (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
268 {
269     unsigned channel;
270
271     length /= sizeof (uint32_t);
272
273     for (channel = 0; length; length--) {
274         int64_t t;
275
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;
280
281         if (PA_UNLIKELY(++channel >= channels))
282             channel = 0;
283     }
284 }
285
286 static void
287 pa_volume_s24_32re_c (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
288 {
289     unsigned channel;
290
291     length /= sizeof (uint32_t);
292
293     for (channel = 0; length; length--) {
294         int64_t t;
295
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);
300
301         if (PA_UNLIKELY(++channel >= channels))
302             channel = 0;
303     }
304 }
305
306 static pa_do_volume_func_t do_volume_table[] =
307 {
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
321 };
322
323 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
324     pa_assert(f >= 0);
325     pa_assert(f < PA_SAMPLE_MAX);
326
327     return do_volume_table[f];
328 }
329
330 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func) {
331     pa_assert(f >= 0);
332     pa_assert(f < PA_SAMPLE_MAX);
333
334     do_volume_table[f] = func;
335 }