Branch data Line data Source code
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, 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 <string.h>
28 : :
29 : : #include <pulse/sample.h>
30 : : #include <pulsecore/log.h>
31 : : #include <pulsecore/macro.h>
32 : :
33 : : #include "remap.h"
34 : :
35 : 0 : static void remap_mono_to_stereo_c(pa_remap_t *m, void *dst, const void *src, unsigned n) {
36 : : unsigned i;
37 : :
38 [ # # # ]: 0 : switch (*m->format) {
39 : : case PA_SAMPLE_FLOAT32NE:
40 : : {
41 : : float *d, *s;
42 : :
43 : 0 : d = (float *) dst;
44 : 0 : s = (float *) src;
45 : :
46 [ # # ]: 0 : for (i = n >> 2; i; i--) {
47 : 0 : d[0] = d[1] = s[0];
48 : 0 : d[2] = d[3] = s[1];
49 : 0 : d[4] = d[5] = s[2];
50 : 0 : d[6] = d[7] = s[3];
51 : 0 : s += 4;
52 : 0 : d += 8;
53 : : }
54 [ # # ]: 0 : for (i = n & 3; i; i--) {
55 : 0 : d[0] = d[1] = s[0];
56 : 0 : s++;
57 : 0 : d += 2;
58 : : }
59 : : break;
60 : : }
61 : : case PA_SAMPLE_S16NE:
62 : : {
63 : : int16_t *d, *s;
64 : :
65 : 0 : d = (int16_t *) dst;
66 : 0 : s = (int16_t *) src;
67 : :
68 [ # # ]: 0 : for (i = n >> 2; i; i--) {
69 : 0 : d[0] = d[1] = s[0];
70 : 0 : d[2] = d[3] = s[1];
71 : 0 : d[4] = d[5] = s[2];
72 : 0 : d[6] = d[7] = s[3];
73 : 0 : s += 4;
74 : 0 : d += 8;
75 : : }
76 [ # # ]: 0 : for (i = n & 3; i; i--) {
77 : 0 : d[0] = d[1] = s[0];
78 : 0 : s++;
79 : 0 : d += 2;
80 : : }
81 : : break;
82 : : }
83 : : default:
84 : 0 : pa_assert_not_reached();
85 : : }
86 : 0 : }
87 : :
88 : 0 : static void remap_channels_matrix_c(pa_remap_t *m, void *dst, const void *src, unsigned n) {
89 : : unsigned oc, ic, i;
90 : : unsigned n_ic, n_oc;
91 : :
92 : 0 : n_ic = m->i_ss->channels;
93 : 0 : n_oc = m->o_ss->channels;
94 : :
95 [ # # # ]: 0 : switch (*m->format) {
96 : : case PA_SAMPLE_FLOAT32NE:
97 : : {
98 : : float *d, *s;
99 : :
100 : 0 : memset(dst, 0, n * sizeof(float) * n_oc);
101 : :
102 [ # # ]: 0 : for (oc = 0; oc < n_oc; oc++) {
103 : :
104 [ # # ]: 0 : for (ic = 0; ic < n_ic; ic++) {
105 : : float vol;
106 : :
107 : 0 : vol = m->map_table_f[oc][ic];
108 : :
109 [ # # ]: 0 : if (vol <= 0.0)
110 : 0 : continue;
111 : :
112 : 0 : d = (float *)dst + oc;
113 : 0 : s = (float *)src + ic;
114 : :
115 [ # # ]: 0 : if (vol >= 1.0) {
116 [ # # ]: 0 : for (i = n; i > 0; i--, s += n_ic, d += n_oc)
117 : 0 : *d += *s;
118 : : } else {
119 [ # # ]: 0 : for (i = n; i > 0; i--, s += n_ic, d += n_oc)
120 : 0 : *d += *s * vol;
121 : : }
122 : : }
123 : : }
124 : :
125 : : break;
126 : : }
127 : : case PA_SAMPLE_S16NE:
128 : : {
129 : : int16_t *d, *s;
130 : :
131 : 0 : memset(dst, 0, n * sizeof(int16_t) * n_oc);
132 : :
133 [ # # ]: 0 : for (oc = 0; oc < n_oc; oc++) {
134 : :
135 [ # # ]: 0 : for (ic = 0; ic < n_ic; ic++) {
136 : : int32_t vol;
137 : :
138 : 0 : vol = m->map_table_i[oc][ic];
139 : :
140 [ # # ]: 0 : if (vol <= 0)
141 : 0 : continue;
142 : :
143 : 0 : d = (int16_t *)dst + oc;
144 : 0 : s = (int16_t *)src + ic;
145 : :
146 [ # # ]: 0 : if (vol >= 0x10000) {
147 [ # # ]: 0 : for (i = n; i > 0; i--, s += n_ic, d += n_oc)
148 : 0 : *d += *s;
149 : : } else {
150 [ # # ]: 0 : for (i = n; i > 0; i--, s += n_ic, d += n_oc)
151 : 0 : *d += (int16_t) (((int32_t)*s * vol) >> 16);
152 : : }
153 : : }
154 : : }
155 : : break;
156 : : }
157 : : default:
158 : 0 : pa_assert_not_reached();
159 : : }
160 : 0 : }
161 : :
162 : : /* set the function that will execute the remapping based on the matrices */
163 : 0 : static void init_remap_c(pa_remap_t *m) {
164 : : unsigned n_oc, n_ic;
165 : :
166 : 0 : n_oc = m->o_ss->channels;
167 : 0 : n_ic = m->i_ss->channels;
168 : :
169 : : /* find some common channel remappings, fall back to full matrix operation. */
170 [ # # ][ # # ]: 0 : if (n_ic == 1 && n_oc == 2 &&
171 [ # # ]: 0 : m->map_table_f[0][0] >= 1.0 && m->map_table_f[1][0] >= 1.0) {
172 : 0 : m->do_remap = (pa_do_remap_func_t) remap_mono_to_stereo_c;
173 : 0 : pa_log_info("Using mono to stereo remapping");
174 : : } else {
175 : 0 : m->do_remap = (pa_do_remap_func_t) remap_channels_matrix_c;
176 : 0 : pa_log_info("Using generic matrix remapping");
177 : : }
178 : 0 : }
179 : :
180 : :
181 : : /* default C implementation */
182 : : static pa_init_remap_func_t remap_func = init_remap_c;
183 : :
184 : 0 : void pa_init_remap(pa_remap_t *m) {
185 [ # # ]: 0 : pa_assert(remap_func);
186 : :
187 : 0 : m->do_remap = NULL;
188 : :
189 : : /* call the installed remap init function */
190 : 0 : remap_func(m);
191 : :
192 [ # # ]: 0 : if (m->do_remap == NULL) {
193 : : /* nothing was installed, fallback to C version */
194 : 0 : init_remap_c(m);
195 : : }
196 : 0 : }
197 : :
198 : 0 : pa_init_remap_func_t pa_get_init_remap_func(void) {
199 : 0 : return remap_func;
200 : : }
201 : :
202 : 0 : void pa_set_init_remap_func(pa_init_remap_func_t func) {
203 : 0 : remap_func = func;
204 : 0 : }
|