4 This file is part of PulseAudio.
6 Copyright 2004-2006 Lennart Poettering
7 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
9 PulseAudio is free software; you can redistribute it and/or modify
10 it under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2 of the License,
12 or (at your option) any later version.
14 PulseAudio is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 General Public License for more details.
19 You should have received a copy of the GNU Lesser General Public License
20 along with PulseAudio; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
34 #include <liboil/liboilfuncs.h>
36 #include <pulsecore/log.h>
38 #include "sample-util.h"
39 #include "endianmacros.h"
41 #define PA_SILENCE_MAX (1024*1024*1)
43 pa_memblock *pa_silence_memblock_new(pa_mempool *pool, const pa_sample_spec *spec, size_t length) {
49 length = pa_bytes_per_second(spec)/20; /* 50 ms */
51 if (length > PA_SILENCE_MAX)
52 length = PA_SILENCE_MAX;
54 fs = pa_frame_size(spec);
55 length = ((PA_SILENCE_MAX+fs-1) / fs) * fs;
60 return pa_silence_memblock(pa_memblock_new(pool, length), spec);
63 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
64 assert(b && b->data && spec);
65 pa_silence_memory(b->data, b->length, spec);
69 void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
70 assert(c && c->memblock && c->memblock->data && spec && c->length);
72 pa_silence_memory((uint8_t*) c->memblock->data+c->index, c->length, spec);
75 void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
77 assert(p && length && spec);
79 switch (spec->format) {
85 case PA_SAMPLE_FLOAT32:
86 case PA_SAMPLE_FLOAT32RE:
101 const pa_mix_info streams[],
105 const pa_sample_spec *spec,
106 const pa_cvolume *volume,
109 assert(streams && data && length && spec);
111 switch (spec->format) {
112 case PA_SAMPLE_S16NE:{
114 unsigned channel = 0;
116 for (d = 0;; d += sizeof(int16_t)) {
122 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
125 for (i = 0; i < nstreams; i++) {
127 pa_volume_t cvolume = streams[i].volume.values[channel];
129 if (d >= streams[i].chunk.length)
132 if (cvolume == PA_VOLUME_MUTED)
135 v = *((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
137 if (cvolume != PA_VOLUME_NORM)
138 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
144 if (volume->values[channel] != PA_VOLUME_NORM)
145 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
147 if (sum < -0x8000) sum = -0x8000;
148 if (sum > 0x7FFF) sum = 0x7FFF;
152 *((int16_t*) data) = sum;
153 data = (uint8_t*) data + sizeof(int16_t);
155 if (++channel >= spec->channels)
160 case PA_SAMPLE_S16RE:{
162 unsigned channel = 0;
164 for (d = 0;; d += sizeof(int16_t)) {
170 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
173 for (i = 0; i < nstreams; i++) {
175 pa_volume_t cvolume = streams[i].volume.values[channel];
177 if (d >= streams[i].chunk.length)
180 if (cvolume == PA_VOLUME_MUTED)
183 v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d)));
185 if (cvolume != PA_VOLUME_NORM)
186 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
192 if (volume->values[channel] != PA_VOLUME_NORM)
193 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
195 if (sum < -0x8000) sum = -0x8000;
196 if (sum > 0x7FFF) sum = 0x7FFF;
200 *((int16_t*) data) = INT16_SWAP(sum);
201 data = (uint8_t*) data + sizeof(int16_t);
203 if (++channel >= spec->channels)
210 unsigned channel = 0;
218 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
221 for (i = 0; i < nstreams; i++) {
223 pa_volume_t cvolume = streams[i].volume.values[channel];
225 if (d >= streams[i].chunk.length)
228 if (cvolume == PA_VOLUME_MUTED)
231 v = (int32_t) *((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d) - 0x80;
233 if (cvolume != PA_VOLUME_NORM)
234 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
240 if (volume->values[channel] != PA_VOLUME_NORM)
241 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
243 if (sum < -0x80) sum = -0x80;
244 if (sum > 0x7F) sum = 0x7F;
248 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
249 data = (uint8_t*) data + 1;
251 if (++channel >= spec->channels)
256 case PA_SAMPLE_FLOAT32NE: {
258 unsigned channel = 0;
260 for (d = 0;; d += sizeof(float)) {
266 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
269 for (i = 0; i < nstreams; i++) {
271 pa_volume_t cvolume = streams[i].volume.values[channel];
273 if (d >= streams[i].chunk.length)
276 if (cvolume == PA_VOLUME_MUTED)
279 v = *((float*) ((uint8_t*) streams[i].chunk.memblock->data + streams[i].chunk.index + d));
281 if (cvolume != PA_VOLUME_NORM)
282 v *= pa_sw_volume_to_linear(cvolume);
288 if (volume->values[channel] != PA_VOLUME_NORM)
289 sum *= pa_sw_volume_to_linear(volume->values[channel]);
292 *((float*) data) = sum;
293 data = (uint8_t*) data + sizeof(float);
295 if (++channel >= spec->channels)
301 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
307 void pa_volume_memchunk(pa_memchunk*c, const pa_sample_spec *spec, const pa_cvolume *volume) {
308 assert(c && spec && (c->length % pa_frame_size(spec) == 0));
311 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
314 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
315 pa_silence_memchunk(c, spec);
319 switch (spec->format) {
320 case PA_SAMPLE_S16NE: {
324 double linear[PA_CHANNELS_MAX];
326 for (channel = 0; channel < spec->channels; channel++)
327 linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
329 for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
330 int32_t t = (int32_t)(*d);
332 t = (int32_t) (t * linear[channel]);
334 if (t < -0x8000) t = -0x8000;
335 if (t > 0x7FFF) t = 0x7FFF;
339 if (++channel >= spec->channels)
345 case PA_SAMPLE_S16RE: {
349 double linear[PA_CHANNELS_MAX];
351 for (channel = 0; channel < spec->channels; channel++)
352 linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
354 for (channel = 0, d = (int16_t*) ((uint8_t*) c->memblock->data+c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
355 int32_t t = (int32_t)(INT16_SWAP(*d));
357 t = (int32_t) (t * linear[channel]);
359 if (t < -0x8000) t = -0x8000;
360 if (t > 0x7FFF) t = 0x7FFF;
362 *d = INT16_SWAP((int16_t) t);
364 if (++channel >= spec->channels)
374 unsigned channel = 0;
376 for (d = (uint8_t*) c->memblock->data + c->index, n = c->length; n > 0; d++, n--) {
377 int32_t t = (int32_t) *d - 0x80;
379 t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel]));
381 if (t < -0x80) t = -0x80;
382 if (t > 0x7F) t = 0x7F;
384 *d = (uint8_t) (t + 0x80);
386 if (++channel >= spec->channels)
392 case PA_SAMPLE_FLOAT32NE: {
398 d = (float*) ((uint8_t*) c->memblock->data + c->index);
399 skip = spec->channels * sizeof(float);
400 n = c->length/sizeof(float)/spec->channels;
402 for (channel = 0; channel < spec->channels ; channel ++) {
405 if (volume->values[channel] == PA_VOLUME_NORM)
408 v = (float) pa_sw_volume_to_linear(volume->values[channel]);
411 oil_scalarmult_f32(t, skip, t, skip, &v, n);
417 pa_log_error("ERROR: Unable to change volume of format %s.",
418 pa_sample_format_to_string(spec->format));