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