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
28 #include <pulsecore/macro.h>
29 #include <pulsecore/g711.h>
30 #include <pulsecore/core-util.h>
32 #include "sample-util.h"
33 #include "endianmacros.h"
35 static void pa_volume_u8_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
38 for (channel = 0; length; length--) {
41 hi = volumes[channel] >> 16;
42 lo = volumes[channel] & 0xFFFF;
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);
49 if (PA_UNLIKELY(++channel >= channels))
54 static void pa_volume_alaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
57 for (channel = 0; length; length--) {
60 hi = volumes[channel] >> 16;
61 lo = volumes[channel] & 0xFFFF;
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);
68 if (PA_UNLIKELY(++channel >= channels))
73 static void pa_volume_ulaw_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
76 for (channel = 0; length; length--) {
79 hi = volumes[channel] >> 16;
80 lo = volumes[channel] & 0xFFFF;
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);
87 if (PA_UNLIKELY(++channel >= channels))
92 static void pa_volume_s16ne_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
95 length /= sizeof(int16_t);
97 for (channel = 0; length; length--) {
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
106 hi = volumes[channel] >> 16;
107 lo = volumes[channel] & 0xFFFF;
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;
114 if (PA_UNLIKELY(++channel >= channels))
119 static void pa_volume_s16re_c(int16_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
122 length /= sizeof(int16_t);
124 for (channel = 0; length; length--) {
127 hi = volumes[channel] >> 16;
128 lo = volumes[channel] & 0xFFFF;
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);
135 if (PA_UNLIKELY(++channel >= channels))
140 static void pa_volume_float32ne_c(float *samples, float *volumes, unsigned channels, unsigned length) {
143 length /= sizeof(float);
145 for (channel = 0; length; length--) {
146 *samples++ *= volumes[channel];
148 if (PA_UNLIKELY(++channel >= channels))
153 static void pa_volume_float32re_c(float *samples, float *volumes, unsigned channels, unsigned length) {
156 length /= sizeof(float);
158 for (channel = 0; length; length--) {
161 t = PA_FLOAT32_SWAP(*samples);
162 t *= volumes[channel];
163 *samples++ = PA_FLOAT32_SWAP(t);
165 if (PA_UNLIKELY(++channel >= channels))
170 static void pa_volume_s32ne_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
173 length /= sizeof(int32_t);
175 for (channel = 0; length; length--) {
178 t = (int64_t)(*samples);
179 t = (t * volumes[channel]) >> 16;
180 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
181 *samples++ = (int32_t) t;
183 if (PA_UNLIKELY(++channel >= channels))
188 static void pa_volume_s32re_c(int32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
191 length /= sizeof(int32_t);
193 for (channel = 0; length; length--) {
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);
201 if (PA_UNLIKELY(++channel >= channels))
206 static void pa_volume_s24ne_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
210 e = samples + length;
212 for (channel = 0; samples < e; samples += 3) {
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);
220 if (PA_UNLIKELY(++channel >= channels))
225 static void pa_volume_s24re_c(uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
229 e = samples + length;
231 for (channel = 0; samples < e; samples += 3) {
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);
239 if (PA_UNLIKELY(++channel >= channels))
244 static void pa_volume_s24_32ne_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
247 length /= sizeof(uint32_t);
249 for (channel = 0; length; length--) {
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;
257 if (PA_UNLIKELY(++channel >= channels))
262 static void pa_volume_s24_32re_c(uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length) {
265 length /= sizeof(uint32_t);
267 for (channel = 0; length; length--) {
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);
275 if (PA_UNLIKELY(++channel >= channels))
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
296 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
298 pa_assert(f < PA_SAMPLE_MAX);
300 return do_volume_table[f];
303 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func) {
305 pa_assert(f < PA_SAMPLE_MAX);
307 do_volume_table[f] = func;