• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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