Fix up according to Coding Style
[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 pa_volume_u8_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
36     unsigned channel;
37
38     for (channel = 0; length; length--) {
39         int32_t t, hi, lo;
40
41         hi = volumes[channel] >> 16;
42         lo = volumes[channel] & 0xFFFF;
43
44         t = (int32_t) *samples - 0x80;
45         t = ((t * lo) >> 16) + (t * hi);
46         t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
47         *samples++ = (uint8_t) (t + 0x80);
48
49         if (PA_UNLIKELY(++channel >= channels))
50             channel = 0;
51     }
52 }
53
54 static void pa_volume_alaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
55     unsigned channel;
56
57     for (channel = 0; length; length--) {
58         int32_t t, hi, lo;
59
60         hi = volumes[channel] >> 16;
61         lo = volumes[channel] & 0xFFFF;
62
63         t = (int32_t) st_alaw2linear16(*samples);
64         t = ((t * lo) >> 16) + (t * hi);
65         t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
66         *samples++ = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
67
68         if (PA_UNLIKELY(++channel >= channels))
69             channel = 0;
70     }
71 }
72
73 static void pa_volume_ulaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
74     unsigned channel;
75
76     for (channel = 0; length; length--) {
77         int32_t t, hi, lo;
78
79         hi = volumes[channel] >> 16;
80         lo = volumes[channel] & 0xFFFF;
81
82         t = (int32_t) st_ulaw2linear16(*samples);
83         t = ((t * lo) >> 16) + (t * hi);
84         t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
85         *samples++ = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
86
87         if (PA_UNLIKELY(++channel >= channels))
88             channel = 0;
89     }
90 }
91
92 static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
93     unsigned channel;
94
95     length /= sizeof(int16_t);
96
97     for (channel = 0; length; length--) {
98         int32_t t, hi, lo;
99
100         /* Multiplying the 32bit volume factor with the 16bit
101          * sample might result in an 48bit value. We want to
102          * do without 64 bit integers and hence do the
103          * multiplication independantly for the HI and LO part
104          * of the volume. */
105
106         hi = volumes[channel] >> 16;
107         lo = volumes[channel] & 0xFFFF;
108
109         t = (int32_t)(*samples);
110         t = ((t * lo) >> 16) + (t * hi);
111         t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
112         *samples++ = (int16_t) t;
113
114         if (PA_UNLIKELY(++channel >= channels))
115             channel = 0;
116     }
117 }
118
119 static void pa_volume_s16re_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
120     unsigned channel;
121
122     length /= sizeof(int16_t);
123
124     for (channel = 0; length; length--) {
125         int32_t t, hi, lo;
126
127         hi = volumes[channel] >> 16;
128         lo = volumes[channel] & 0xFFFF;
129
130         t = (int32_t) PA_INT16_SWAP(*samples);
131         t = ((t * lo) >> 16) + (t * hi);
132         t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
133         *samples++ = PA_INT16_SWAP((int16_t) t);
134
135         if (PA_UNLIKELY(++channel >= channels))
136             channel = 0;
137     }
138 }
139
140 static void pa_volume_float32ne_c(float *samples, float *volumes, unsigned channels, unsigned length) {
141     unsigned channel;
142
143     length /= sizeof(float);
144
145     for (channel = 0; length; length--) {
146         *samples++ *= volumes[channel];
147
148         if (PA_UNLIKELY(++channel >= channels))
149             channel = 0;
150     }
151 }
152
153 static void pa_volume_float32re_c(float *samples, float *volumes, unsigned channels, unsigned length) {
154     unsigned channel;
155
156     length /= sizeof(float);
157
158     for (channel = 0; length; length--) {
159         float t;
160
161         t = PA_FLOAT32_SWAP(*samples);
162         t *= volumes[channel];
163         *samples++ = PA_FLOAT32_SWAP(t);
164
165         if (PA_UNLIKELY(++channel >= channels))
166             channel = 0;
167     }
168 }
169
170 static void pa_volume_s32ne_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
171     unsigned channel;
172
173     length /= sizeof(int32_t);
174
175     for (channel = 0; length; length--) {
176         int64_t t;
177
178         t = (int64_t)(*samples);
179         t = (t * volumes[channel]) >> 16;
180         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
181         *samples++ = (int32_t) t;
182
183         if (PA_UNLIKELY(++channel >= channels))
184             channel = 0;
185     }
186 }
187
188 static void pa_volume_s32re_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
189     unsigned channel;
190
191     length /= sizeof(int32_t);
192
193     for (channel = 0; length; length--) {
194         int64_t t;
195
196         t = (int64_t) PA_INT32_SWAP(*samples);
197         t = (t * volumes[channel]) >> 16;
198         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
199         *samples++ = PA_INT32_SWAP((int32_t) t);
200
201         if (PA_UNLIKELY(++channel >= channels))
202             channel = 0;
203     }
204 }
205
206 static void pa_volume_s24ne_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
207     unsigned channel;
208     uint8_t *e;
209
210     e = samples + length;
211
212     for (channel = 0; samples < e; samples += 3) {
213         int64_t t;
214
215         t = (int64_t)((int32_t) (PA_READ24NE(samples) << 8));
216         t = (t * volumes[channel]) >> 16;
217         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
218         PA_WRITE24NE(samples, ((uint32_t) (int32_t) t) >> 8);
219
220         if (PA_UNLIKELY(++channel >= channels))
221             channel = 0;
222     }
223 }
224
225 static void pa_volume_s24re_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
226     unsigned channel;
227     uint8_t *e;
228
229     e = samples + length;
230
231     for (channel = 0; samples < e; samples += 3) {
232         int64_t t;
233
234         t = (int64_t)((int32_t) (PA_READ24RE(samples) << 8));
235         t = (t * volumes[channel]) >> 16;
236         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
237         PA_WRITE24RE(samples, ((uint32_t) (int32_t) t) >> 8);
238
239         if (PA_UNLIKELY(++channel >= channels))
240             channel = 0;
241     }
242 }
243
244 static void pa_volume_s24_32ne_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
245     unsigned channel;
246
247     length /= sizeof(uint32_t);
248
249     for (channel = 0; length; length--) {
250         int64_t t;
251
252         t = (int64_t) ((int32_t) (*samples << 8));
253         t = (t * volumes[channel]) >> 16;
254         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
255         *samples++ = ((uint32_t) ((int32_t) t)) >> 8;
256
257         if (PA_UNLIKELY(++channel >= channels))
258             channel = 0;
259     }
260 }
261
262 static void pa_volume_s24_32re_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
263     unsigned channel;
264
265     length /= sizeof(uint32_t);
266
267     for (channel = 0; length; length--) {
268         int64_t t;
269
270         t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples) << 8));
271         t = (t * volumes[channel]) >> 16;
272         t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
273         *samples++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8);
274
275         if (PA_UNLIKELY(++channel >= channels))
276             channel = 0;
277     }
278 }
279
280 static pa_do_volume_func_t do_volume_table[] = {
281     [PA_SAMPLE_U8]        = (pa_do_volume_func_t) pa_volume_u8_c,
282     [PA_SAMPLE_ALAW]      = (pa_do_volume_func_t) pa_volume_alaw_c,
283     [PA_SAMPLE_ULAW]      = (pa_do_volume_func_t) pa_volume_ulaw_c,
284     [PA_SAMPLE_S16NE]     = (pa_do_volume_func_t) pa_volume_s16ne_c,
285     [PA_SAMPLE_S16RE]     = (pa_do_volume_func_t) pa_volume_s16re_c,
286     [PA_SAMPLE_FLOAT32NE] = (pa_do_volume_func_t) pa_volume_float32ne_c,
287     [PA_SAMPLE_FLOAT32RE] = (pa_do_volume_func_t) pa_volume_float32re_c,
288     [PA_SAMPLE_S32NE]     = (pa_do_volume_func_t) pa_volume_s32ne_c,
289     [PA_SAMPLE_S32RE]     = (pa_do_volume_func_t) pa_volume_s32re_c,
290     [PA_SAMPLE_S24NE]     = (pa_do_volume_func_t) pa_volume_s24ne_c,
291     [PA_SAMPLE_S24RE]     = (pa_do_volume_func_t) pa_volume_s24re_c,
292     [PA_SAMPLE_S24_32NE]  = (pa_do_volume_func_t) pa_volume_s24_32ne_c,
293     [PA_SAMPLE_S24_32RE]  = (pa_do_volume_func_t) pa_volume_s24_32re_c
294 };
295
296 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
297     pa_assert(f >= 0);
298     pa_assert(f < PA_SAMPLE_MAX);
299
300     return do_volume_table[f];
301 }
302
303 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func) {
304     pa_assert(f >= 0);
305     pa_assert(f < PA_SAMPLE_MAX);
306
307     do_volume_table[f] = func;
308 }