build-sys: Use ax_check_flag macros from autoconf archive
[pulseaudio-mirror.git] / src / pulsecore / svolume_c.c
blob6c0fbf81a0a3311e0ba15c57df15dd8228f702a4
1 /***
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
20 USA.
21 ***/
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
28 #include <pulsecore/macro.h>
29 #include <pulsecore/g711.h>
30 #include <pulsecore/endianmacros.h>
32 #include "sample-util.h"
34 static void pa_volume_u8_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
35 unsigned channel;
37 for (channel = 0; length; length--) {
38 int32_t t, hi, lo;
40 hi = volumes[channel] >> 16;
41 lo = volumes[channel] & 0xFFFF;
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);
48 if (PA_UNLIKELY(++channel >= channels))
49 channel = 0;
53 static void pa_volume_alaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
54 unsigned channel;
56 for (channel = 0; length; length--) {
57 int32_t t, hi, lo;
59 hi = volumes[channel] >> 16;
60 lo = volumes[channel] & 0xFFFF;
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);
67 if (PA_UNLIKELY(++channel >= channels))
68 channel = 0;
72 static void pa_volume_ulaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
73 unsigned channel;
75 for (channel = 0; length; length--) {
76 int32_t t, hi, lo;
78 hi = volumes[channel] >> 16;
79 lo = volumes[channel] & 0xFFFF;
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);
86 if (PA_UNLIKELY(++channel >= channels))
87 channel = 0;
91 static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
92 unsigned channel;
94 length /= sizeof(int16_t);
96 for (channel = 0; length; length--) {
97 int32_t t, hi, lo;
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 independantly for the HI and LO part
103 * of the volume. */
105 hi = volumes[channel] >> 16;
106 lo = volumes[channel] & 0xFFFF;
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;
113 if (PA_UNLIKELY(++channel >= channels))
114 channel = 0;
118 static void pa_volume_s16re_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
119 unsigned channel;
121 length /= sizeof(int16_t);
123 for (channel = 0; length; length--) {
124 int32_t t, hi, lo;
126 hi = volumes[channel] >> 16;
127 lo = volumes[channel] & 0xFFFF;
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);
134 if (PA_UNLIKELY(++channel >= channels))
135 channel = 0;
139 static void pa_volume_float32ne_c(float *samples, float *volumes, unsigned channels, unsigned length) {
140 unsigned channel;
142 length /= sizeof(float);
144 for (channel = 0; length; length--) {
145 *samples++ *= volumes[channel];
147 if (PA_UNLIKELY(++channel >= channels))
148 channel = 0;
152 static void pa_volume_float32re_c(float *samples, float *volumes, unsigned channels, unsigned length) {
153 unsigned channel;
155 length /= sizeof(float);
157 for (channel = 0; length; length--) {
158 float t;
160 t = PA_FLOAT32_SWAP(*samples);
161 t *= volumes[channel];
162 *samples++ = PA_FLOAT32_SWAP(t);
164 if (PA_UNLIKELY(++channel >= channels))
165 channel = 0;
169 static void pa_volume_s32ne_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
170 unsigned channel;
172 length /= sizeof(int32_t);
174 for (channel = 0; length; length--) {
175 int64_t t;
177 t = (int64_t)(*samples);
178 t = (t * volumes[channel]) >> 16;
179 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
180 *samples++ = (int32_t) t;
182 if (PA_UNLIKELY(++channel >= channels))
183 channel = 0;
187 static void pa_volume_s32re_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
188 unsigned channel;
190 length /= sizeof(int32_t);
192 for (channel = 0; length; length--) {
193 int64_t t;
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);
200 if (PA_UNLIKELY(++channel >= channels))
201 channel = 0;
205 static void pa_volume_s24ne_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
206 unsigned channel;
207 uint8_t *e;
209 e = samples + length;
211 for (channel = 0; samples < e; samples += 3) {
212 int64_t t;
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);
219 if (PA_UNLIKELY(++channel >= channels))
220 channel = 0;
224 static void pa_volume_s24re_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
225 unsigned channel;
226 uint8_t *e;
228 e = samples + length;
230 for (channel = 0; samples < e; samples += 3) {
231 int64_t t;
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);
238 if (PA_UNLIKELY(++channel >= channels))
239 channel = 0;
243 static void pa_volume_s24_32ne_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
244 unsigned channel;
246 length /= sizeof(uint32_t);
248 for (channel = 0; length; length--) {
249 int64_t t;
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;
256 if (PA_UNLIKELY(++channel >= channels))
257 channel = 0;
261 static void pa_volume_s24_32re_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
262 unsigned channel;
264 length /= sizeof(uint32_t);
266 for (channel = 0; length; length--) {
267 int64_t t;
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);
274 if (PA_UNLIKELY(++channel >= channels))
275 channel = 0;
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
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);
299 return do_volume_table[f];
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);
306 do_volume_table[f] = func;