]> code.delx.au - pulseaudio/blob - src/pulsecore/svolume_c.c
remap: Change remapping function argument type from void to int16_t / float as approp...
[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 #include <pulsecore/macro.h>
28 #include <pulsecore/g711.h>
29 #include <pulsecore/endianmacros.h>
30
31 #include "sample-util.h"
32
33 static void pa_volume_u8_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
34 unsigned channel;
35
36 for (channel = 0; length; length--) {
37 int32_t t = pa_mult_s16_volume(*samples - 0x80, volumes[channel]);
38
39 t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
40 *samples++ = (uint8_t) (t + 0x80);
41
42 if (PA_UNLIKELY(++channel >= channels))
43 channel = 0;
44 }
45 }
46
47 static void pa_volume_alaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
48 unsigned channel;
49
50 for (channel = 0; length; length--) {
51 int32_t t = pa_mult_s16_volume(st_alaw2linear16(*samples), volumes[channel]);
52
53 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
54 *samples++ = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
55
56 if (PA_UNLIKELY(++channel >= channels))
57 channel = 0;
58 }
59 }
60
61 static void pa_volume_ulaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
62 unsigned channel;
63
64 for (channel = 0; length; length--) {
65 int32_t t = pa_mult_s16_volume(st_ulaw2linear16(*samples), volumes[channel]);
66
67 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
68 *samples++ = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
69
70 if (PA_UNLIKELY(++channel >= channels))
71 channel = 0;
72 }
73 }
74
75 static void pa_volume_s16ne_c(int16_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
76 unsigned channel;
77
78 length /= sizeof(int16_t);
79
80 for (channel = 0; length; length--) {
81 int32_t t = pa_mult_s16_volume(*samples, volumes[channel]);
82
83 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
84 *samples++ = (int16_t) t;
85
86 if (PA_UNLIKELY(++channel >= channels))
87 channel = 0;
88 }
89 }
90
91 static void pa_volume_s16re_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 = pa_mult_s16_volume(PA_INT16_SWAP(*samples), volumes[channel]);
98
99 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
100 *samples++ = PA_INT16_SWAP((int16_t) t);
101
102 if (PA_UNLIKELY(++channel >= channels))
103 channel = 0;
104 }
105 }
106
107 static void pa_volume_float32ne_c(float *samples, const float *volumes, unsigned channels, unsigned length) {
108 unsigned channel;
109
110 length /= sizeof(float);
111
112 for (channel = 0; length; length--) {
113 *samples++ *= volumes[channel];
114
115 if (PA_UNLIKELY(++channel >= channels))
116 channel = 0;
117 }
118 }
119
120 static void pa_volume_float32re_c(float *samples, float *volumes, unsigned channels, unsigned length) {
121 unsigned channel;
122
123 length /= sizeof(float);
124
125 for (channel = 0; length; length--) {
126 float t;
127
128 t = PA_FLOAT32_SWAP(*samples);
129 t *= volumes[channel];
130 *samples++ = PA_FLOAT32_SWAP(t);
131
132 if (PA_UNLIKELY(++channel >= channels))
133 channel = 0;
134 }
135 }
136
137 static void pa_volume_s32ne_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
138 unsigned channel;
139
140 length /= sizeof(int32_t);
141
142 for (channel = 0; length; length--) {
143 int64_t t;
144
145 t = (int64_t)(*samples);
146 t = (t * volumes[channel]) >> 16;
147 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
148 *samples++ = (int32_t) t;
149
150 if (PA_UNLIKELY(++channel >= channels))
151 channel = 0;
152 }
153 }
154
155 static void pa_volume_s32re_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
156 unsigned channel;
157
158 length /= sizeof(int32_t);
159
160 for (channel = 0; length; length--) {
161 int64_t t;
162
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);
167
168 if (PA_UNLIKELY(++channel >= channels))
169 channel = 0;
170 }
171 }
172
173 static void pa_volume_s24ne_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
174 unsigned channel;
175 uint8_t *e;
176
177 e = samples + length;
178
179 for (channel = 0; samples < e; samples += 3) {
180 int64_t t;
181
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);
186
187 if (PA_UNLIKELY(++channel >= channels))
188 channel = 0;
189 }
190 }
191
192 static void pa_volume_s24re_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
193 unsigned channel;
194 uint8_t *e;
195
196 e = samples + length;
197
198 for (channel = 0; samples < e; samples += 3) {
199 int64_t t;
200
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);
205
206 if (PA_UNLIKELY(++channel >= channels))
207 channel = 0;
208 }
209 }
210
211 static void pa_volume_s24_32ne_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
212 unsigned channel;
213
214 length /= sizeof(uint32_t);
215
216 for (channel = 0; length; length--) {
217 int64_t t;
218
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;
223
224 if (PA_UNLIKELY(++channel >= channels))
225 channel = 0;
226 }
227 }
228
229 static void pa_volume_s24_32re_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
230 unsigned channel;
231
232 length /= sizeof(uint32_t);
233
234 for (channel = 0; length; length--) {
235 int64_t t;
236
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);
241
242 if (PA_UNLIKELY(++channel >= channels))
243 channel = 0;
244 }
245 }
246
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
261 };
262
263 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
264 pa_assert(pa_sample_format_valid(f));
265
266 return do_volume_table[f];
267 }
268
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));
271
272 do_volume_table[f] = func;
273 }