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