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
34 #include <pulse/timeval.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/core-error.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/g711.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/endianmacros.h>
43 #include "sample-util.h"
45 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
47 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
53 data = pa_memblock_acquire(b);
54 pa_silence_memory(data, pa_memblock_get_length(b), spec);
55 pa_memblock_release(b);
60 pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
64 pa_assert(c->memblock);
67 data = pa_memblock_acquire(c->memblock);
68 pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
69 pa_memblock_release(c->memblock);
74 static uint8_t silence_byte(pa_sample_format_t format) {
82 case PA_SAMPLE_FLOAT32LE:
83 case PA_SAMPLE_FLOAT32BE:
86 case PA_SAMPLE_S24_32LE:
87 case PA_SAMPLE_S24_32BE:
94 pa_assert_not_reached();
98 void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
100 pa_assert(length > 0);
103 memset(p, silence_byte(spec->format), length);
107 #define VOLUME_PADDING 32
109 static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) {
110 unsigned channel, nchannels, padding;
115 nchannels = volume->channels;
117 for (channel = 0; channel < nchannels; channel++)
118 linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
120 for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
121 linear[channel] = linear[padding];
124 static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
125 unsigned channel, nchannels, padding;
130 nchannels = volume->channels;
132 for (channel = 0; channel < nchannels; channel++)
133 linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]);
135 for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
136 linear[channel] = linear[padding];
139 static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
141 float linear[PA_CHANNELS_MAX + VOLUME_PADDING];
147 calc_linear_float_volume(linear, volume);
149 for (k = 0; k < nstreams; k++) {
151 for (channel = 0; channel < spec->channels; channel++) {
152 pa_mix_info *m = streams + k;
153 m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
158 static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
160 float linear[PA_CHANNELS_MAX + VOLUME_PADDING];
166 calc_linear_float_volume(linear, volume);
168 for (k = 0; k < nstreams; k++) {
170 for (channel = 0; channel < spec->channels; channel++) {
171 pa_mix_info *m = streams + k;
172 m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]);
178 pa_mix_info streams[],
182 const pa_sample_spec *spec,
183 const pa_cvolume *volume,
186 pa_cvolume full_volume;
197 volume = pa_cvolume_reset(&full_volume, spec->channels);
199 if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) {
200 pa_silence_memory(data, length, spec);
204 for (k = 0; k < nstreams; k++)
205 streams[k].ptr = (uint8_t*) pa_memblock_acquire(streams[k].chunk.memblock) + streams[k].chunk.index;
207 for (z = 0; z < nstreams; z++)
208 if (length > streams[z].chunk.length)
209 length = streams[z].chunk.length;
211 end = (uint8_t*) data + length;
213 switch (spec->format) {
215 case PA_SAMPLE_S16NE:{
216 unsigned channel = 0;
218 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
224 for (i = 0; i < nstreams; i++) {
225 pa_mix_info *m = streams + i;
226 int32_t v, lo, hi, cv = m->linear[channel].i;
228 if (PA_LIKELY(cv > 0)) {
230 /* Multiplying the 32bit volume factor with the
231 * 16bit sample might result in an 48bit value. We
232 * want to do without 64 bit integers and hence do
233 * the multiplication independently for the HI and
234 * LO part of the volume. */
239 v = *((int16_t*) m->ptr);
240 v = ((v * lo) >> 16) + (v * hi);
243 m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
246 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
247 *((int16_t*) data) = (int16_t) sum;
249 data = (uint8_t*) data + sizeof(int16_t);
251 if (PA_UNLIKELY(++channel >= spec->channels))
258 case PA_SAMPLE_S16RE:{
259 unsigned channel = 0;
261 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
267 for (i = 0; i < nstreams; i++) {
268 pa_mix_info *m = streams + i;
269 int32_t v, lo, hi, cv = m->linear[channel].i;
271 if (PA_LIKELY(cv > 0)) {
276 v = PA_INT16_SWAP(*((int16_t*) m->ptr));
277 v = ((v * lo) >> 16) + (v * hi);
280 m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
283 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
284 *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
286 data = (uint8_t*) data + sizeof(int16_t);
288 if (PA_UNLIKELY(++channel >= spec->channels))
295 case PA_SAMPLE_S32NE:{
296 unsigned channel = 0;
298 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
304 for (i = 0; i < nstreams; i++) {
305 pa_mix_info *m = streams + i;
306 int32_t cv = m->linear[channel].i;
309 if (PA_LIKELY(cv > 0)) {
311 v = *((int32_t*) m->ptr);
315 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
318 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
319 *((int32_t*) data) = (int32_t) sum;
321 data = (uint8_t*) data + sizeof(int32_t);
323 if (PA_UNLIKELY(++channel >= spec->channels))
330 case PA_SAMPLE_S32RE:{
331 unsigned channel = 0;
333 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
339 for (i = 0; i < nstreams; i++) {
340 pa_mix_info *m = streams + i;
341 int32_t cv = m->linear[channel].i;
344 if (PA_LIKELY(cv > 0)) {
346 v = PA_INT32_SWAP(*((int32_t*) m->ptr));
350 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
353 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
354 *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum);
356 data = (uint8_t*) data + sizeof(int32_t);
358 if (PA_UNLIKELY(++channel >= spec->channels))
365 case PA_SAMPLE_S24NE: {
366 unsigned channel = 0;
368 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
374 for (i = 0; i < nstreams; i++) {
375 pa_mix_info *m = streams + i;
376 int32_t cv = m->linear[channel].i;
379 if (PA_LIKELY(cv > 0)) {
381 v = (int32_t) (PA_READ24NE(m->ptr) << 8);
385 m->ptr = (uint8_t*) m->ptr + 3;
388 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
389 PA_WRITE24NE(data, ((uint32_t) sum) >> 8);
391 data = (uint8_t*) data + 3;
393 if (PA_UNLIKELY(++channel >= spec->channels))
400 case PA_SAMPLE_S24RE: {
401 unsigned channel = 0;
403 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
409 for (i = 0; i < nstreams; i++) {
410 pa_mix_info *m = streams + i;
411 int32_t cv = m->linear[channel].i;
414 if (PA_LIKELY(cv > 0)) {
416 v = (int32_t) (PA_READ24RE(m->ptr) << 8);
420 m->ptr = (uint8_t*) m->ptr + 3;
423 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
424 PA_WRITE24RE(data, ((uint32_t) sum) >> 8);
426 data = (uint8_t*) data + 3;
428 if (PA_UNLIKELY(++channel >= spec->channels))
435 case PA_SAMPLE_S24_32NE: {
436 unsigned channel = 0;
438 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
444 for (i = 0; i < nstreams; i++) {
445 pa_mix_info *m = streams + i;
446 int32_t cv = m->linear[channel].i;
449 if (PA_LIKELY(cv > 0)) {
451 v = (int32_t) (*((uint32_t*)m->ptr) << 8);
455 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
458 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
459 *((uint32_t*) data) = ((uint32_t) (int32_t) sum) >> 8;
461 data = (uint8_t*) data + sizeof(uint32_t);
463 if (PA_UNLIKELY(++channel >= spec->channels))
470 case PA_SAMPLE_S24_32RE: {
471 unsigned channel = 0;
473 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
479 for (i = 0; i < nstreams; i++) {
480 pa_mix_info *m = streams + i;
481 int32_t cv = m->linear[channel].i;
484 if (PA_LIKELY(cv > 0)) {
486 v = (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m->ptr)) << 8);
490 m->ptr = (uint8_t*) m->ptr + 3;
493 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
494 *((uint32_t*) data) = PA_INT32_SWAP(((uint32_t) (int32_t) sum) >> 8);
496 data = (uint8_t*) data + sizeof(uint32_t);
498 if (PA_UNLIKELY(++channel >= spec->channels))
506 unsigned channel = 0;
508 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
514 for (i = 0; i < nstreams; i++) {
515 pa_mix_info *m = streams + i;
516 int32_t v, cv = m->linear[channel].i;
518 if (PA_LIKELY(cv > 0)) {
520 v = (int32_t) *((uint8_t*) m->ptr) - 0x80;
524 m->ptr = (uint8_t*) m->ptr + 1;
527 sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F);
528 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
530 data = (uint8_t*) data + 1;
532 if (PA_UNLIKELY(++channel >= spec->channels))
539 case PA_SAMPLE_ULAW: {
540 unsigned channel = 0;
542 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
548 for (i = 0; i < nstreams; i++) {
549 pa_mix_info *m = streams + i;
550 int32_t v, hi, lo, cv = m->linear[channel].i;
552 if (PA_LIKELY(cv > 0)) {
557 v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr));
558 v = ((v * lo) >> 16) + (v * hi);
561 m->ptr = (uint8_t*) m->ptr + 1;
564 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
565 *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2);
567 data = (uint8_t*) data + 1;
569 if (PA_UNLIKELY(++channel >= spec->channels))
576 case PA_SAMPLE_ALAW: {
577 unsigned channel = 0;
579 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
585 for (i = 0; i < nstreams; i++) {
586 pa_mix_info *m = streams + i;
587 int32_t v, hi, lo, cv = m->linear[channel].i;
589 if (PA_LIKELY(cv > 0)) {
594 v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr));
595 v = ((v * lo) >> 16) + (v * hi);
598 m->ptr = (uint8_t*) m->ptr + 1;
601 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
602 *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3);
604 data = (uint8_t*) data + 1;
606 if (PA_UNLIKELY(++channel >= spec->channels))
613 case PA_SAMPLE_FLOAT32NE: {
614 unsigned channel = 0;
616 calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
622 for (i = 0; i < nstreams; i++) {
623 pa_mix_info *m = streams + i;
624 float v, cv = m->linear[channel].f;
626 if (PA_LIKELY(cv > 0)) {
628 v = *((float*) m->ptr);
632 m->ptr = (uint8_t*) m->ptr + sizeof(float);
635 *((float*) data) = sum;
637 data = (uint8_t*) data + sizeof(float);
639 if (PA_UNLIKELY(++channel >= spec->channels))
646 case PA_SAMPLE_FLOAT32RE: {
647 unsigned channel = 0;
649 calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
655 for (i = 0; i < nstreams; i++) {
656 pa_mix_info *m = streams + i;
657 float v, cv = m->linear[channel].f;
659 if (PA_LIKELY(cv > 0)) {
661 v = PA_FLOAT32_SWAP(*(float*) m->ptr);
665 m->ptr = (uint8_t*) m->ptr + sizeof(float);
668 *((float*) data) = PA_FLOAT32_SWAP(sum);
670 data = (uint8_t*) data + sizeof(float);
672 if (PA_UNLIKELY(++channel >= spec->channels))
680 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
681 pa_assert_not_reached();
684 for (k = 0; k < nstreams; k++)
685 pa_memblock_release(streams[k].chunk.memblock);
695 typedef void (*pa_calc_volume_func_t) (void *volumes, const pa_cvolume *volume);
697 static const pa_calc_volume_func_t calc_volume_table[] = {
698 [PA_SAMPLE_U8] = (pa_calc_volume_func_t) calc_linear_integer_volume,
699 [PA_SAMPLE_ALAW] = (pa_calc_volume_func_t) calc_linear_integer_volume,
700 [PA_SAMPLE_ULAW] = (pa_calc_volume_func_t) calc_linear_integer_volume,
701 [PA_SAMPLE_S16LE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
702 [PA_SAMPLE_S16BE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
703 [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_func_t) calc_linear_float_volume,
704 [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_func_t) calc_linear_float_volume,
705 [PA_SAMPLE_S32LE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
706 [PA_SAMPLE_S32BE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
707 [PA_SAMPLE_S24LE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
708 [PA_SAMPLE_S24BE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
709 [PA_SAMPLE_S24_32LE] = (pa_calc_volume_func_t) calc_linear_integer_volume,
710 [PA_SAMPLE_S24_32BE] = (pa_calc_volume_func_t) calc_linear_integer_volume
713 void pa_volume_memchunk(
715 const pa_sample_spec *spec,
716 const pa_cvolume *volume) {
719 volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING];
720 pa_do_volume_func_t do_volume;
724 pa_assert(pa_sample_spec_valid(spec));
725 pa_assert(pa_frame_aligned(c->length, spec));
728 if (pa_memblock_is_silence(c->memblock))
731 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
734 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
735 pa_silence_memchunk(c, spec);
739 do_volume = pa_get_volume_func(spec->format);
740 pa_assert(do_volume);
742 calc_volume_table[spec->format] ((void *)linear, volume);
744 ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
746 do_volume (ptr, (void *)linear, spec->channels, c->length);
748 pa_memblock_release(c->memblock);
751 size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
756 fs = pa_frame_size(ss);
761 pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
766 fs = pa_frame_size(ss);
771 void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
776 pa_assert(channels > 0);
783 for (c = 0; c < channels; c++) {
789 d = (uint8_t*) dst + c * ss;
791 for (j = 0; j < n; j ++) {
792 memcpy(d, s, (int) ss);
793 s = (uint8_t*) s + ss;
794 d = (uint8_t*) d + fs;
799 void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
805 pa_assert(channels > 0);
811 for (c = 0; c < channels; c++) {
816 s = (uint8_t*) src + c * ss;
819 for (j = 0; j < n; j ++) {
820 memcpy(d, s, (int) ss);
821 s = (uint8_t*) s + fs;
822 d = (uint8_t*) d + ss;
827 static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
834 length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
836 b = pa_memblock_new(pool, length);
838 data = pa_memblock_acquire(b);
839 memset(data, c, length);
840 pa_memblock_release(b);
842 pa_memblock_set_is_silence(b, TRUE);
847 void pa_silence_cache_init(pa_silence_cache *cache) {
850 memset(cache, 0, sizeof(pa_silence_cache));
853 void pa_silence_cache_done(pa_silence_cache *cache) {
854 pa_sample_format_t f;
857 for (f = 0; f < PA_SAMPLE_MAX; f++)
858 if (cache->blocks[f])
859 pa_memblock_unref(cache->blocks[f]);
861 memset(cache, 0, sizeof(pa_silence_cache));
864 pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
869 pa_assert(pa_sample_spec_valid(spec));
871 if (!(b = cache->blocks[spec->format]))
873 switch (spec->format) {
875 cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
877 case PA_SAMPLE_S16LE:
878 case PA_SAMPLE_S16BE:
879 case PA_SAMPLE_S32LE:
880 case PA_SAMPLE_S32BE:
881 case PA_SAMPLE_S24LE:
882 case PA_SAMPLE_S24BE:
883 case PA_SAMPLE_S24_32LE:
884 case PA_SAMPLE_S24_32BE:
885 case PA_SAMPLE_FLOAT32LE:
886 case PA_SAMPLE_FLOAT32BE:
887 cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
888 cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
889 cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
890 cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
891 cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b);
892 cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);
893 cache->blocks[PA_SAMPLE_S24_32LE] = pa_memblock_ref(b);
894 cache->blocks[PA_SAMPLE_S24_32BE] = pa_memblock_ref(b);
895 cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
896 cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
899 cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
902 cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
905 pa_assert_not_reached();
910 ret->memblock = pa_memblock_ref(b);
912 l = pa_memblock_get_length(b);
913 if (length > l || length == 0)
916 ret->length = pa_frame_align(length, spec);
922 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
928 if (format == PA_SAMPLE_FLOAT32NE) {
933 *d = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
935 s = (const float*) ((const uint8_t*) s + sstr);
936 d = (float*) ((uint8_t*) d + dstr);
939 pa_assert(format == PA_SAMPLE_FLOAT32RE);
944 f = PA_FLOAT32_SWAP(*s);
945 f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
946 *d = PA_FLOAT32_SWAP(f);
948 s = (const float*) ((const uint8_t*) s + sstr);
949 d = (float*) ((uint8_t*) d + dstr);
954 /* Similar to pa_bytes_to_usec() but rounds up, not down */
956 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) {
962 fs = pa_frame_size(spec);
963 length = (length + fs - 1) / fs;
965 usec = (pa_usec_t) length * PA_USEC_PER_SEC;
967 return (usec + spec->rate - 1) / spec->rate;
970 /* Similar to pa_usec_to_bytes() but rounds up, not down */
972 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
976 u = (uint64_t) t * (uint64_t) spec->rate;
978 u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC;
980 u *= pa_frame_size(spec);
985 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
992 /* Only for debugging purposes */
994 f = pa_fopen_cloexec(fn, "a");
997 pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
1001 p = pa_memblock_acquire(c->memblock);
1003 if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
1004 pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
1006 pa_memblock_release(c->memblock);
1011 static void calc_sine(float *f, size_t l, double freq) {
1016 for (i = 0; i < l; i++)
1017 *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
1020 void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
1025 pa_memchunk_reset(c);
1027 gcd = pa_gcd(rate, freq);
1030 l = pa_mempool_block_size_max(pool) / sizeof(float);
1036 c->length = l * sizeof(float);
1037 c->memblock = pa_memblock_new(pool, c->length);
1039 p = pa_memblock_acquire(c->memblock);
1040 calc_sine(p, c->length, freq * l / rate);
1041 pa_memblock_release(c->memblock);
1044 size_t pa_convert_size(size_t size, const pa_sample_spec *from, const pa_sample_spec *to) {
1050 usec = pa_bytes_to_usec_round_up(size, from);
1051 return pa_usec_to_bytes_round_up(usec, to);
1054 static void calc_linear_integer_volume_no_mapping(int32_t linear[], float volume[], unsigned nchannels) {
1055 unsigned channel, padding;
1060 for (channel = 0; channel < nchannels; channel++)
1061 linear[channel] = (int32_t) lrint(volume[channel] * 0x10000U);
1063 for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
1064 linear[channel] = linear[padding];
1067 static void calc_linear_float_volume_no_mapping(float linear[], float volume[], unsigned nchannels) {
1068 unsigned channel, padding;
1073 for (channel = 0; channel < nchannels; channel++)
1074 linear[channel] = volume[channel];
1076 for (padding = 0; padding < VOLUME_PADDING; padding++, channel++)
1077 linear[channel] = linear[padding];
1080 typedef void (*pa_calc_volume_no_mapping_func_t) (void *volumes, float *volume, int channels);
1082 static const pa_calc_volume_no_mapping_func_t calc_volume_table_no_mapping[] = {
1083 [PA_SAMPLE_U8] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1084 [PA_SAMPLE_ALAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1085 [PA_SAMPLE_ULAW] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1086 [PA_SAMPLE_S16LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1087 [PA_SAMPLE_S16BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1088 [PA_SAMPLE_FLOAT32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
1089 [PA_SAMPLE_FLOAT32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_float_volume_no_mapping,
1090 [PA_SAMPLE_S32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1091 [PA_SAMPLE_S32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1092 [PA_SAMPLE_S24LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1093 [PA_SAMPLE_S24BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1094 [PA_SAMPLE_S24_32LE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping,
1095 [PA_SAMPLE_S24_32BE] = (pa_calc_volume_no_mapping_func_t) calc_linear_integer_volume_no_mapping
1098 static const unsigned format_sample_size_table[] = {
1100 [PA_SAMPLE_ALAW] = 1,
1101 [PA_SAMPLE_ULAW] = 1,
1102 [PA_SAMPLE_S16LE] = 2,
1103 [PA_SAMPLE_S16BE] = 2,
1104 [PA_SAMPLE_FLOAT32LE] = 4,
1105 [PA_SAMPLE_FLOAT32BE] = 4,
1106 [PA_SAMPLE_S32LE] = 4,
1107 [PA_SAMPLE_S32BE] = 4,
1108 [PA_SAMPLE_S24LE] = 3,
1109 [PA_SAMPLE_S24BE] = 3,
1110 [PA_SAMPLE_S24_32LE] = 4,
1111 [PA_SAMPLE_S24_32BE] = 4
1114 static float calc_volume_ramp_linear(pa_volume_ramp_int_t *ramp) {
1116 pa_assert(ramp->length > 0);
1118 /* basic linear interpolation */
1119 return ramp->start + (ramp->length - ramp->left) * (ramp->end - ramp->start) / (float) ramp->length;
1122 static float calc_volume_ramp_logarithmic(pa_volume_ramp_int_t *ramp) {
1127 pa_assert(ramp->length > 0);
1129 if (ramp->end > ramp->start) {
1134 temp = ramp->length - ramp->left;
1139 x_val = temp == 0 ? 0.0 : powf(temp, 10);
1141 /* base 10 logarithmic interpolation */
1142 return s + x_val * (e - s) / powf(ramp->length, 10);
1145 static float calc_volume_ramp_cubic(pa_volume_ramp_int_t *ramp) {
1150 pa_assert(ramp->length > 0);
1152 if (ramp->end > ramp->start) {
1157 temp = ramp->length - ramp->left;
1162 x_val = temp == 0 ? 0.0 : cbrtf(temp);
1164 /* cubic interpolation */
1165 return s + x_val * (e - s) / cbrtf(ramp->length);
1168 typedef float (*pa_calc_volume_ramp_func_t) (pa_volume_ramp_int_t *);
1170 static const pa_calc_volume_ramp_func_t calc_volume_ramp_table[] = {
1171 [PA_VOLUME_RAMP_TYPE_LINEAR] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_linear,
1172 [PA_VOLUME_RAMP_TYPE_LOGARITHMIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_logarithmic,
1173 [PA_VOLUME_RAMP_TYPE_CUBIC] = (pa_calc_volume_ramp_func_t) calc_volume_ramp_cubic
1176 static void calc_volume_ramps(pa_cvolume_ramp_int *ram, float *vol)
1180 for (i = 0; i < ram->channels; i++) {
1181 if (ram->ramps[i].left <= 0) {
1182 if (ram->ramps[i].target == PA_VOLUME_NORM) {
1186 vol[i] = ram->ramps[i].curr = calc_volume_ramp_table[ram->ramps[i].type] (&ram->ramps[i]);
1187 ram->ramps[i].left--;
1192 void pa_volume_ramp_memchunk(
1194 const pa_sample_spec *spec,
1195 pa_cvolume_ramp_int *ramp) {
1198 volume_val linear[PA_CHANNELS_MAX + VOLUME_PADDING];
1199 float vol[PA_CHANNELS_MAX + VOLUME_PADDING];
1200 pa_do_volume_func_t do_volume;
1201 long length_in_frames;
1206 pa_assert(pa_frame_aligned(c->length, spec));
1209 length_in_frames = c->length / format_sample_size_table[spec->format] / spec->channels;
1211 if (pa_memblock_is_silence(c->memblock)) {
1212 for (i = 0; i < ramp->channels; i++) {
1213 if (ramp->ramps[i].length > 0)
1214 ramp->ramps[i].length -= length_in_frames;
1219 if (spec->format < 0 || spec->format >= PA_SAMPLE_MAX) {
1220 pa_log_warn("Unable to change volume of format");
1224 do_volume = pa_get_volume_func(spec->format);
1225 pa_assert(do_volume);
1227 ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
1229 for (i = 0; i < length_in_frames; i++) {
1230 calc_volume_ramps(ramp, vol);
1231 calc_volume_table_no_mapping[spec->format] ((void *)linear, vol, spec->channels);
1233 /* we only process one frame per iteration */
1234 do_volume (ptr, (void *)linear, spec->channels, format_sample_size_table[spec->format] * spec->channels);
1236 /* pa_log_debug("1: %d 2: %d", linear[0], linear[1]); */
1238 ptr = (uint8_t*)ptr + format_sample_size_table[spec->format] * spec->channels;
1241 pa_memblock_release(c->memblock);
1244 pa_cvolume_ramp_int* pa_cvolume_ramp_convert(const pa_cvolume_ramp *src, pa_cvolume_ramp_int *dst, int sample_rate) {
1248 for (i = 0; i < dst->channels; i++) {
1249 dst->ramps[i].type = src->ramps[i].type;
1251 dst->ramps[i].length = src->ramps[i].length * sample_rate / 1000;
1252 dst->ramps[i].left = dst->ramps[i].length;
1253 dst->ramps[i].start = dst->ramps[i].end;
1254 dst->ramps[i].target = src->ramps[i].target;
1255 /* scale to pulse internal mapping so that when ramp is over there's no glitch in volume */
1256 temp = src->ramps[i].target / (float)0x10000U;
1257 dst->ramps[i].end = temp * temp * temp;
1263 pa_bool_t pa_cvolume_ramp_active(pa_cvolume_ramp_int *ramp) {
1266 for (i = 0; i < ramp->channels; i++) {
1267 if (ramp->ramps[i].left > 0)
1274 pa_bool_t pa_cvolume_ramp_target_active(pa_cvolume_ramp_int *ramp) {
1277 for (i = 0; i < ramp->channels; i++) {
1278 if (ramp->ramps[i].target != PA_VOLUME_NORM)
1285 pa_cvolume * pa_cvolume_ramp_get_targets(pa_cvolume_ramp_int *ramp, pa_cvolume *volume) {
1288 volume->channels = ramp->channels;
1290 for (i = 0; i < ramp->channels; i++)
1291 volume->values[i] = ramp->ramps[i].target;
1296 pa_cvolume_ramp_int* pa_cvolume_ramp_start_from(pa_cvolume_ramp_int *src, pa_cvolume_ramp_int *dst) {
1299 for (i = 0; i < src->channels; i++) {
1300 /* if new vols are invalid, copy old ramp i.e. no effect */
1301 if (dst->ramps[i].target == PA_VOLUME_INVALID)
1302 dst->ramps[i] = src->ramps[i];
1303 /* if there's some old ramp still left */
1304 else if (src->ramps[i].left > 0)
1305 dst->ramps[i].start = src->ramps[i].curr;
1311 pa_cvolume_ramp_int* pa_cvolume_ramp_int_init(pa_cvolume_ramp_int *src, pa_volume_t vol, int channels) {
1315 src->channels = channels;
1317 for (i = 0; i < channels; i++) {
1318 src->ramps[i].type = PA_VOLUME_RAMP_TYPE_LINEAR;
1319 src->ramps[i].length = 0;
1320 src->ramps[i].left = 0;
1321 if (vol == PA_VOLUME_NORM) {
1322 src->ramps[i].start = 1.0;
1323 src->ramps[i].end = 1.0;
1324 src->ramps[i].curr = 1.0;
1326 else if (vol == PA_VOLUME_MUTED) {
1327 src->ramps[i].start = 0.0;
1328 src->ramps[i].end = 0.0;
1329 src->ramps[i].curr = 0.0;
1332 temp = vol / (float)0x10000U;
1333 src->ramps[i].start = temp * temp * temp;
1334 src->ramps[i].end = src->ramps[i].start;
1335 src->ramps[i].curr = src->ramps[i].start;
1337 src->ramps[i].target = vol;