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