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