1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2009 Wim Taymans <wim.taymans@collabora.co.uk.com>
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, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <string.h>
26
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>
32
33 #include "cpu.h"
34 #include "remap.h"
35
remap_mono_to_stereo_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)36 static void remap_mono_to_stereo_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
37 unsigned i;
38
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];
44 src += 4;
45 dst += 8;
46 }
47 for (i = n & 3; i; i--) {
48 dst[0] = dst[1] = src[0];
49 src++;
50 dst += 2;
51 }
52 }
53
remap_mono_to_stereo_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)54 static void remap_mono_to_stereo_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
55 unsigned i;
56
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];
62 src += 4;
63 dst += 8;
64 }
65 for (i = n & 3; i; i--) {
66 dst[0] = dst[1] = src[0];
67 src++;
68 dst += 2;
69 }
70 }
71
remap_mono_to_stereo_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)72 static void remap_mono_to_stereo_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
73 unsigned i;
74
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];
80 src += 4;
81 dst += 8;
82 }
83 for (i = n & 3; i; i--) {
84 dst[0] = dst[1] = src[0];
85 src++;
86 dst += 2;
87 }
88 }
89
remap_stereo_to_mono_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)90 static void remap_stereo_to_mono_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
91 unsigned i;
92
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;
98 src += 8;
99 dst += 4;
100 }
101 for (i = n & 3; i; i--) {
102 dst[0] = (src[0] + src[1])/2;
103 src += 2;
104 dst += 1;
105 }
106 }
107
remap_stereo_to_mono_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)108 static void remap_stereo_to_mono_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
109 unsigned i;
110
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);
118 src += 8;
119 dst += 4;
120 }
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);
125 src += 2;
126 dst += 1;
127 }
128 }
129
remap_stereo_to_mono_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)130 static void remap_stereo_to_mono_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
131 unsigned i;
132
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;
138 src += 8;
139 dst += 4;
140 }
141 for (i = n & 3; i; i--) {
142 dst[0] = (src[0] + src[1])*0.5f;
143 src += 2;
144 dst += 1;
145 }
146 }
147
remap_mono_to_ch4_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)148 static void remap_mono_to_ch4_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
149 unsigned i;
150
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];
156 src += 4;
157 dst += 16;
158 }
159 for (i = n & 3; i; i--) {
160 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
161 src++;
162 dst += 4;
163 }
164 }
165
remap_mono_to_ch4_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)166 static void remap_mono_to_ch4_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
167 unsigned i;
168
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];
174 src += 4;
175 dst += 16;
176 }
177 for (i = n & 3; i; i--) {
178 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
179 src++;
180 dst += 4;
181 }
182 }
183
remap_mono_to_ch4_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)184 static void remap_mono_to_ch4_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
185 unsigned i;
186
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];
192 src += 4;
193 dst += 16;
194 }
195 for (i = n & 3; i; i--) {
196 dst[0] = dst[1] = dst[2] = dst[3] = src[0];
197 src++;
198 dst += 4;
199 }
200 }
201
remap_ch4_to_mono_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)202 static void remap_ch4_to_mono_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
203 unsigned i;
204
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;
210 src += 16;
211 dst += 4;
212 }
213 for (i = n & 3; i; i--) {
214 dst[0] = (src[0] + src[1] + src[2] + src[3])/4;
215 src += 4;
216 dst += 1;
217 }
218 }
219
remap_ch4_to_mono_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)220 static void remap_ch4_to_mono_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
221 unsigned i;
222
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);
230 src += 16;
231 dst += 4;
232 }
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);
237 src += 4;
238 dst += 1;
239 }
240 }
241
remap_ch4_to_mono_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)242 static void remap_ch4_to_mono_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
243 unsigned i;
244
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;
250 src += 16;
251 dst += 4;
252 }
253 for (i = n & 3; i; i--) {
254 dst[0] = (src[0] + src[1] + src[2] + src[3])*0.25f;
255 src += 4;
256 dst += 1;
257 }
258 }
259
remap_channels_matrix_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)260 static void remap_channels_matrix_s16ne_c(pa_remap_t *m, int16_t *dst, const int16_t *src, unsigned n) {
261
262 unsigned oc, ic, i;
263 unsigned n_ic, n_oc;
264
265 n_ic = m->i_ss.channels;
266 n_oc = m->o_ss.channels;
267
268 memset(dst, 0, n * sizeof(int16_t) * n_oc);
269
270 for (oc = 0; oc < n_oc; oc++) {
271
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];
276
277 if (vol <= 0)
278 continue;
279
280 if (vol >= 0x10000) {
281 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
282 *d += *s;
283 } else {
284 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
285 *d += (int16_t) (((int32_t)*s * vol) >> 16);
286 }
287 }
288 }
289 }
290
remap_channels_matrix_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)291 static void remap_channels_matrix_s32ne_c(pa_remap_t *m, int32_t *dst, const int32_t *src, unsigned n) {
292 unsigned oc, ic, i;
293 unsigned n_ic, n_oc;
294
295 n_ic = m->i_ss.channels;
296 n_oc = m->o_ss.channels;
297
298 memset(dst, 0, n * sizeof(int32_t) * n_oc);
299
300 for (oc = 0; oc < n_oc; oc++) {
301
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];
306
307 if (vol <= 0)
308 continue;
309
310 if (vol >= 0x10000) {
311 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
312 *d += *s;
313 } else {
314 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
315 *d += (int32_t) (((int64_t)*s * vol) >> 16);
316 }
317 }
318 }
319 }
320
remap_channels_matrix_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)321 static void remap_channels_matrix_float32ne_c(pa_remap_t *m, float *dst, const float *src, unsigned n) {
322 unsigned oc, ic, i;
323 unsigned n_ic, n_oc;
324
325 n_ic = m->i_ss.channels;
326 n_oc = m->o_ss.channels;
327
328 memset(dst, 0, n * sizeof(float) * n_oc);
329
330 for (oc = 0; oc < n_oc; oc++) {
331
332 for (ic = 0; ic < n_ic; ic++) {
333 float *d = dst + oc;
334 const float *s = src + ic;
335 float vol = m->map_table_f[oc][ic];
336
337 if (vol <= 0.0f)
338 continue;
339
340 if (vol >= 1.0f) {
341 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
342 *d += *s;
343 } else {
344 for (i = n; i > 0; i--, s += n_ic, d += n_oc)
345 *d += *s * vol;
346 }
347 }
348 }
349 }
350
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. */
pa_setup_remap_arrange(const pa_remap_t * m,int8_t arrange[PA_CHANNELS_MAX])353 bool pa_setup_remap_arrange(const pa_remap_t *m, int8_t arrange[PA_CHANNELS_MAX]) {
354 unsigned ic, oc;
355 unsigned n_ic, n_oc;
356 unsigned count_output = 0;
357
358 pa_assert(m);
359
360 n_ic = m->i_ss.channels;
361 n_oc = m->o_ss.channels;
362
363 for (oc = 0; oc < n_oc; oc++) {
364 arrange[oc] = -1;
365 for (ic = 0; ic < n_ic; ic++) {
366 int32_t vol = m->map_table_i[oc][ic];
367
368 /* input channel is not used */
369 if (vol == 0)
370 continue;
371
372 /* if mixing this channel, we cannot just rearrange */
373 if (vol != 0x10000 || arrange[oc] >= 0)
374 return false;
375
376 arrange[oc] = ic;
377 count_output++;
378 }
379 }
380
381 return count_output > 0;
382 }
383
remap_arrange_mono_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)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;
387
388 src += arrange[0];
389 for (; n > 0; n--) {
390 *dst++ = *src;
391 src += n_ic;
392 }
393 }
394
remap_arrange_stereo_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)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];
399
400 for (; n > 0; n--) {
401 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
402 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
403 src += n_ic;
404 }
405 }
406
remap_arrange_ch4_s16ne_c(pa_remap_t * m,int16_t * dst,const int16_t * src,unsigned n)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];
412
413 for (; n > 0; n--) {
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;
418 src += n_ic;
419 }
420 }
421
remap_arrange_mono_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)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;
425
426 src += arrange[0];
427 for (; n > 0; n--) {
428 *dst++ = *src;
429 src += n_ic;
430 }
431 }
432
remap_arrange_stereo_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)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];
437
438 for (; n > 0; n--) {
439 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0;
440 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0;
441 src += n_ic;
442 }
443 }
444
remap_arrange_ch4_s32ne_c(pa_remap_t * m,int32_t * dst,const int32_t * src,unsigned n)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];
450
451 for (; n > 0; n--) {
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;
456 src += n_ic;
457 }
458 }
459
remap_arrange_mono_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)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;
463
464 src += arrange[0];
465 for (; n > 0; n--) {
466 *dst++ = *src;
467 src += n_ic;
468 }
469 }
470
remap_arrange_stereo_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)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];
475
476 for (; n > 0; n--) {
477 *dst++ = (ic0 >= 0) ? *(src + ic0) : 0.0f;
478 *dst++ = (ic1 >= 0) ? *(src + ic1) : 0.0f;
479 src += n_ic;
480 }
481 }
482
remap_arrange_ch4_float32ne_c(pa_remap_t * m,float * dst,const float * src,unsigned n)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];
488
489 for (; n > 0; n--) {
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;
494 src += n_ic;
495 }
496 }
497
pa_set_remap_func(pa_remap_t * m,pa_do_remap_func_t func_s16,pa_do_remap_func_t func_s32,pa_do_remap_func_t func_float)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) {
500
501 pa_assert(m);
502
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;
509 else
510 pa_assert_not_reached();
511 pa_assert(m->do_remap);
512 }
513
514 static bool force_generic_code = false;
515
516 /* set the function that will execute the remapping based on the matrices */
init_remap_c(pa_remap_t * m)517 static void init_remap_c(pa_remap_t *m) {
518 unsigned n_oc, n_ic;
519 int8_t arrange[PA_CHANNELS_MAX];
520
521 n_oc = m->o_ss.channels;
522 n_ic = m->i_ss.channels;
523
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);
530 return;
531 }
532
533 if (n_ic == 1 && n_oc == 2 &&
534 m->map_table_i[0][0] == 0x10000 && m->map_table_i[1][0] == 0x10000) {
535
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) {
542
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) {
550
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) {
558
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) {
564
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);
569
570 /* setup state */
571 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
572 } else if (pa_setup_remap_arrange(m, arrange) && n_oc == 2) {
573
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);
578
579 /* setup state */
580 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
581 } else if (pa_setup_remap_arrange(m, arrange) && n_oc == 4) {
582
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);
587
588 /* setup state */
589 m->state = pa_xnewdup(int8_t, arrange, PA_CHANNELS_MAX);
590 } else {
591
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);
596 }
597 }
598
599 /* default C implementation */
600 static pa_init_remap_func_t init_remap_func = init_remap_c;
601
pa_init_remap_func(pa_remap_t * m)602 void pa_init_remap_func(pa_remap_t *m) {
603 pa_assert(init_remap_func);
604
605 m->do_remap = NULL;
606
607 /* call the installed remap init function */
608 init_remap_func(m);
609
610 if (m->do_remap == NULL) {
611 /* nothing was installed, fallback to C version */
612 init_remap_c(m);
613 }
614 }
615
pa_get_init_remap_func(void)616 pa_init_remap_func_t pa_get_init_remap_func(void) {
617 return init_remap_func;
618 }
619
pa_set_init_remap_func(pa_init_remap_func_t func)620 void pa_set_init_remap_func(pa_init_remap_func_t func) {
621 init_remap_func = func;
622 }
623
pa_remap_func_init(const pa_cpu_info * cpu_info)624 void pa_remap_func_init(const pa_cpu_info *cpu_info) {
625 force_generic_code = cpu_info->force_generic_code;
626 }
627