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, see <http://www.gnu.org/licenses/>.
25 #include <pulsecore/macro.h>
26 #include <pulsecore/g711.h>
27 #include <pulsecore/endianmacros.h>
29 #include "sample-util.h"
31 static void pa_volume_u8_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
34 for (channel = 0; length; length--) {
35 int32_t t = pa_mult_s16_volume(*samples - 0x80, volumes[channel]);
37 t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
38 *samples++ = (uint8_t) (t + 0x80);
40 if (PA_UNLIKELY(++channel >= channels))
45 static void pa_volume_alaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
48 for (channel = 0; length; length--) {
49 int32_t t = pa_mult_s16_volume(st_alaw2linear16(*samples), volumes[channel]);
51 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
52 *samples++ = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
54 if (PA_UNLIKELY(++channel >= channels))
59 static void pa_volume_ulaw_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
62 for (channel = 0; length; length--) {
63 int32_t t = pa_mult_s16_volume(st_ulaw2linear16(*samples), volumes[channel]);
65 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
66 *samples++ = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
68 if (PA_UNLIKELY(++channel >= channels))
73 static void pa_volume_s16ne_c(int16_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
76 length /= sizeof(int16_t);
78 for (channel = 0; length; length--) {
79 int32_t t = pa_mult_s16_volume(*samples, volumes[channel]);
81 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
82 *samples++ = (int16_t) t;
84 if (PA_UNLIKELY(++channel >= channels))
89 static void pa_volume_s16re_c(int16_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
92 length /= sizeof(int16_t);
94 for (channel = 0; length; length--) {
95 int32_t t = pa_mult_s16_volume(PA_INT16_SWAP(*samples), volumes[channel]);
97 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
98 *samples++ = PA_INT16_SWAP((int16_t) t);
100 if (PA_UNLIKELY(++channel >= channels))
105 static void pa_volume_float32ne_c(float *samples, const float *volumes, unsigned channels, unsigned length) {
108 length /= sizeof(float);
110 for (channel = 0; length; length--) {
111 *samples++ *= volumes[channel];
113 if (PA_UNLIKELY(++channel >= channels))
118 static void pa_volume_float32re_c(float *samples, const float *volumes, unsigned channels, unsigned length) {
121 length /= sizeof(float);
123 for (channel = 0; length; length--) {
126 t = PA_READ_FLOAT32RE(samples);
127 t *= volumes[channel];
128 PA_WRITE_FLOAT32RE(samples++, t);
130 if (PA_UNLIKELY(++channel >= channels))
135 static void pa_volume_s32ne_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
138 length /= sizeof(int32_t);
140 for (channel = 0; length; length--) {
143 t = (int64_t)(*samples);
144 t = (t * volumes[channel]) >> 16;
145 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
146 *samples++ = (int32_t) t;
148 if (PA_UNLIKELY(++channel >= channels))
153 static void pa_volume_s32re_c(int32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
156 length /= sizeof(int32_t);
158 for (channel = 0; length; length--) {
161 t = (int64_t) PA_INT32_SWAP(*samples);
162 t = (t * volumes[channel]) >> 16;
163 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
164 *samples++ = PA_INT32_SWAP((int32_t) t);
166 if (PA_UNLIKELY(++channel >= channels))
171 static void pa_volume_s24ne_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
175 e = samples + length;
177 for (channel = 0; samples < e; samples += 3) {
180 t = (int64_t)((int32_t) (PA_READ24NE(samples) << 8));
181 t = (t * volumes[channel]) >> 16;
182 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
183 PA_WRITE24NE(samples, ((uint32_t) (int32_t) t) >> 8);
185 if (PA_UNLIKELY(++channel >= channels))
190 static void pa_volume_s24re_c(uint8_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
194 e = samples + length;
196 for (channel = 0; samples < e; samples += 3) {
199 t = (int64_t)((int32_t) (PA_READ24RE(samples) << 8));
200 t = (t * volumes[channel]) >> 16;
201 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
202 PA_WRITE24RE(samples, ((uint32_t) (int32_t) t) >> 8);
204 if (PA_UNLIKELY(++channel >= channels))
209 static void pa_volume_s24_32ne_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
212 length /= sizeof(uint32_t);
214 for (channel = 0; length; length--) {
217 t = (int64_t) ((int32_t) (*samples << 8));
218 t = (t * volumes[channel]) >> 16;
219 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
220 *samples++ = ((uint32_t) ((int32_t) t)) >> 8;
222 if (PA_UNLIKELY(++channel >= channels))
227 static void pa_volume_s24_32re_c(uint32_t *samples, const int32_t *volumes, unsigned channels, unsigned length) {
230 length /= sizeof(uint32_t);
232 for (channel = 0; length; length--) {
235 t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples) << 8));
236 t = (t * volumes[channel]) >> 16;
237 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
238 *samples++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8);
240 if (PA_UNLIKELY(++channel >= channels))
245 static pa_do_volume_func_t do_volume_table[] = {
246 [PA_SAMPLE_U8] = (pa_do_volume_func_t) pa_volume_u8_c,
247 [PA_SAMPLE_ALAW] = (pa_do_volume_func_t) pa_volume_alaw_c,
248 [PA_SAMPLE_ULAW] = (pa_do_volume_func_t) pa_volume_ulaw_c,
249 [PA_SAMPLE_S16NE] = (pa_do_volume_func_t) pa_volume_s16ne_c,
250 [PA_SAMPLE_S16RE] = (pa_do_volume_func_t) pa_volume_s16re_c,
251 [PA_SAMPLE_FLOAT32NE] = (pa_do_volume_func_t) pa_volume_float32ne_c,
252 [PA_SAMPLE_FLOAT32RE] = (pa_do_volume_func_t) pa_volume_float32re_c,
253 [PA_SAMPLE_S32NE] = (pa_do_volume_func_t) pa_volume_s32ne_c,
254 [PA_SAMPLE_S32RE] = (pa_do_volume_func_t) pa_volume_s32re_c,
255 [PA_SAMPLE_S24NE] = (pa_do_volume_func_t) pa_volume_s24ne_c,
256 [PA_SAMPLE_S24RE] = (pa_do_volume_func_t) pa_volume_s24re_c,
257 [PA_SAMPLE_S24_32NE] = (pa_do_volume_func_t) pa_volume_s24_32ne_c,
258 [PA_SAMPLE_S24_32RE] = (pa_do_volume_func_t) pa_volume_s24_32re_c
261 pa_do_volume_func_t pa_get_volume_func(pa_sample_format_t f) {
262 pa_assert(pa_sample_format_valid(f));
264 return do_volume_table[f];
267 void pa_set_volume_func(pa_sample_format_t f, pa_do_volume_func_t func) {
268 pa_assert(pa_sample_format_valid(f));
270 do_volume_table[f] = func;