2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk.com>
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.
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.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
27 #include <pulse/xmalloc.h>
28 #include <pulse/sample.h>
29 #include <pulse/volume.h>
30 #include <pulsecore/log.h>
31 #include <pulsecore/macro.h>
36 static void remap_mono_to_stereo_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
39 for (i = n >> 2; i; i--) {
40 dst[0] = dst[1] = src[0];
41 dst[2] = dst[3] = src[1];
42 dst[4] = dst[5] = src[2];
43 dst[6] = dst[7] = src[3];
47 for (i = n & 3; i; i--) {
48 dst[0] = dst[1] = src[0];
54 static void remap_mono_to_stereo_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
57 for (i = n >> 2; i; i--) {
58 dst[0] = dst[1] = src[0];
59 dst[2] = dst[3] = src[1];
60 dst[4] = dst[5] = src[2];
61 dst[6] = dst[7] = src[3];
65 for (i = n & 3; i; i--) {
66 dst[0] = dst[1] = src[0];
72 static void remap_mono_to_stereo_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
75 for (i = n >> 2; i; i--) {
76 dst[0] = dst[1] = src[0];
77 dst[2] = dst[3] = src[1];
78 dst[4] = dst[5] = src[2];
79 dst[6] = dst[7] = src[3];
83 for (i = n & 3; i; i--) {
84 dst[0] = dst[1] = src[0];
90 static void remap_stereo_to_mono_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
93 for (i = n >> 2; i > 0; i--) {
94 dst[0] = (src[0] + src[1])/2;
95 dst[1] = (src[2] + src[3])/2;
96 dst[2] = (src[4] + src[5])/2;
97 dst[3] = (src[6] + src[7])/2;
101 for (i = n & 3; i; i--) {
102 dst[0] = (src[0] + src[1])/2;
108 static void remap_stereo_to_mono_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
111 for (i = n >> 2; i > 0; i--) {
112 /* Avoid overflow by performing division first. We accept a
113 * difference of +/- 1 to the ideal result. */
114 dst[0] = (src[0]/2 + src[1]/2);
115 dst[1] = (src[2]/2 + src[3]/2);
116 dst[2] = (src[4]/2 + src[5]/2);
117 dst[3] = (src[6]/2 + src[7]/2);
121 for (i = n & 3; i; i--) {
122 /* Avoid overflow by performing division first. We accept a
123 * difference of +/- 1 to the ideal result. */
124 dst[0] = (src[0]/2 + src[1]/2);
130 static void remap_stereo_to_mono_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
133 for (i = n >> 2; i > 0; i--) {
134 dst[0] = (src[0] + src[1])*0.5f;
135 dst[1] = (src[2] + src[3])*0.5f;
136 dst[2] = (src[4] + src[5])*0.5f;
137 dst[3] = (src[6] + src[7])*0.5f;
141 for (i = n & 3; i; i--) {
142 dst[0] = (src[0] + src[1])*0.5f;
148 static void remap_mono_to_ch4_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
151 for (i = n >> 2; i; i--) {
152 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
153 dst[4] = dst[5] = dst[6] = dst[7] = src[1];
154 dst[8] = dst[9] = dst[10] = dst[11] = src[2];
155 dst[12] = dst[13] = dst[14] = dst[15] = src[3];
159 for (i = n & 3; i; i--) {
160 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
166 static void remap_mono_to_ch4_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
169 for (i = n >> 2; i; i--) {
170 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
171 dst[4] = dst[5] = dst[6] = dst[7] = src[1];
172 dst[8] = dst[9] = dst[10] = dst[11] = src[2];
173 dst[12] = dst[13] = dst[14] = dst[15] = src[3];
177 for (i = n & 3; i; i--) {
178 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
184 static void remap_mono_to_ch4_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
187 for (i = n >> 2; i; i--) {
188 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
189 dst[4] = dst[5] = dst[6] = dst[7] = src[1];
190 dst[8] = dst[9] = dst[10] = dst[11] = src[2];
191 dst[12] = dst[13] = dst[14] = dst[15] = src[3];
195 for (i = n & 3; i; i--) {
196 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
202 static void remap_ch4_to_mono_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
205 for (i = n >> 2; i > 0; i--) {
206 dst[0] = (src[0] + src[1] + src[2] + src[3])/4;
207 dst[1] = (src[4] + src[5] + src[6] + src[7])/4;
208 dst[2] = (src[8] + src[9] + src[10] + src[11])/4;
209 dst[3] = (src[12] + src[13] + src[14] + src[15])/4;
213 for (i = n & 3; i; i--) {
214 dst[0] = (src[0] + src[1] + src[2] + src[3])/4;
220 static void remap_ch4_to_mono_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
223 for (i = n >> 2; i > 0; i--) {
224 /* Avoid overflow by performing division first. We accept a
225 * difference of +/- 3 to the ideal result. */
226 dst[0] = (src[0]/4 + src[1]/4 + src[2]/4 + src[3]/4);
227 dst[1] = (src[4]/4 + src[5]/4 + src[6]/4 + src[7]/4);
228 dst[2] = (src[8]/4 + src[9]/4 + src[10]/4 + src[11]/4);
229 dst[3] = (src[12]/4 + src[13]/4 + src[14]/4 + src[15]/4);
233 for (i = n & 3; i; i--) {
234 /* Avoid overflow by performing division first. We accept a
235 * difference of +/- 3 to the ideal result. */
236 dst[0] = (src[0]/4 + src[1]/4 + src[2]/4 + src[3]/4);
242 static void remap_ch4_to_mono_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
245 for (i = n >> 2; i > 0; i--) {
246 dst[0] = (src[0] + src[1] + src[2] + src[3])*0.25f;
247 dst[1] = (src[4] + src[5] + src[6] + src[7])*0.25f;
248 dst[2] = (src[8] + src[9] + src[10] + src[11])*0.25f;
249 dst[3] = (src[12] + src[13] + src[14] + src[15])*0.25f;
253 for (i = n & 3; i; i--) {
254 dst[0] = (src[0] + src[1] + src[2] + src[3])*0.25f;
260 static void remap_channels_matrix_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
265 n_ic = m->i_ss.channels;
266 n_oc = m->o_ss.channels;
268 memset(dst, 0, n * sizeof(int16_t) * n_oc);
270 for (oc = 0; oc < n_oc; oc++) {
272 for (ic = 0; ic < n_ic; ic++) {
273 int16_t *d = dst + oc;
274 const int16_t *s = src + ic;
275 int32_t vol = m->map_table_i[oc][ic];
280 if (vol >= 0x10000) {
281 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
284 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
285 *d += (int16_t) (((int32_t)*s * vol) >> 16);
291 static void remap_channels_matrix_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
295 n_ic = m->i_ss.channels;
296 n_oc = m->o_ss.channels;
298 memset(dst, 0, n * sizeof(int32_t) * n_oc);
300 for (oc = 0; oc < n_oc; oc++) {
302 for (ic = 0; ic < n_ic; ic++) {
303 int32_t *d = dst + oc;
304 const int32_t *s = src + ic;
305 int32_t vol = m->map_table_i[oc][ic];
310 if (vol >= 0x10000) {
311 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
314 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
315 *d += (int32_t) (((int64_t)*s * vol) >> 16);
321 static void remap_channels_matrix_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
325 n_ic = m->i_ss.channels;
326 n_oc = m->o_ss.channels;
328 memset(dst, 0, n * sizeof(float) * n_oc);
330 for (oc = 0; oc < n_oc; oc++) {
332 for (ic = 0; ic < n_ic; ic++) {
334 const float *s = src + ic;
335 float vol = m->map_table_f[oc][ic];
341 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
344 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
351 /* Produce an array containing input channel indices to map to output channels.
352 * If the output channel is empty, the array element is -1. */
353 bool pa_setup_remap_arrange(const pa_remap_t *m, int8_t arrange[PA_CHANNELS_MAX]) {
356 unsigned count_output = 0;
360 n_ic = m->i_ss.channels;
361 n_oc = m->o_ss.channels;
363 for (oc = 0; oc < n_oc; oc++) {
365 for (ic = 0; ic < n_ic; ic++) {
366 int32_t vol = m->map_table_i[oc][ic];
368 /* input channel is not used */
372 /* if mixing this channel, we cannot just rearrange */
373 if (vol != 0x10000 || arrange[oc] >= 0)
381 return count_output > 0;
384 static void remap_arrange_mono_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
385 const unsigned n_ic = m->i_ss.channels;
386 const int8_t *arrange = m->state;
395 static void remap_arrange_stereo_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
396 const unsigned n_ic = m->i_ss.channels;
397 const int8_t *arrange = m->state;
398 const int8_t ic0 = arrange[0], ic1 = arrange[1];
401 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
402 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
407 static void remap_arrange_ch4_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
408 const unsigned n_ic = m->i_ss.channels;
409 const int8_t *arrange = m->state;
410 const int8_t ic0 = arrange[0], ic1 = arrange[1],
411 ic2 = arrange[2], ic3 = arrange[3];
414 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
415 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
416 *dst++ = (ic2 >= 0) ? *(src + ic2) : 0;
417 *dst++ = (ic3 >= 0) ? *(src + ic3) : 0;
422 static void remap_arrange_mono_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
423 const unsigned n_ic = m->i_ss.channels;
424 const int8_t *arrange = m->state;
433 static void remap_arrange_stereo_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
434 const unsigned n_ic = m->i_ss.channels;
435 const int8_t *arrange = m->state;
436 const int ic0 = arrange[0], ic1 = arrange[1];
439 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
440 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
445 static void remap_arrange_ch4_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
446 const unsigned n_ic = m->i_ss.channels;
447 const int8_t *arrange = m->state;
448 const int ic0 = arrange[0], ic1 = arrange[1],
449 ic2 = arrange[2], ic3 = arrange[3];
452 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
453 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
454 *dst++ = (ic2 >= 0) ? *(src + ic2) : 0;
455 *dst++ = (ic3 >= 0) ? *(src + ic3) : 0;
460 static void remap_arrange_mono_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
461 const unsigned n_ic = m->i_ss.channels;
462 const int8_t *arrange = m->state;
471 static void remap_arrange_stereo_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
472 const unsigned n_ic = m->i_ss.channels;
473 const int8_t *arrange = m->state;
474 const int ic0 = arrange[0], ic1 = arrange[1];
477 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0.0f;
478 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0.0f;
483 static void remap_arrange_ch4_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
484 const unsigned n_ic = m->i_ss.channels;
485 const int8_t *arrange = m->state;
486 const int ic0 = arrange[0], ic1 = arrange[1],
487 ic2 = arrange[2], ic3 = arrange[3];
490 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0.0f;
491 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0.0f;
492 *dst++ = (ic2 >= 0) ? *(src + ic2) : 0.0f;
493 *dst++ = (ic3 >= 0) ? *(src + ic3) : 0.0f;
498 void pa_set_remap_func(pa_remap_t *m, pa_do_remap_func_t func_s16,
499 pa_do_remap_func_t func_s32, pa_do_remap_func_t func_float) {
503 if (m->format == PA_SAMPLE_S16NE)
504 m->do_remap = func_s16;
505 else if (m->format == PA_SAMPLE_S32NE)
506 m->do_remap = func_s32;
507 else if (m->format == PA_SAMPLE_FLOAT32NE)
508 m->do_remap = func_float;
510 pa_assert_not_reached();
511 pa_assert(m->do_remap);
514 static bool force_generic_code = false;
516 /* set the function that will execute the remapping based on the matrices */
517 static void init_remap_c(pa_remap_t *m) {
519 int8_t arrange[PA_CHANNELS_MAX];
521 n_oc = m->o_ss.channels;
522 n_ic = m->i_ss.channels;
524 /* find some common channel remappings, fall back to full matrix operation. */
525 if (force_generic_code) {
526 pa_log_info("Forced to use generic matrix remapping");
527 pa_set_remap_func(m, (pa_do_remap_func_t) remap_channels_matrix_s16ne_c,
528 (pa_do_remap_func_t) remap_channels_matrix_s32ne_c,
529 (pa_do_remap_func_t) remap_channels_matrix_float32ne_c);
533 if (n_ic == 1 && n_oc == 2 &&
534 m->map_table_i[0][0] == 0x10000 && m->map_table_i[1][0] == 0x10000) {
536 pa_log_info("Using mono to stereo remapping");
537 pa_set_remap_func(m, (pa_do_remap_func_t) remap_mono_to_stereo_s16ne_c,
538 (pa_do_remap_func_t) remap_mono_to_stereo_s32ne_c,
539 (pa_do_remap_func_t) remap_mono_to_stereo_float32ne_c);
540 } else if (n_ic == 2 && n_oc == 1 &&
541 m->map_table_i[0][0] == 0x8000 && m->map_table_i[0][1] == 0x8000) {
543 pa_log_info("Using stereo to mono remapping");
544 pa_set_remap_func(m, (pa_do_remap_func_t) remap_stereo_to_mono_s16ne_c,
545 (pa_do_remap_func_t) remap_stereo_to_mono_s32ne_c,
546 (pa_do_remap_func_t) remap_stereo_to_mono_float32ne_c);
547 } else if (n_ic == 1 && n_oc == 4 &&
548 m->map_table_i[0][0] == 0x10000 && m->map_table_i[1][0] == 0x10000 &&
549 m->map_table_i[2][0] == 0x10000 && m->map_table_i[3][0] == 0x10000) {
551 pa_log_info("Using mono to 4-channel remapping");
552 pa_set_remap_func(m, (pa_do_remap_func_t)remap_mono_to_ch4_s16ne_c,
553 (pa_do_remap_func_t) remap_mono_to_ch4_s32ne_c,
554 (pa_do_remap_func_t) remap_mono_to_ch4_float32ne_c);
555 } else if (n_ic == 4 && n_oc == 1 &&
556 m->map_table_i[0][0] == 0x4000 && m->map_table_i[0][1] == 0x4000 &&
557 m->map_table_i[0][2] == 0x4000 && m->map_table_i[0][3] == 0x4000) {
559 pa_log_info("Using 4-channel to mono remapping");
560 pa_set_remap_func(m, (pa_do_remap_func_t) remap_ch4_to_mono_s16ne_c,
561 (pa_do_remap_func_t) remap_ch4_to_mono_s32ne_c,
562 (pa_do_remap_func_t) remap_ch4_to_mono_float32ne_c);
563 } else if (pa_setup_remap_arrange(m, arrange) && n_oc == 1) {
565 pa_log_info("Using mono arrange remapping");
566 pa_set_remap_func(m, (pa_do_remap_func_t) remap_arrange_mono_s16ne_c,
567 (pa_do_remap_func_t) remap_arrange_mono_s32ne_c,
568 (pa_do_remap_func_t) remap_arrange_mono_float32ne_c);
571 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
572 } else if (pa_setup_remap_arrange(m, arrange) && n_oc == 2) {
574 pa_log_info("Using stereo arrange remapping");
575 pa_set_remap_func(m, (pa_do_remap_func_t) remap_arrange_stereo_s16ne_c,
576 (pa_do_remap_func_t) remap_arrange_stereo_s32ne_c,
577 (pa_do_remap_func_t) remap_arrange_stereo_float32ne_c);
580 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
581 } else if (pa_setup_remap_arrange(m, arrange) && n_oc == 4) {
583 pa_log_info("Using 4-channel arrange remapping");
584 pa_set_remap_func(m, (pa_do_remap_func_t) remap_arrange_ch4_s16ne_c,
585 (pa_do_remap_func_t) remap_arrange_ch4_s32ne_c,
586 (pa_do_remap_func_t) remap_arrange_ch4_float32ne_c);
589 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
592 pa_log_info("Using generic matrix remapping");
593 pa_set_remap_func(m, (pa_do_remap_func_t) remap_channels_matrix_s16ne_c,
594 (pa_do_remap_func_t) remap_channels_matrix_s32ne_c,
595 (pa_do_remap_func_t) remap_channels_matrix_float32ne_c);
599 /* default C implementation */
600 static pa_init_remap_func_t init_remap_func = init_remap_c;
602 void pa_init_remap_func(pa_remap_t *m) {
603 pa_assert(init_remap_func);
607 /* call the installed remap init function */
610 if (m->do_remap == NULL) {
611 /* nothing was installed, fallback to C version */
616 pa_init_remap_func_t pa_get_init_remap_func(void) {
617 return init_remap_func;
620 void pa_set_init_remap_func(pa_init_remap_func_t func) {
621 init_remap_func = func;
624 void pa_remap_func_init(const pa_cpu_info *cpu_info) {
625 force_generic_code = cpu_info->force_generic_code;