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