]> code.delx.au - pulseaudio/blob - src/pulsecore/sample-util.c
don't overflow when we do digital amplification of 16 bit samples
[pulseaudio] / src / pulsecore / sample-util.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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 of the License,
10 or (at your option) any later version.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <errno.h>
32
33 #include <liboil/liboilfuncs.h>
34 #include <liboil/liboil.h>
35
36 #include <pulse/timeval.h>
37
38 #include <pulsecore/log.h>
39 #include <pulsecore/core-error.h>
40 #include <pulsecore/macro.h>
41 #include <pulsecore/g711.h>
42 #include <pulsecore/core-util.h>
43
44 #include "sample-util.h"
45 #include "endianmacros.h"
46
47 #define PA_SILENCE_MAX (PA_PAGE_SIZE*16)
48
49 pa_memblock *pa_silence_memblock(pa_memblock* b, const pa_sample_spec *spec) {
50 void *data;
51
52 pa_assert(b);
53 pa_assert(spec);
54
55 data = pa_memblock_acquire(b);
56 pa_silence_memory(data, pa_memblock_get_length(b), spec);
57 pa_memblock_release(b);
58
59 return b;
60 }
61
62 pa_memchunk* pa_silence_memchunk(pa_memchunk *c, const pa_sample_spec *spec) {
63 void *data;
64
65 pa_assert(c);
66 pa_assert(c->memblock);
67 pa_assert(spec);
68
69 data = pa_memblock_acquire(c->memblock);
70 pa_silence_memory((uint8_t*) data+c->index, c->length, spec);
71 pa_memblock_release(c->memblock);
72
73 return c;
74 }
75
76 static uint8_t silence_byte(pa_sample_format_t format) {
77 switch (format) {
78 case PA_SAMPLE_U8:
79 return 0x80;
80 case PA_SAMPLE_S16LE:
81 case PA_SAMPLE_S16BE:
82 case PA_SAMPLE_S32LE:
83 case PA_SAMPLE_S32BE:
84 case PA_SAMPLE_FLOAT32LE:
85 case PA_SAMPLE_FLOAT32BE:
86 case PA_SAMPLE_S24LE:
87 case PA_SAMPLE_S24BE:
88 case PA_SAMPLE_S24_32LE:
89 case PA_SAMPLE_S24_32BE:
90 return 0;
91 case PA_SAMPLE_ALAW:
92 return 0xd5;
93 case PA_SAMPLE_ULAW:
94 return 0xff;
95 default:
96 pa_assert_not_reached();
97 }
98 }
99
100 void* pa_silence_memory(void *p, size_t length, const pa_sample_spec *spec) {
101 pa_assert(p);
102 pa_assert(length > 0);
103 pa_assert(spec);
104
105 memset(p, silence_byte(spec->format), length);
106 return p;
107 }
108
109 static void calc_linear_integer_volume(int32_t linear[], const pa_cvolume *volume) {
110 unsigned channel;
111
112 pa_assert(linear);
113 pa_assert(volume);
114
115 for (channel = 0; channel < volume->channels; channel++)
116 linear[channel] = (int32_t) lrint(pa_sw_volume_to_linear(volume->values[channel]) * 0x10000);
117 }
118
119 static void calc_linear_float_volume(float linear[], const pa_cvolume *volume) {
120 unsigned channel;
121
122 pa_assert(linear);
123 pa_assert(volume);
124
125 for (channel = 0; channel < volume->channels; channel++)
126 linear[channel] = (float) pa_sw_volume_to_linear(volume->values[channel]);
127 }
128
129 static void calc_linear_integer_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
130 unsigned k, channel;
131 float linear[PA_CHANNELS_MAX];
132
133 pa_assert(streams);
134 pa_assert(spec);
135 pa_assert(volume);
136
137 calc_linear_float_volume(linear, volume);
138
139 for (k = 0; k < nstreams; k++) {
140
141 for (channel = 0; channel < spec->channels; channel++) {
142 pa_mix_info *m = streams + k;
143 m->linear[channel].i = (int32_t) lrint(pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel] * 0x10000);
144 }
145 }
146 }
147
148 static void calc_linear_float_stream_volumes(pa_mix_info streams[], unsigned nstreams, const pa_cvolume *volume, const pa_sample_spec *spec) {
149 unsigned k, channel;
150 float linear[PA_CHANNELS_MAX];
151
152 pa_assert(streams);
153 pa_assert(spec);
154 pa_assert(volume);
155
156 calc_linear_float_volume(linear, volume);
157
158 for (k = 0; k < nstreams; k++) {
159
160 for (channel = 0; channel < spec->channels; channel++) {
161 pa_mix_info *m = streams + k;
162 m->linear[channel].f = (float) (pa_sw_volume_to_linear(m->volume.values[channel]) * linear[channel]);
163 }
164 }
165 }
166
167 size_t pa_mix(
168 pa_mix_info streams[],
169 unsigned nstreams,
170 void *data,
171 size_t length,
172 const pa_sample_spec *spec,
173 const pa_cvolume *volume,
174 pa_bool_t mute) {
175
176 pa_cvolume full_volume;
177 unsigned k;
178 unsigned z;
179 void *end;
180
181 pa_assert(streams);
182 pa_assert(data);
183 pa_assert(length);
184 pa_assert(spec);
185
186 if (!volume)
187 volume = pa_cvolume_reset(&full_volume, spec->channels);
188
189 if (mute || pa_cvolume_is_muted(volume) || nstreams <= 0) {
190 pa_silence_memory(data, length, spec);
191 return length;
192 }
193
194 for (k = 0; k < nstreams; k++)
195 streams[k].ptr = (uint8_t*) pa_memblock_acquire(streams[k].chunk.memblock) + streams[k].chunk.index;
196
197 for (z = 0; z < nstreams; z++)
198 if (length > streams[z].chunk.length)
199 length = streams[z].chunk.length;
200
201 end = (uint8_t*) data + length;
202
203 switch (spec->format) {
204
205 case PA_SAMPLE_S16NE:{
206 unsigned channel = 0;
207
208 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
209
210 while (data < end) {
211 int32_t sum = 0;
212 unsigned i;
213
214 for (i = 0; i < nstreams; i++) {
215 pa_mix_info *m = streams + i;
216 int32_t v, lo, hi, cv = m->linear[channel].i;
217
218 if (PA_UNLIKELY(cv <= 0))
219 continue;
220
221 /* Multiplying the 32bit volume factor with the
222 * 16bit sample might result in an 48bit value. We
223 * want to do without 64 bit integers and hence do
224 * the multiplication independantly for the HI and
225 * LO part of the volume. */
226
227 hi = cv >> 16;
228 lo = cv & 0xFFFF;
229
230 v = *((int16_t*) m->ptr);
231 v = ((v * lo) >> 16) + (v * hi);
232 sum += v;
233
234 m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
235 }
236
237 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
238 *((int16_t*) data) = (int16_t) sum;
239
240 data = (uint8_t*) data + sizeof(int16_t);
241
242 if (PA_UNLIKELY(++channel >= spec->channels))
243 channel = 0;
244 }
245
246 break;
247 }
248
249 case PA_SAMPLE_S16RE:{
250 unsigned channel = 0;
251
252 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
253
254 while (data < end) {
255 int32_t sum = 0;
256 unsigned i;
257
258 for (i = 0; i < nstreams; i++) {
259 pa_mix_info *m = streams + i;
260 int32_t v, lo, hi, cv = m->linear[channel].i;
261
262 if (PA_UNLIKELY(cv <= 0))
263 continue;
264
265 hi = cv >> 16;
266 lo = cv & 0xFFFF;
267
268 v = PA_INT16_SWAP(*((int16_t*) m->ptr));
269 v = ((v * lo) >> 16) + (v * hi);
270 sum += v;
271
272 m->ptr = (uint8_t*) m->ptr + sizeof(int16_t);
273 }
274
275 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
276 *((int16_t*) data) = PA_INT16_SWAP((int16_t) sum);
277
278 data = (uint8_t*) data + sizeof(int16_t);
279
280 if (PA_UNLIKELY(++channel >= spec->channels))
281 channel = 0;
282 }
283
284 break;
285 }
286
287 case PA_SAMPLE_S32NE:{
288 unsigned channel = 0;
289
290 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
291
292 while (data < end) {
293 int64_t sum = 0;
294 unsigned i;
295
296 for (i = 0; i < nstreams; i++) {
297 pa_mix_info *m = streams + i;
298 int32_t cv = m->linear[channel].i;
299 int64_t v;
300
301 if (PA_UNLIKELY(cv <= 0))
302 continue;
303
304 v = *((int32_t*) m->ptr);
305 v = (v * cv) >> 16;
306 sum += v;
307
308 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
309 }
310
311 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
312 *((int32_t*) data) = (int32_t) sum;
313
314 data = (uint8_t*) data + sizeof(int32_t);
315
316 if (PA_UNLIKELY(++channel >= spec->channels))
317 channel = 0;
318 }
319
320 break;
321 }
322
323 case PA_SAMPLE_S32RE:{
324 unsigned channel = 0;
325
326 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
327
328 while (data < end) {
329 int64_t sum = 0;
330 unsigned i;
331
332 for (i = 0; i < nstreams; i++) {
333 pa_mix_info *m = streams + i;
334 int32_t cv = m->linear[channel].i;
335 int64_t v;
336
337 if (PA_UNLIKELY(cv <= 0))
338 continue;
339
340 v = PA_INT32_SWAP(*((int32_t*) m->ptr));
341 v = (v * cv) >> 16;
342 sum += v;
343
344 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
345 }
346
347 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
348 *((int32_t*) data) = PA_INT32_SWAP((int32_t) sum);
349
350 data = (uint8_t*) data + sizeof(int32_t);
351
352 if (PA_UNLIKELY(++channel >= spec->channels))
353 channel = 0;
354 }
355
356 break;
357 }
358
359 case PA_SAMPLE_S24NE: {
360 unsigned channel = 0;
361
362 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
363
364 while (data < end) {
365 int64_t sum = 0;
366 unsigned i;
367
368 for (i = 0; i < nstreams; i++) {
369 pa_mix_info *m = streams + i;
370 int32_t cv = m->linear[channel].i;
371 int64_t v;
372
373 if (PA_UNLIKELY(cv <= 0))
374 continue;
375
376 v = (int32_t) (PA_READ24NE(m->ptr) << 8);
377 v = (v * cv) >> 16;
378 sum += v;
379
380 m->ptr = (uint8_t*) m->ptr + 3;
381 }
382
383 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
384 PA_WRITE24NE(data, ((uint32_t) sum) >> 8);
385
386 data = (uint8_t*) data + 3;
387
388 if (PA_UNLIKELY(++channel >= spec->channels))
389 channel = 0;
390 }
391
392 break;
393 }
394
395 case PA_SAMPLE_S24RE: {
396 unsigned channel = 0;
397
398 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
399
400 while (data < end) {
401 int64_t sum = 0;
402 unsigned i;
403
404 for (i = 0; i < nstreams; i++) {
405 pa_mix_info *m = streams + i;
406 int32_t cv = m->linear[channel].i;
407 int64_t v;
408
409 if (PA_UNLIKELY(cv <= 0))
410 continue;
411
412 v = (int32_t) (PA_READ24RE(m->ptr) << 8);
413 v = (v * cv) >> 16;
414 sum += v;
415
416 m->ptr = (uint8_t*) m->ptr + 3;
417 }
418
419 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
420 PA_WRITE24RE(data, ((uint32_t) sum) >> 8);
421
422 data = (uint8_t*) data + 3;
423
424 if (PA_UNLIKELY(++channel >= spec->channels))
425 channel = 0;
426 }
427
428 break;
429 }
430
431 case PA_SAMPLE_S24_32NE: {
432 unsigned channel = 0;
433
434 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
435
436 while (data < end) {
437 int64_t sum = 0;
438 unsigned i;
439
440 for (i = 0; i < nstreams; i++) {
441 pa_mix_info *m = streams + i;
442 int32_t cv = m->linear[channel].i;
443 int64_t v;
444
445 if (PA_UNLIKELY(cv <= 0))
446 continue;
447
448 v = (int32_t) (*((uint32_t*)m->ptr) << 8);
449 v = (v * cv) >> 16;
450 sum += v;
451
452 m->ptr = (uint8_t*) m->ptr + sizeof(int32_t);
453 }
454
455 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
456 *((uint32_t*) data) = ((uint32_t) (int32_t) sum) >> 8;
457
458 data = (uint8_t*) data + sizeof(uint32_t);
459
460 if (PA_UNLIKELY(++channel >= spec->channels))
461 channel = 0;
462 }
463
464 break;
465 }
466
467 case PA_SAMPLE_S24_32RE: {
468 unsigned channel = 0;
469
470 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
471
472 while (data < end) {
473 int64_t sum = 0;
474 unsigned i;
475
476 for (i = 0; i < nstreams; i++) {
477 pa_mix_info *m = streams + i;
478 int32_t cv = m->linear[channel].i;
479 int64_t v;
480
481 if (PA_UNLIKELY(cv <= 0))
482 continue;
483
484 v = (int32_t) (PA_UINT32_SWAP(*((uint32_t*) m->ptr)) << 8);
485 v = (v * cv) >> 16;
486 sum += v;
487
488 m->ptr = (uint8_t*) m->ptr + 3;
489 }
490
491 sum = PA_CLAMP_UNLIKELY(sum, -0x80000000LL, 0x7FFFFFFFLL);
492 *((uint32_t*) data) = PA_INT32_SWAP(((uint32_t) (int32_t) sum) >> 8);
493
494 data = (uint8_t*) data + sizeof(uint32_t);
495
496 if (PA_UNLIKELY(++channel >= spec->channels))
497 channel = 0;
498 }
499
500 break;
501 }
502
503 case PA_SAMPLE_U8: {
504 unsigned channel = 0;
505
506 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
507
508 while (data < end) {
509 int32_t sum = 0;
510 unsigned i;
511
512 for (i = 0; i < nstreams; i++) {
513 pa_mix_info *m = streams + i;
514 int32_t v, cv = m->linear[channel].i;
515
516 if (PA_UNLIKELY(cv <= 0))
517 continue;
518
519 v = (int32_t) *((uint8_t*) m->ptr) - 0x80;
520 v = (v * cv) >> 16;
521 sum += v;
522
523 m->ptr = (uint8_t*) m->ptr + 1;
524 }
525
526 sum = PA_CLAMP_UNLIKELY(sum, -0x80, 0x7F);
527 *((uint8_t*) data) = (uint8_t) (sum + 0x80);
528
529 data = (uint8_t*) data + 1;
530
531 if (PA_UNLIKELY(++channel >= spec->channels))
532 channel = 0;
533 }
534
535 break;
536 }
537
538 case PA_SAMPLE_ULAW: {
539 unsigned channel = 0;
540
541 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
542
543 while (data < end) {
544 int32_t sum = 0;
545 unsigned i;
546
547 for (i = 0; i < nstreams; i++) {
548 pa_mix_info *m = streams + i;
549 int32_t v, hi, lo, cv = m->linear[channel].i;
550
551 if (PA_UNLIKELY(cv <= 0))
552 continue;
553
554 hi = cv >> 16;
555 lo = cv & 0xFFFF;
556
557 v = (int32_t) st_ulaw2linear16(*((uint8_t*) m->ptr));
558 v = ((v * lo) >> 16) + (v * hi);
559 sum += v;
560
561 m->ptr = (uint8_t*) m->ptr + 1;
562 }
563
564 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
565 *((uint8_t*) data) = (uint8_t) st_14linear2ulaw((int16_t) sum >> 2);
566
567 data = (uint8_t*) data + 1;
568
569 if (PA_UNLIKELY(++channel >= spec->channels))
570 channel = 0;
571 }
572
573 break;
574 }
575
576 case PA_SAMPLE_ALAW: {
577 unsigned channel = 0;
578
579 calc_linear_integer_stream_volumes(streams, nstreams, volume, spec);
580
581 while (data < end) {
582 int32_t sum = 0;
583 unsigned i;
584
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;
588
589 if (PA_UNLIKELY(cv <= 0))
590 continue;
591
592 hi = cv >> 16;
593 lo = cv & 0xFFFF;
594
595 v = (int32_t) st_alaw2linear16(*((uint8_t*) m->ptr));
596 v = ((v * lo) >> 16) + (v * hi);
597 sum += v;
598
599 m->ptr = (uint8_t*) m->ptr + 1;
600 }
601
602 sum = PA_CLAMP_UNLIKELY(sum, -0x8000, 0x7FFF);
603 *((uint8_t*) data) = (uint8_t) st_13linear2alaw((int16_t) sum >> 3);
604
605 data = (uint8_t*) data + 1;
606
607 if (PA_UNLIKELY(++channel >= spec->channels))
608 channel = 0;
609 }
610
611 break;
612 }
613
614 case PA_SAMPLE_FLOAT32NE: {
615 unsigned channel = 0;
616
617 calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
618
619 while (data < end) {
620 float sum = 0;
621 unsigned i;
622
623 for (i = 0; i < nstreams; i++) {
624 pa_mix_info *m = streams + i;
625 float v, cv = m->linear[channel].f;
626
627 if (PA_UNLIKELY(cv <= 0))
628 continue;
629
630 v = *((float*) m->ptr);
631 v *= cv;
632 sum += v;
633
634 m->ptr = (uint8_t*) m->ptr + sizeof(float);
635 }
636
637 *((float*) data) = sum;
638
639 data = (uint8_t*) data + sizeof(float);
640
641 if (PA_UNLIKELY(++channel >= spec->channels))
642 channel = 0;
643 }
644
645 break;
646 }
647
648 case PA_SAMPLE_FLOAT32RE: {
649 unsigned channel = 0;
650
651 calc_linear_float_stream_volumes(streams, nstreams, volume, spec);
652
653 while (data < end) {
654 float sum = 0;
655 unsigned i;
656
657 for (i = 0; i < nstreams; i++) {
658 pa_mix_info *m = streams + i;
659 float v, cv = m->linear[channel].f;
660
661 if (PA_UNLIKELY(cv <= 0))
662 continue;
663
664 v = PA_FLOAT32_SWAP(*(float*) m->ptr);
665 v *= cv;
666 sum += v;
667
668 m->ptr = (uint8_t*) m->ptr + sizeof(float);
669 }
670
671 *((float*) data) = PA_FLOAT32_SWAP(sum);
672
673 data = (uint8_t*) data + sizeof(float);
674
675 if (PA_UNLIKELY(++channel >= spec->channels))
676 channel = 0;
677 }
678
679 break;
680 }
681
682 default:
683 pa_log_error("Unable to mix audio data of format %s.", pa_sample_format_to_string(spec->format));
684 pa_assert_not_reached();
685 }
686
687 for (k = 0; k < nstreams; k++)
688 pa_memblock_release(streams[k].chunk.memblock);
689
690 return length;
691 }
692
693
694 void pa_volume_memchunk(
695 pa_memchunk*c,
696 const pa_sample_spec *spec,
697 const pa_cvolume *volume) {
698
699 void *ptr;
700
701 pa_assert(c);
702 pa_assert(spec);
703 pa_assert(c->length % pa_frame_size(spec) == 0);
704 pa_assert(volume);
705
706 if (pa_memblock_is_silence(c->memblock))
707 return;
708
709 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
710 return;
711
712 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
713 pa_silence_memchunk(c, spec);
714 return;
715 }
716
717 ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
718
719 switch (spec->format) {
720
721 case PA_SAMPLE_S16NE: {
722 int16_t *d, *e;
723 unsigned channel;
724 int32_t linear[PA_CHANNELS_MAX];
725
726 calc_linear_integer_volume(linear, volume);
727
728 e = (int16_t*) ptr + c->length/sizeof(int16_t);
729
730 for (channel = 0, d = ptr; d < e; d++) {
731 int32_t t, hi, lo;
732
733 /* Multiplying the 32bit volume factor with the 16bit
734 * sample might result in an 48bit value. We want to
735 * do without 64 bit integers and hence do the
736 * multiplication independantly for the HI and LO part
737 * of the volume. */
738
739 hi = linear[channel] >> 16;
740 lo = linear[channel] & 0xFFFF;
741
742 t = (int32_t)(*d);
743 t = ((t * lo) >> 16) + (t * hi);
744 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
745 *d = (int16_t) t;
746
747 if (PA_UNLIKELY(++channel >= spec->channels))
748 channel = 0;
749 }
750
751 break;
752 }
753
754 case PA_SAMPLE_S16RE: {
755 int16_t *d, *e;
756 unsigned channel;
757 int32_t linear[PA_CHANNELS_MAX];
758
759 calc_linear_integer_volume(linear, volume);
760
761 e = (int16_t*) ptr + c->length/sizeof(int16_t);
762
763 for (channel = 0, d = ptr; d < e; d++) {
764 int32_t t, hi, lo;
765
766 hi = linear[channel] >> 16;
767 lo = linear[channel] & 0xFFFF;
768
769 t = (int32_t) PA_INT16_SWAP(*d);
770 t = ((t * lo) >> 16) + (t * hi);
771 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
772 *d = PA_INT16_SWAP((int16_t) t);
773
774 if (PA_UNLIKELY(++channel >= spec->channels))
775 channel = 0;
776 }
777
778 break;
779 }
780
781 case PA_SAMPLE_S32NE: {
782 int32_t *d, *e;
783 unsigned channel;
784 int32_t linear[PA_CHANNELS_MAX];
785
786 calc_linear_integer_volume(linear, volume);
787
788 e = (int32_t*) ptr + c->length/sizeof(int32_t);
789
790 for (channel = 0, d = ptr; d < e; d++) {
791 int64_t t;
792
793 t = (int64_t)(*d);
794 t = (t * linear[channel]) >> 16;
795 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
796 *d = (int32_t) t;
797
798 if (PA_UNLIKELY(++channel >= spec->channels))
799 channel = 0;
800 }
801 break;
802 }
803
804 case PA_SAMPLE_S32RE: {
805 int32_t *d, *e;
806 unsigned channel;
807 int32_t linear[PA_CHANNELS_MAX];
808
809 calc_linear_integer_volume(linear, volume);
810
811 e = (int32_t*) ptr + c->length/sizeof(int32_t);
812
813 for (channel = 0, d = ptr; d < e; d++) {
814 int64_t t;
815
816 t = (int64_t) PA_INT32_SWAP(*d);
817 t = (t * linear[channel]) >> 16;
818 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
819 *d = PA_INT32_SWAP((int32_t) t);
820
821 if (PA_UNLIKELY(++channel >= spec->channels))
822 channel = 0;
823 }
824 break;
825 }
826
827 case PA_SAMPLE_S24NE: {
828 uint8_t *d, *e;
829 unsigned channel;
830 int32_t linear[PA_CHANNELS_MAX];
831
832 calc_linear_integer_volume(linear, volume);
833
834 e = (uint8_t*) ptr + c->length/3;
835
836 for (channel = 0, d = ptr; d < e; d++) {
837 int64_t t;
838
839 t = (int64_t)((int32_t) (PA_READ24NE(d) << 8));
840 t = (t * linear[channel]) >> 16;
841 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
842 PA_WRITE24NE(d, ((uint32_t) (int32_t) t) >> 8);
843
844 if (PA_UNLIKELY(++channel >= spec->channels))
845 channel = 0;
846 }
847 break;
848 }
849
850 case PA_SAMPLE_S24RE: {
851 uint8_t *d, *e;
852 unsigned channel;
853 int32_t linear[PA_CHANNELS_MAX];
854
855 calc_linear_integer_volume(linear, volume);
856
857 e = (uint8_t*) ptr + c->length/3;
858
859 for (channel = 0, d = ptr; d < e; d++) {
860 int64_t t;
861
862 t = (int64_t)((int32_t) (PA_READ24RE(d) << 8));
863 t = (t * linear[channel]) >> 16;
864 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
865 PA_WRITE24RE(d, ((uint32_t) (int32_t) t) >> 8);
866
867 if (PA_UNLIKELY(++channel >= spec->channels))
868 channel = 0;
869 }
870 break;
871 }
872
873 case PA_SAMPLE_S24_32NE: {
874 uint32_t *d, *e;
875 unsigned channel;
876 int32_t linear[PA_CHANNELS_MAX];
877
878 calc_linear_integer_volume(linear, volume);
879
880 e = (uint32_t*) ptr + c->length/sizeof(uint32_t);
881
882 for (channel = 0, d = ptr; d < e; d++) {
883 int64_t t;
884
885 t = (int64_t) ((int32_t) (*d << 8));
886 t = (t * linear[channel]) >> 16;
887 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
888 *d = ((uint32_t) ((int32_t) t)) >> 8;
889
890 if (PA_UNLIKELY(++channel >= spec->channels))
891 channel = 0;
892 }
893 break;
894 }
895
896 case PA_SAMPLE_S24_32RE: {
897 uint32_t *d, *e;
898 unsigned channel;
899 int32_t linear[PA_CHANNELS_MAX];
900
901 calc_linear_integer_volume(linear, volume);
902
903 e = (uint32_t*) ptr + c->length/sizeof(uint32_t);
904
905 for (channel = 0, d = ptr; d < e; d++) {
906 int64_t t;
907
908 t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*d) << 8));
909 t = (t * linear[channel]) >> 16;
910 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
911 *d = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8);
912
913 if (PA_UNLIKELY(++channel >= spec->channels))
914 channel = 0;
915 }
916 break;
917 }
918
919 case PA_SAMPLE_U8: {
920 uint8_t *d, *e;
921 unsigned channel;
922 int32_t linear[PA_CHANNELS_MAX];
923
924 calc_linear_integer_volume(linear, volume);
925
926 e = (uint8_t*) ptr + c->length;
927
928 for (channel = 0, d = ptr; d < e; d++) {
929 int32_t t, hi, lo;
930
931 hi = linear[channel] >> 16;
932 lo = linear[channel] & 0xFFFF;
933
934 t = (int32_t) *d - 0x80;
935 t = ((t * lo) >> 16) + (t * hi);
936 t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
937 *d = (uint8_t) (t + 0x80);
938
939 if (PA_UNLIKELY(++channel >= spec->channels))
940 channel = 0;
941 }
942 break;
943 }
944
945 case PA_SAMPLE_ULAW: {
946 uint8_t *d, *e;
947 unsigned channel;
948 int32_t linear[PA_CHANNELS_MAX];
949
950 calc_linear_integer_volume(linear, volume);
951
952 e = (uint8_t*) ptr + c->length;
953
954 for (channel = 0, d = ptr; d < e; d++) {
955 int32_t t, hi, lo;
956
957 hi = linear[channel] >> 16;
958 lo = linear[channel] & 0xFFFF;
959
960 t = (int32_t) st_ulaw2linear16(*d);
961 t = ((t * lo) >> 16) + (t * hi);
962 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
963 *d = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
964
965 if (PA_UNLIKELY(++channel >= spec->channels))
966 channel = 0;
967 }
968 break;
969 }
970
971 case PA_SAMPLE_ALAW: {
972 uint8_t *d, *e;
973 unsigned channel;
974 int32_t linear[PA_CHANNELS_MAX];
975
976 calc_linear_integer_volume(linear, volume);
977
978 e = (uint8_t*) ptr + c->length;
979
980 for (channel = 0, d = ptr; d < e; d++) {
981 int32_t t, hi, lo;
982
983 hi = linear[channel] >> 16;
984 lo = linear[channel] & 0xFFFF;
985
986 t = (int32_t) st_alaw2linear16(*d);
987 t = ((t * lo) >> 16) + (t * hi);
988 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
989 *d = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
990
991 if (PA_UNLIKELY(++channel >= spec->channels))
992 channel = 0;
993 }
994 break;
995 }
996
997 case PA_SAMPLE_FLOAT32NE: {
998 float *d;
999 int skip;
1000 unsigned n;
1001 unsigned channel;
1002
1003 d = ptr;
1004 skip = (int) (spec->channels * sizeof(float));
1005 n = (unsigned) (c->length/sizeof(float)/spec->channels);
1006
1007 for (channel = 0; channel < spec->channels; channel ++) {
1008 float v, *t;
1009
1010 if (PA_UNLIKELY(volume->values[channel] == PA_VOLUME_NORM))
1011 continue;
1012
1013 v = (float) pa_sw_volume_to_linear(volume->values[channel]);
1014 t = d + channel;
1015 oil_scalarmult_f32(t, skip, t, skip, &v, (int) n);
1016 }
1017 break;
1018 }
1019
1020 case PA_SAMPLE_FLOAT32RE: {
1021 float *d, *e;
1022 unsigned channel;
1023 float linear[PA_CHANNELS_MAX];
1024
1025 calc_linear_float_volume(linear, volume);
1026
1027 e = (float*) ptr + c->length/sizeof(float);
1028
1029 for (channel = 0, d = ptr; d < e; d++) {
1030 float t;
1031
1032 t = PA_FLOAT32_SWAP(*d);
1033 t *= linear[channel];
1034 *d = PA_FLOAT32_SWAP(t);
1035
1036 if (PA_UNLIKELY(++channel >= spec->channels))
1037 channel = 0;
1038 }
1039
1040 break;
1041 }
1042
1043
1044 default:
1045 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec->format));
1046 /* If we cannot change the volume, we just don't do it */
1047 }
1048
1049 pa_memblock_release(c->memblock);
1050 }
1051
1052 size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
1053 size_t fs;
1054
1055 pa_assert(ss);
1056
1057 fs = pa_frame_size(ss);
1058
1059 return (l/fs) * fs;
1060 }
1061
1062 pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
1063 size_t fs;
1064
1065 pa_assert(ss);
1066
1067 fs = pa_frame_size(ss);
1068
1069 return l % fs == 0;
1070 }
1071
1072 void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
1073 unsigned c;
1074 size_t fs;
1075
1076 pa_assert(src);
1077 pa_assert(channels > 0);
1078 pa_assert(dst);
1079 pa_assert(ss > 0);
1080 pa_assert(n > 0);
1081
1082 fs = ss * channels;
1083
1084 for (c = 0; c < channels; c++) {
1085 unsigned j;
1086 void *d;
1087 const void *s;
1088
1089 s = src[c];
1090 d = (uint8_t*) dst + c * ss;
1091
1092 for (j = 0; j < n; j ++) {
1093 oil_memcpy(d, s, (int) ss);
1094 s = (uint8_t*) s + ss;
1095 d = (uint8_t*) d + fs;
1096 }
1097 }
1098 }
1099
1100 void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
1101 size_t fs;
1102 unsigned c;
1103
1104 pa_assert(src);
1105 pa_assert(dst);
1106 pa_assert(channels > 0);
1107 pa_assert(ss > 0);
1108 pa_assert(n > 0);
1109
1110 fs = ss * channels;
1111
1112 for (c = 0; c < channels; c++) {
1113 unsigned j;
1114 const void *s;
1115 void *d;
1116
1117 s = (uint8_t*) src + c * ss;
1118 d = dst[c];
1119
1120 for (j = 0; j < n; j ++) {
1121 oil_memcpy(d, s, (int) ss);
1122 s = (uint8_t*) s + fs;
1123 d = (uint8_t*) d + ss;
1124 }
1125 }
1126 }
1127
1128 static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
1129 pa_memblock *b;
1130 size_t length;
1131 void *data;
1132
1133 pa_assert(pool);
1134
1135 length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
1136
1137 b = pa_memblock_new(pool, length);
1138
1139 data = pa_memblock_acquire(b);
1140 memset(data, c, length);
1141 pa_memblock_release(b);
1142
1143 pa_memblock_set_is_silence(b, TRUE);
1144
1145 return b;
1146 }
1147
1148 void pa_silence_cache_init(pa_silence_cache *cache) {
1149 pa_assert(cache);
1150
1151 memset(cache, 0, sizeof(pa_silence_cache));
1152 }
1153
1154 void pa_silence_cache_done(pa_silence_cache *cache) {
1155 pa_sample_format_t f;
1156 pa_assert(cache);
1157
1158 for (f = 0; f < PA_SAMPLE_MAX; f++)
1159 if (cache->blocks[f])
1160 pa_memblock_unref(cache->blocks[f]);
1161
1162 memset(cache, 0, sizeof(pa_silence_cache));
1163 }
1164
1165 pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
1166 pa_memblock *b;
1167 size_t l;
1168
1169 pa_assert(cache);
1170 pa_assert(pa_sample_spec_valid(spec));
1171
1172 if (!(b = cache->blocks[spec->format]))
1173
1174 switch (spec->format) {
1175 case PA_SAMPLE_U8:
1176 cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
1177 break;
1178 case PA_SAMPLE_S16LE:
1179 case PA_SAMPLE_S16BE:
1180 case PA_SAMPLE_S32LE:
1181 case PA_SAMPLE_S32BE:
1182 case PA_SAMPLE_S24LE:
1183 case PA_SAMPLE_S24BE:
1184 case PA_SAMPLE_FLOAT32LE:
1185 case PA_SAMPLE_FLOAT32BE:
1186 cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
1187 cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
1188 cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
1189 cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
1190 cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b);
1191 cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);
1192 cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
1193 cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
1194 break;
1195 case PA_SAMPLE_ALAW:
1196 cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
1197 break;
1198 case PA_SAMPLE_ULAW:
1199 cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
1200 break;
1201 default:
1202 pa_assert_not_reached();
1203 }
1204
1205 pa_assert(b);
1206
1207 ret->memblock = pa_memblock_ref(b);
1208
1209 l = pa_memblock_get_length(b);
1210 if (length > l || length == 0)
1211 length = l;
1212
1213 ret->length = pa_frame_align(length, spec);
1214 ret->index = 0;
1215
1216 return ret;
1217 }
1218
1219 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
1220 const float *s;
1221 float *d;
1222
1223 s = src; d = dst;
1224
1225 if (format == PA_SAMPLE_FLOAT32NE) {
1226
1227 float minus_one = -1.0, plus_one = 1.0;
1228 oil_clip_f32(d, (int) dstr, s, (int) sstr, (int) n, &minus_one, &plus_one);
1229
1230 } else {
1231 pa_assert(format == PA_SAMPLE_FLOAT32RE);
1232
1233 for (; n > 0; n--) {
1234 float f;
1235
1236 f = PA_FLOAT32_SWAP(*s);
1237 f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
1238 *d = PA_FLOAT32_SWAP(f);
1239
1240 s = (const float*) ((const uint8_t*) s + sstr);
1241 d = (float*) ((uint8_t*) d + dstr);
1242 }
1243 }
1244 }
1245
1246 /* Similar to pa_bytes_to_usec() but rounds up, not down */
1247
1248 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) {
1249 size_t fs;
1250 pa_usec_t usec;
1251
1252 pa_assert(spec);
1253
1254 fs = pa_frame_size(spec);
1255 length = (length + fs - 1) / fs;
1256
1257 usec = (pa_usec_t) length * PA_USEC_PER_SEC;
1258
1259 return (usec + spec->rate - 1) / spec->rate;
1260 }
1261
1262 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1263
1264 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
1265 uint64_t u;
1266 pa_assert(spec);
1267
1268 u = (uint64_t) t * (uint64_t) spec->rate;
1269
1270 u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC;
1271
1272 u *= pa_frame_size(spec);
1273
1274 return (size_t) u;
1275 }
1276
1277 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
1278 FILE *f;
1279 void *p;
1280
1281 pa_assert(c);
1282 pa_assert(fn);
1283
1284 /* Only for debugging purposes */
1285
1286 f = fopen(fn, "a");
1287
1288 if (!f) {
1289 pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
1290 return;
1291 }
1292
1293 p = pa_memblock_acquire(c->memblock);
1294
1295 if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
1296 pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
1297
1298 pa_memblock_release(c->memblock);
1299
1300 fclose(f);
1301 }
1302
1303 static void calc_sine(float *f, size_t l, double freq) {
1304 size_t i;
1305
1306 l /= sizeof(float);
1307
1308 for (i = 0; i < l; i++)
1309 *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
1310 }
1311
1312 void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
1313 size_t l;
1314 unsigned gcd, n;
1315 void *p;
1316
1317 pa_memchunk_reset(c);
1318
1319 gcd = pa_gcd(rate, freq);
1320 n = rate / gcd;
1321
1322 l = pa_mempool_block_size_max(pool) / sizeof(float);
1323
1324 l /= n;
1325 if (l <= 0) l = 1;
1326 l *= n;
1327
1328 c->length = l * sizeof(float);
1329 c->memblock = pa_memblock_new(pool, c->length);
1330
1331 p = pa_memblock_acquire(c->memblock);
1332 calc_sine(p, c->length, freq * l / rate);
1333 pa_memblock_release(c->memblock);
1334 }