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