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