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