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) {
69 data = pa_memblock_acquire(b);
70 pa_silence_memory(data, pa_memblock_get_length(b), spec);
71 pa_memblock_release(b);
75 void pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
82 data = pa_memblock_acquire(c->memblock);
83 pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
84 pa_memblock_release(c->memblock);
87 void pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
89 assert(p && length && spec);
91 switch (spec->format) {
97 case PA_SAMPLE_FLOAT32:
98 case PA_SAMPLE_FLOAT32RE:
109 memset(p, c, length);
113 pa_mix_info streams[],
117 const pa_sample_spec *spec,
118 const pa_cvolume *volume,
121 pa_cvolume full_volume;
131 volume = pa_cvolume_reset(&full_volume, spec->channels);
133 for (k = 0; k < nstreams; k++)
134 streams[k].internal = pa_memblock_acquire(streams[k].chunk.memblock);
136 switch (spec->format) {
137 case PA_SAMPLE_S16NE:{
138 unsigned channel = 0;
140 for (d = 0;; d += sizeof(int16_t)) {
146 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
149 for (i = 0; i < nstreams; i++) {
151 pa_volume_t cvolume = streams[i].volume.values[channel];
153 if (d >= streams[i].chunk.length)
156 if (cvolume == PA_VOLUME_MUTED)
159 v = *((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d));
161 if (cvolume != PA_VOLUME_NORM)
162 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
168 if (volume->values[channel] != PA_VOLUME_NORM)
169 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
171 if (sum < -0x8000) sum = -0x8000;
172 if (sum > 0x7FFF) sum = 0x7FFF;
176 *((int16_t*) data) = sum;
177 data = (uint8_t*) data + sizeof(int16_t);
179 if (++channel >= spec->channels)
186 case PA_SAMPLE_S16RE:{
187 unsigned channel = 0;
189 for (d = 0;; d += sizeof(int16_t)) {
195 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
198 for (i = 0; i < nstreams; i++) {
200 pa_volume_t cvolume = streams[i].volume.values[channel];
202 if (d >= streams[i].chunk.length)
205 if (cvolume == PA_VOLUME_MUTED)
208 v = INT16_SWAP(*((int16_t*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d)));
210 if (cvolume != PA_VOLUME_NORM)
211 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
217 if (volume->values[channel] != PA_VOLUME_NORM)
218 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
220 if (sum < -0x8000) sum = -0x8000;
221 if (sum > 0x7FFF) sum = 0x7FFF;
225 *((int16_t*) data) = INT16_SWAP(sum);
226 data = (uint8_t*) data + sizeof(int16_t);
228 if (++channel >= spec->channels)
236 unsigned channel = 0;
244 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
247 for (i = 0; i < nstreams; i++) {
249 pa_volume_t cvolume = streams[i].volume.values[channel];
251 if (d >= streams[i].chunk.length)
254 if (cvolume == PA_VOLUME_MUTED)
257 v = (int32_t) *((uint8_t*) streams[i].internal + streams[i].chunk.index + d) - 0x80;
259 if (cvolume != PA_VOLUME_NORM)
260 v = (int32_t) (v * pa_sw_volume_to_linear(cvolume));
266 if (volume->values[channel] != PA_VOLUME_NORM)
267 sum = (int32_t) (sum * pa_sw_volume_to_linear(volume->values[channel]));
269 if (sum < -0x80) sum = -0x80;
270 if (sum > 0x7F) sum = 0x7F;
274 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
275 data = (uint8_t*) data + 1;
277 if (++channel >= spec->channels)
284 case PA_SAMPLE_FLOAT32NE: {
285 unsigned channel = 0;
287 for (d = 0;; d += sizeof(float)) {
293 if (!mute && volume->values[channel] != PA_VOLUME_MUTED) {
296 for (i = 0; i < nstreams; i++) {
298 pa_volume_t cvolume = streams[i].volume.values[channel];
300 if (d >= streams[i].chunk.length)
303 if (cvolume == PA_VOLUME_MUTED)
306 v = *((float*) ((uint8_t*) streams[i].internal + streams[i].chunk.index + d));
308 if (cvolume != PA_VOLUME_NORM)
309 v *= pa_sw_volume_to_linear(cvolume);
315 if (volume->values[channel] != PA_VOLUME_NORM)
316 sum *= pa_sw_volume_to_linear(volume->values[channel]);
319 *((float*) data) = sum;
320 data = (uint8_t*) data + sizeof(float);
322 if (++channel >= spec->channels)
330 pa_log_error("ERROR: Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
336 for (k = 0; k < nstreams; k++)
337 pa_memblock_release(streams[k].chunk.memblock);
343 void pa_volume_memchunk(
345 const pa_sample_spec *spec,
346 const pa_cvolume *volume) {
352 assert(c->length % pa_frame_size(spec) == 0);
355 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
358 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
359 pa_silence_memchunk(c, spec);
363 ptr = pa_memblock_acquire(c->memblock);
365 switch (spec->format) {
366 case PA_SAMPLE_S16NE: {
370 double linear[PA_CHANNELS_MAX];
372 for (channel = 0; channel < spec->channels; channel++)
373 linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
375 for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
376 int32_t t = (int32_t)(*d);
378 t = (int32_t) (t * linear[channel]);
380 if (t < -0x8000) t = -0x8000;
381 if (t > 0x7FFF) t = 0x7FFF;
385 if (++channel >= spec->channels)
391 case PA_SAMPLE_S16RE: {
395 double linear[PA_CHANNELS_MAX];
397 for (channel = 0; channel < spec->channels; channel++)
398 linear[channel] = pa_sw_volume_to_linear(volume->values[channel]);
400 for (channel = 0, d = (int16_t*) ((uint8_t*) ptr + c->index), n = c->length/sizeof(int16_t); n > 0; d++, n--) {
401 int32_t t = (int32_t)(INT16_SWAP(*d));
403 t = (int32_t) (t * linear[channel]);
405 if (t < -0x8000) t = -0x8000;
406 if (t > 0x7FFF) t = 0x7FFF;
408 *d = INT16_SWAP((int16_t) t);
410 if (++channel >= spec->channels)
420 unsigned channel = 0;
422 for (d = (uint8_t*) ptr + c->index, n = c->length; n > 0; d++, n--) {
423 int32_t t = (int32_t) *d - 0x80;
425 t = (int32_t) (t * pa_sw_volume_to_linear(volume->values[channel]));
427 if (t < -0x80) t = -0x80;
428 if (t > 0x7F) t = 0x7F;
430 *d = (uint8_t) (t + 0x80);
432 if (++channel >= spec->channels)
438 case PA_SAMPLE_FLOAT32NE: {
444 d = (float*) ((uint8_t*) ptr + c->index);
445 skip = spec->channels * sizeof(float);
446 n = c->length/sizeof(float)/spec->channels;
448 for (channel = 0; channel < spec->channels ; channel ++) {
451 if (volume->values[channel] == PA_VOLUME_NORM)
454 v = (float) pa_sw_volume_to_linear(volume->values[channel]);
457 oil_scalarmult_f32(t, skip, t, skip, &v, n);
463 pa_log_error("ERROR: Unable to change volume of format %s.",
464 pa_sample_format_to_string(spec->format));
468 pa_memblock_release(c->memblock);