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