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