]> code.delx.au - pulseaudio/blob - src/pulsecore/sample-util.c
sample-utils: split out functions from case
[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.1 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 typedef struct pa_volume_funcs {
694 void (*u8) (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length);
695 void (*alaw) (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length);
696 void (*ulaw) (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length);
697 void (*s16ne) (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length);
698 void (*s16re) (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length);
699 void (*float32ne) (float *samples, float *volumes, unsigned channels, unsigned length);
700 void (*float32re) (float *samples, float *volumes, unsigned channels, unsigned length);
701 void (*s32ne) (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length);
702 void (*s32re) (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length);
703 void (*s24ne) (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length);
704 void (*s24re) (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length);
705 void (*s24_32ne) (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length);
706 void (*s24_32re) (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length);
707 } pa_volume_funcs;
708
709 static void
710 pa_volume_u8_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
711 {
712 unsigned channel;
713
714 for (channel = 0; length; length--) {
715 int32_t t, hi, lo;
716
717 hi = volumes[channel] >> 16;
718 lo = volumes[channel] & 0xFFFF;
719
720 t = (int32_t) *samples - 0x80;
721 t = ((t * lo) >> 16) + (t * hi);
722 t = PA_CLAMP_UNLIKELY(t, -0x80, 0x7F);
723 *samples++ = (uint8_t) (t + 0x80);
724
725 if (PA_UNLIKELY(++channel >= channels))
726 channel = 0;
727 }
728 }
729
730 static void
731 pa_volume_alaw_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
732 {
733 unsigned channel;
734
735 for (channel = 0; length; length--) {
736 int32_t t, hi, lo;
737
738 hi = volumes[channel] >> 16;
739 lo = volumes[channel] & 0xFFFF;
740
741 t = (int32_t) st_alaw2linear16(*samples);
742 t = ((t * lo) >> 16) + (t * hi);
743 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
744 *samples++ = (uint8_t) st_13linear2alaw((int16_t) t >> 3);
745
746 if (PA_UNLIKELY(++channel >= channels))
747 channel = 0;
748 }
749 }
750
751 static void
752 pa_volume_ulaw_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
753 {
754 unsigned channel;
755
756 for (channel = 0; length; length--) {
757 int32_t t, hi, lo;
758
759 hi = volumes[channel] >> 16;
760 lo = volumes[channel] & 0xFFFF;
761
762 t = (int32_t) st_ulaw2linear16(*samples);
763 t = ((t * lo) >> 16) + (t * hi);
764 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
765 *samples++ = (uint8_t) st_14linear2ulaw((int16_t) t >> 2);
766
767 if (PA_UNLIKELY(++channel >= channels))
768 channel = 0;
769 }
770 }
771
772 static void
773 pa_volume_s16ne_c (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
774 {
775 unsigned channel;
776
777 length /= sizeof (int16_t);
778
779 for (channel = 0; length; length--) {
780 int32_t t, hi, lo;
781
782 /* Multiplying the 32bit volume factor with the 16bit
783 * sample might result in an 48bit value. We want to
784 * do without 64 bit integers and hence do the
785 * multiplication independantly for the HI and LO part
786 * of the volume. */
787
788 hi = volumes[channel] >> 16;
789 lo = volumes[channel] & 0xFFFF;
790
791 t = (int32_t)(*samples);
792 t = ((t * lo) >> 16) + (t * hi);
793 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
794 *samples++ = (int16_t) t;
795
796 if (PA_UNLIKELY(++channel >= channels))
797 channel = 0;
798 }
799 }
800
801 static void
802 pa_volume_s16re_c (int16_t *samples, int32_t *volumes, unsigned channels, unsigned length)
803 {
804 unsigned channel;
805
806 length /= sizeof (int16_t);
807
808 for (channel = 0; length; length--) {
809 int32_t t, hi, lo;
810
811 hi = volumes[channel] >> 16;
812 lo = volumes[channel] & 0xFFFF;
813
814 t = (int32_t) PA_INT16_SWAP(*samples);
815 t = ((t * lo) >> 16) + (t * hi);
816 t = PA_CLAMP_UNLIKELY(t, -0x8000, 0x7FFF);
817 *samples++ = PA_INT16_SWAP((int16_t) t);
818
819 if (PA_UNLIKELY(++channel >= channels))
820 channel = 0;
821 }
822 }
823
824 static void
825 pa_volume_float32ne_c (float *samples, float *volumes, unsigned channels, unsigned length)
826 {
827 unsigned channel;
828
829 length /= sizeof (float);
830
831 for (channel = 0; length; length--) {
832 *samples++ *= volumes[channel];
833
834 if (PA_UNLIKELY(++channel >= channels))
835 channel = 0;
836 }
837 }
838
839 static void
840 pa_volume_float32re_c (float *samples, float *volumes, unsigned channels, unsigned length)
841 {
842 unsigned channel;
843
844 length /= sizeof (float);
845
846 for (channel = 0; length; length--) {
847 float t;
848
849 t = PA_FLOAT32_SWAP(*samples);
850 t *= volumes[channel];
851 *samples++ = PA_FLOAT32_SWAP(t);
852
853 if (PA_UNLIKELY(++channel >= channels))
854 channel = 0;
855 }
856 }
857
858 static void
859 pa_volume_s32ne_c (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
860 {
861 unsigned channel;
862
863 length /= sizeof (int32_t);
864
865 for (channel = 0; length; length--) {
866 int64_t t;
867
868 t = (int64_t)(*samples);
869 t = (t * volumes[channel]) >> 16;
870 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
871 *samples++ = (int32_t) t;
872
873 if (PA_UNLIKELY(++channel >= channels))
874 channel = 0;
875 }
876 }
877
878 static void
879 pa_volume_s32re_c (int32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
880 {
881 unsigned channel;
882
883 length /= sizeof (int32_t);
884
885 for (channel = 0; length; length--) {
886 int64_t t;
887
888 t = (int64_t) PA_INT32_SWAP(*samples);
889 t = (t * volumes[channel]) >> 16;
890 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
891 *samples++ = PA_INT32_SWAP((int32_t) t);
892
893 if (PA_UNLIKELY(++channel >= channels))
894 channel = 0;
895 }
896 }
897
898 static void
899 pa_volume_s24ne_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
900 {
901 unsigned channel;
902 uint8_t *e;
903
904 e = samples + length;
905
906 for (channel = 0; samples < e; samples += 3) {
907 int64_t t;
908
909 t = (int64_t)((int32_t) (PA_READ24NE(samples) << 8));
910 t = (t * volumes[channel]) >> 16;
911 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
912 PA_WRITE24NE(samples, ((uint32_t) (int32_t) t) >> 8);
913
914 if (PA_UNLIKELY(++channel >= channels))
915 channel = 0;
916 }
917 }
918
919 static void
920 pa_volume_s24re_c (uint8_t *samples, int32_t *volumes, unsigned channels, unsigned length)
921 {
922 unsigned channel;
923 uint8_t *e;
924
925 e = samples + length;
926
927 for (channel = 0; samples < e; samples += 3) {
928 int64_t t;
929
930 t = (int64_t)((int32_t) (PA_READ24RE(samples) << 8));
931 t = (t * volumes[channel]) >> 16;
932 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
933 PA_WRITE24RE(samples, ((uint32_t) (int32_t) t) >> 8);
934
935 if (PA_UNLIKELY(++channel >= channels))
936 channel = 0;
937 }
938 }
939
940 static void
941 pa_volume_s24_32ne_c (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
942 {
943 unsigned channel;
944
945 length /= sizeof (uint32_t);
946
947 for (channel = 0; length; length--) {
948 int64_t t;
949
950 t = (int64_t) ((int32_t) (*samples << 8));
951 t = (t * volumes[channel]) >> 16;
952 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
953 *samples++ = ((uint32_t) ((int32_t) t)) >> 8;
954
955 if (PA_UNLIKELY(++channel >= channels))
956 channel = 0;
957 }
958 }
959
960 static void
961 pa_volume_s24_32re_c (uint32_t *samples, int32_t *volumes, unsigned channels, unsigned length)
962 {
963 unsigned channel;
964
965 length /= sizeof (uint32_t);
966
967 for (channel = 0; length; length--) {
968 int64_t t;
969
970 t = (int64_t) ((int32_t) (PA_UINT32_SWAP(*samples) << 8));
971 t = (t * volumes[channel]) >> 16;
972 t = PA_CLAMP_UNLIKELY(t, -0x80000000LL, 0x7FFFFFFFLL);
973 *samples++ = PA_UINT32_SWAP(((uint32_t) ((int32_t) t)) >> 8);
974
975 if (PA_UNLIKELY(++channel >= channels))
976 channel = 0;
977 }
978 }
979
980 typedef void (*pa_do_volume_func) (void *samples, void *volumes, unsigned channels, unsigned length);
981 typedef void (*pa_calc_volume_func) (void *volumes, const pa_cvolume *volume);
982
983 typedef union {
984 float f;
985 uint32_t i;
986 } volume_val;
987
988 static pa_calc_volume_func calc_volume_funcs[] =
989 {
990 (pa_calc_volume_func) calc_linear_integer_volume,
991 (pa_calc_volume_func) calc_linear_integer_volume,
992 (pa_calc_volume_func) calc_linear_integer_volume,
993 (pa_calc_volume_func) calc_linear_integer_volume,
994 (pa_calc_volume_func) calc_linear_integer_volume,
995 (pa_calc_volume_func) calc_linear_float_volume,
996 (pa_calc_volume_func) calc_linear_float_volume,
997 (pa_calc_volume_func) calc_linear_integer_volume,
998 (pa_calc_volume_func) calc_linear_integer_volume,
999 (pa_calc_volume_func) calc_linear_integer_volume,
1000 (pa_calc_volume_func) calc_linear_integer_volume,
1001 (pa_calc_volume_func) calc_linear_integer_volume,
1002 (pa_calc_volume_func) calc_linear_integer_volume
1003 };
1004
1005 static pa_do_volume_func do_volume_funcs[] =
1006 {
1007 (pa_do_volume_func) pa_volume_u8_c,
1008 (pa_do_volume_func) pa_volume_alaw_c,
1009 (pa_do_volume_func) pa_volume_ulaw_c,
1010 #ifdef WORDS_BIGENDIAN
1011 (pa_do_volume_func) pa_volume_s16re_c,
1012 (pa_do_volume_func) pa_volume_s16ne_c,
1013 (pa_do_volume_func) pa_volume_float32re_c,
1014 (pa_do_volume_func) pa_volume_float32ne_c,
1015 (pa_do_volume_func) pa_volume_s32re_c,
1016 (pa_do_volume_func) pa_volume_s32ne_c,
1017 (pa_do_volume_func) pa_volume_s24re_c,
1018 (pa_do_volume_func) pa_volume_s24ne_c,
1019 (pa_do_volume_func) pa_volume_s24_32re_c
1020 (pa_do_volume_func) pa_volume_s24_32ne_c,
1021 #else
1022 (pa_do_volume_func) pa_volume_s16ne_c,
1023 (pa_do_volume_func) pa_volume_s16re_c,
1024 (pa_do_volume_func) pa_volume_float32ne_c,
1025 (pa_do_volume_func) pa_volume_float32re_c,
1026 (pa_do_volume_func) pa_volume_s32ne_c,
1027 (pa_do_volume_func) pa_volume_s32re_c,
1028 (pa_do_volume_func) pa_volume_s24ne_c,
1029 (pa_do_volume_func) pa_volume_s24re_c,
1030 (pa_do_volume_func) pa_volume_s24_32ne_c,
1031 (pa_do_volume_func) pa_volume_s24_32re_c
1032 #endif
1033 };
1034
1035 void pa_volume_memchunk(
1036 pa_memchunk*c,
1037 const pa_sample_spec *spec,
1038 const pa_cvolume *volume) {
1039
1040 void *ptr;
1041 volume_val linear[PA_CHANNELS_MAX];
1042
1043 pa_assert(c);
1044 pa_assert(spec);
1045 pa_assert(c->length % pa_frame_size(spec) == 0);
1046 pa_assert(volume);
1047
1048 if (pa_memblock_is_silence(c->memblock))
1049 return;
1050
1051 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_NORM))
1052 return;
1053
1054 if (pa_cvolume_channels_equal_to(volume, PA_VOLUME_MUTED)) {
1055 pa_silence_memchunk(c, spec);
1056 return;
1057 }
1058
1059 if (spec->format < 0 || spec->format > PA_SAMPLE_MAX) {
1060 pa_log_warn(" Unable to change volume of format %s.", pa_sample_format_to_string(spec->format));
1061 return;
1062 }
1063
1064 ptr = (uint8_t*) pa_memblock_acquire(c->memblock) + c->index;
1065
1066 calc_volume_funcs[spec->format] ((void *)linear, volume);
1067 do_volume_funcs[spec->format] (ptr, (void *)linear, spec->channels, c->length);
1068
1069 pa_memblock_release(c->memblock);
1070 }
1071
1072 size_t pa_frame_align(size_t l, const pa_sample_spec *ss) {
1073 size_t fs;
1074
1075 pa_assert(ss);
1076
1077 fs = pa_frame_size(ss);
1078
1079 return (l/fs) * fs;
1080 }
1081
1082 pa_bool_t pa_frame_aligned(size_t l, const pa_sample_spec *ss) {
1083 size_t fs;
1084
1085 pa_assert(ss);
1086
1087 fs = pa_frame_size(ss);
1088
1089 return l % fs == 0;
1090 }
1091
1092 void pa_interleave(const void *src[], unsigned channels, void *dst, size_t ss, unsigned n) {
1093 unsigned c;
1094 size_t fs;
1095
1096 pa_assert(src);
1097 pa_assert(channels > 0);
1098 pa_assert(dst);
1099 pa_assert(ss > 0);
1100 pa_assert(n > 0);
1101
1102 fs = ss * channels;
1103
1104 for (c = 0; c < channels; c++) {
1105 unsigned j;
1106 void *d;
1107 const void *s;
1108
1109 s = src[c];
1110 d = (uint8_t*) dst + c * ss;
1111
1112 for (j = 0; j < n; j ++) {
1113 oil_memcpy(d, s, (int) ss);
1114 s = (uint8_t*) s + ss;
1115 d = (uint8_t*) d + fs;
1116 }
1117 }
1118 }
1119
1120 void pa_deinterleave(const void *src, void *dst[], unsigned channels, size_t ss, unsigned n) {
1121 size_t fs;
1122 unsigned c;
1123
1124 pa_assert(src);
1125 pa_assert(dst);
1126 pa_assert(channels > 0);
1127 pa_assert(ss > 0);
1128 pa_assert(n > 0);
1129
1130 fs = ss * channels;
1131
1132 for (c = 0; c < channels; c++) {
1133 unsigned j;
1134 const void *s;
1135 void *d;
1136
1137 s = (uint8_t*) src + c * ss;
1138 d = dst[c];
1139
1140 for (j = 0; j < n; j ++) {
1141 oil_memcpy(d, s, (int) ss);
1142 s = (uint8_t*) s + fs;
1143 d = (uint8_t*) d + ss;
1144 }
1145 }
1146 }
1147
1148 static pa_memblock *silence_memblock_new(pa_mempool *pool, uint8_t c) {
1149 pa_memblock *b;
1150 size_t length;
1151 void *data;
1152
1153 pa_assert(pool);
1154
1155 length = PA_MIN(pa_mempool_block_size_max(pool), PA_SILENCE_MAX);
1156
1157 b = pa_memblock_new(pool, length);
1158
1159 data = pa_memblock_acquire(b);
1160 memset(data, c, length);
1161 pa_memblock_release(b);
1162
1163 pa_memblock_set_is_silence(b, TRUE);
1164
1165 return b;
1166 }
1167
1168 void pa_silence_cache_init(pa_silence_cache *cache) {
1169 pa_assert(cache);
1170
1171 memset(cache, 0, sizeof(pa_silence_cache));
1172 }
1173
1174 void pa_silence_cache_done(pa_silence_cache *cache) {
1175 pa_sample_format_t f;
1176 pa_assert(cache);
1177
1178 for (f = 0; f < PA_SAMPLE_MAX; f++)
1179 if (cache->blocks[f])
1180 pa_memblock_unref(cache->blocks[f]);
1181
1182 memset(cache, 0, sizeof(pa_silence_cache));
1183 }
1184
1185 pa_memchunk* pa_silence_memchunk_get(pa_silence_cache *cache, pa_mempool *pool, pa_memchunk* ret, const pa_sample_spec *spec, size_t length) {
1186 pa_memblock *b;
1187 size_t l;
1188
1189 pa_assert(cache);
1190 pa_assert(pa_sample_spec_valid(spec));
1191
1192 if (!(b = cache->blocks[spec->format]))
1193
1194 switch (spec->format) {
1195 case PA_SAMPLE_U8:
1196 cache->blocks[PA_SAMPLE_U8] = b = silence_memblock_new(pool, 0x80);
1197 break;
1198 case PA_SAMPLE_S16LE:
1199 case PA_SAMPLE_S16BE:
1200 case PA_SAMPLE_S32LE:
1201 case PA_SAMPLE_S32BE:
1202 case PA_SAMPLE_S24LE:
1203 case PA_SAMPLE_S24BE:
1204 case PA_SAMPLE_S24_32LE:
1205 case PA_SAMPLE_S24_32BE:
1206 case PA_SAMPLE_FLOAT32LE:
1207 case PA_SAMPLE_FLOAT32BE:
1208 cache->blocks[PA_SAMPLE_S16LE] = b = silence_memblock_new(pool, 0);
1209 cache->blocks[PA_SAMPLE_S16BE] = pa_memblock_ref(b);
1210 cache->blocks[PA_SAMPLE_S32LE] = pa_memblock_ref(b);
1211 cache->blocks[PA_SAMPLE_S32BE] = pa_memblock_ref(b);
1212 cache->blocks[PA_SAMPLE_S24LE] = pa_memblock_ref(b);
1213 cache->blocks[PA_SAMPLE_S24BE] = pa_memblock_ref(b);
1214 cache->blocks[PA_SAMPLE_S24_32LE] = pa_memblock_ref(b);
1215 cache->blocks[PA_SAMPLE_S24_32BE] = pa_memblock_ref(b);
1216 cache->blocks[PA_SAMPLE_FLOAT32LE] = pa_memblock_ref(b);
1217 cache->blocks[PA_SAMPLE_FLOAT32BE] = pa_memblock_ref(b);
1218 break;
1219 case PA_SAMPLE_ALAW:
1220 cache->blocks[PA_SAMPLE_ALAW] = b = silence_memblock_new(pool, 0xd5);
1221 break;
1222 case PA_SAMPLE_ULAW:
1223 cache->blocks[PA_SAMPLE_ULAW] = b = silence_memblock_new(pool, 0xff);
1224 break;
1225 default:
1226 pa_assert_not_reached();
1227 }
1228
1229 pa_assert(b);
1230
1231 ret->memblock = pa_memblock_ref(b);
1232
1233 l = pa_memblock_get_length(b);
1234 if (length > l || length == 0)
1235 length = l;
1236
1237 ret->length = pa_frame_align(length, spec);
1238 ret->index = 0;
1239
1240 return ret;
1241 }
1242
1243 void pa_sample_clamp(pa_sample_format_t format, void *dst, size_t dstr, const void *src, size_t sstr, unsigned n) {
1244 const float *s;
1245 float *d;
1246
1247 s = src; d = dst;
1248
1249 if (format == PA_SAMPLE_FLOAT32NE) {
1250
1251 float minus_one = -1.0, plus_one = 1.0;
1252 oil_clip_f32(d, (int) dstr, s, (int) sstr, (int) n, &minus_one, &plus_one);
1253
1254 } else {
1255 pa_assert(format == PA_SAMPLE_FLOAT32RE);
1256
1257 for (; n > 0; n--) {
1258 float f;
1259
1260 f = PA_FLOAT32_SWAP(*s);
1261 f = PA_CLAMP_UNLIKELY(f, -1.0f, 1.0f);
1262 *d = PA_FLOAT32_SWAP(f);
1263
1264 s = (const float*) ((const uint8_t*) s + sstr);
1265 d = (float*) ((uint8_t*) d + dstr);
1266 }
1267 }
1268 }
1269
1270 /* Similar to pa_bytes_to_usec() but rounds up, not down */
1271
1272 pa_usec_t pa_bytes_to_usec_round_up(uint64_t length, const pa_sample_spec *spec) {
1273 size_t fs;
1274 pa_usec_t usec;
1275
1276 pa_assert(spec);
1277
1278 fs = pa_frame_size(spec);
1279 length = (length + fs - 1) / fs;
1280
1281 usec = (pa_usec_t) length * PA_USEC_PER_SEC;
1282
1283 return (usec + spec->rate - 1) / spec->rate;
1284 }
1285
1286 /* Similar to pa_usec_to_bytes() but rounds up, not down */
1287
1288 size_t pa_usec_to_bytes_round_up(pa_usec_t t, const pa_sample_spec *spec) {
1289 uint64_t u;
1290 pa_assert(spec);
1291
1292 u = (uint64_t) t * (uint64_t) spec->rate;
1293
1294 u = (u + PA_USEC_PER_SEC - 1) / PA_USEC_PER_SEC;
1295
1296 u *= pa_frame_size(spec);
1297
1298 return (size_t) u;
1299 }
1300
1301 void pa_memchunk_dump_to_file(pa_memchunk *c, const char *fn) {
1302 FILE *f;
1303 void *p;
1304
1305 pa_assert(c);
1306 pa_assert(fn);
1307
1308 /* Only for debugging purposes */
1309
1310 f = fopen(fn, "a");
1311
1312 if (!f) {
1313 pa_log_warn("Failed to open '%s': %s", fn, pa_cstrerror(errno));
1314 return;
1315 }
1316
1317 p = pa_memblock_acquire(c->memblock);
1318
1319 if (fwrite((uint8_t*) p + c->index, 1, c->length, f) != c->length)
1320 pa_log_warn("Failed to write to '%s': %s", fn, pa_cstrerror(errno));
1321
1322 pa_memblock_release(c->memblock);
1323
1324 fclose(f);
1325 }
1326
1327 static void calc_sine(float *f, size_t l, double freq) {
1328 size_t i;
1329
1330 l /= sizeof(float);
1331
1332 for (i = 0; i < l; i++)
1333 *(f++) = (float) 0.5f * sin((double) i*M_PI*2*freq / (double) l);
1334 }
1335
1336 void pa_memchunk_sine(pa_memchunk *c, pa_mempool *pool, unsigned rate, unsigned freq) {
1337 size_t l;
1338 unsigned gcd, n;
1339 void *p;
1340
1341 pa_memchunk_reset(c);
1342
1343 gcd = pa_gcd(rate, freq);
1344 n = rate / gcd;
1345
1346 l = pa_mempool_block_size_max(pool) / sizeof(float);
1347
1348 l /= n;
1349 if (l <= 0) l = 1;
1350 l *= n;
1351
1352 c->length = l * sizeof(float);
1353 c->memblock = pa_memblock_new(pool, c->length);
1354
1355 p = pa_memblock_acquire(c->memblock);
1356 calc_sine(p, c->length, freq * l / rate);
1357 pa_memblock_release(c->memblock);
1358 }