blob: 03b9b20900e2a9a6a0a11780229eeca7ca882bdb
1 | /* |
2 | * Copyright (C) 2011-2012 Michael Niedermayer (michaelni@gmx.at) |
3 | * |
4 | * This file is part of libswresample |
5 | * |
6 | * libswresample is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU Lesser General Public |
8 | * License as published by the Free Software Foundation; either |
9 | * version 2.1 of the License, or (at your option) any later version. |
10 | * |
11 | * libswresample is distributed in the hope that it will be useful, |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | * Lesser General Public License for more details. |
15 | * |
16 | * You should have received a copy of the GNU Lesser General Public |
17 | * License along with libswresample; if not, write to the Free Software |
18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | */ |
20 | |
21 | #include "swresample_internal.h" |
22 | #include "libavutil/avassert.h" |
23 | #include "libavutil/channel_layout.h" |
24 | |
25 | #define TEMPLATE_REMATRIX_FLT |
26 | #include "rematrix_template.c" |
27 | #undef TEMPLATE_REMATRIX_FLT |
28 | |
29 | #define TEMPLATE_REMATRIX_DBL |
30 | #include "rematrix_template.c" |
31 | #undef TEMPLATE_REMATRIX_DBL |
32 | |
33 | #define TEMPLATE_REMATRIX_S16 |
34 | #include "rematrix_template.c" |
35 | #define TEMPLATE_CLIP |
36 | #include "rematrix_template.c" |
37 | #undef TEMPLATE_CLIP |
38 | #undef TEMPLATE_REMATRIX_S16 |
39 | |
40 | #define TEMPLATE_REMATRIX_S32 |
41 | #include "rematrix_template.c" |
42 | #undef TEMPLATE_REMATRIX_S32 |
43 | |
44 | #define FRONT_LEFT 0 |
45 | #define FRONT_RIGHT 1 |
46 | #define FRONT_CENTER 2 |
47 | #define LOW_FREQUENCY 3 |
48 | #define BACK_LEFT 4 |
49 | #define BACK_RIGHT 5 |
50 | #define FRONT_LEFT_OF_CENTER 6 |
51 | #define FRONT_RIGHT_OF_CENTER 7 |
52 | #define BACK_CENTER 8 |
53 | #define SIDE_LEFT 9 |
54 | #define SIDE_RIGHT 10 |
55 | #define TOP_CENTER 11 |
56 | #define TOP_FRONT_LEFT 12 |
57 | #define TOP_FRONT_CENTER 13 |
58 | #define TOP_FRONT_RIGHT 14 |
59 | #define TOP_BACK_LEFT 15 |
60 | #define TOP_BACK_CENTER 16 |
61 | #define TOP_BACK_RIGHT 17 |
62 | #define NUM_NAMED_CHANNELS 18 |
63 | |
64 | int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride) |
65 | { |
66 | int nb_in, nb_out, in, out; |
67 | |
68 | if (!s || s->in_convert) // s needs to be allocated but not initialized |
69 | return AVERROR(EINVAL); |
70 | memset(s->matrix, 0, sizeof(s->matrix)); |
71 | memset(s->matrix_flt, 0, sizeof(s->matrix_flt)); |
72 | nb_in = av_get_channel_layout_nb_channels(s->user_in_ch_layout); |
73 | nb_out = av_get_channel_layout_nb_channels(s->user_out_ch_layout); |
74 | for (out = 0; out < nb_out; out++) { |
75 | for (in = 0; in < nb_in; in++) |
76 | s->matrix_flt[out][in] = s->matrix[out][in] = matrix[in]; |
77 | matrix += stride; |
78 | } |
79 | s->rematrix_custom = 1; |
80 | return 0; |
81 | } |
82 | |
83 | static int even(int64_t layout){ |
84 | if(!layout) return 1; |
85 | if(layout&(layout-1)) return 1; |
86 | return 0; |
87 | } |
88 | |
89 | static int clean_layout(void *s, int64_t layout){ |
90 | if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) { |
91 | char buf[128]; |
92 | av_get_channel_layout_string(buf, sizeof(buf), -1, layout); |
93 | av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf); |
94 | return AV_CH_FRONT_CENTER; |
95 | } |
96 | |
97 | return layout; |
98 | } |
99 | |
100 | static int sane_layout(int64_t layout){ |
101 | if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker |
102 | return 0; |
103 | if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front |
104 | return 0; |
105 | if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT))) // no asymetric side |
106 | return 0; |
107 | if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT))) |
108 | return 0; |
109 | if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER))) |
110 | return 0; |
111 | if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX) |
112 | return 0; |
113 | |
114 | return 1; |
115 | } |
116 | |
117 | av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param, |
118 | double center_mix_level, double surround_mix_level, |
119 | double lfe_mix_level, double maxval, |
120 | double rematrix_volume, double *matrix_param, |
121 | int stride, enum AVMatrixEncoding matrix_encoding, void *log_context) |
122 | { |
123 | int i, j, out_i; |
124 | double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; |
125 | int64_t unaccounted, in_ch_layout, out_ch_layout; |
126 | double maxcoef=0; |
127 | char buf[128]; |
128 | |
129 | in_ch_layout = clean_layout(log_context, in_ch_layout_param); |
130 | out_ch_layout = clean_layout(log_context, out_ch_layout_param); |
131 | |
132 | if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX |
133 | && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 |
134 | ) |
135 | out_ch_layout = AV_CH_LAYOUT_STEREO; |
136 | |
137 | if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX |
138 | && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 |
139 | ) |
140 | in_ch_layout = AV_CH_LAYOUT_STEREO; |
141 | |
142 | if(!sane_layout(in_ch_layout)){ |
143 | av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param); |
144 | av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); |
145 | return AVERROR(EINVAL); |
146 | } |
147 | |
148 | if(!sane_layout(out_ch_layout)){ |
149 | av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param); |
150 | av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); |
151 | return AVERROR(EINVAL); |
152 | } |
153 | |
154 | for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){ |
155 | if(in_ch_layout & out_ch_layout & (1ULL<<i)) |
156 | matrix[i][i]= 1.0; |
157 | } |
158 | |
159 | unaccounted= in_ch_layout & ~out_ch_layout; |
160 | |
161 | //FIXME implement dolby surround |
162 | //FIXME implement full ac3 |
163 | |
164 | |
165 | if(unaccounted & AV_CH_FRONT_CENTER){ |
166 | if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ |
167 | if(in_ch_layout & AV_CH_LAYOUT_STEREO) { |
168 | matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level; |
169 | matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level; |
170 | } else { |
171 | matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; |
172 | matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; |
173 | } |
174 | }else |
175 | av_assert0(0); |
176 | } |
177 | if(unaccounted & AV_CH_LAYOUT_STEREO){ |
178 | if(out_ch_layout & AV_CH_FRONT_CENTER){ |
179 | matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; |
180 | matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; |
181 | if(in_ch_layout & AV_CH_FRONT_CENTER) |
182 | matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2); |
183 | }else |
184 | av_assert0(0); |
185 | } |
186 | |
187 | if(unaccounted & AV_CH_BACK_CENTER){ |
188 | if(out_ch_layout & AV_CH_BACK_LEFT){ |
189 | matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; |
190 | matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; |
191 | }else if(out_ch_layout & AV_CH_SIDE_LEFT){ |
192 | matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; |
193 | matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; |
194 | }else if(out_ch_layout & AV_CH_FRONT_LEFT){ |
195 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || |
196 | matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
197 | if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { |
198 | matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2; |
199 | matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2; |
200 | } else { |
201 | matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level; |
202 | matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level; |
203 | } |
204 | } else { |
205 | matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
206 | matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
207 | } |
208 | }else if(out_ch_layout & AV_CH_FRONT_CENTER){ |
209 | matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; |
210 | }else |
211 | av_assert0(0); |
212 | } |
213 | if(unaccounted & AV_CH_BACK_LEFT){ |
214 | if(out_ch_layout & AV_CH_BACK_CENTER){ |
215 | matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; |
216 | matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; |
217 | }else if(out_ch_layout & AV_CH_SIDE_LEFT){ |
218 | if(in_ch_layout & AV_CH_SIDE_LEFT){ |
219 | matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; |
220 | matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; |
221 | }else{ |
222 | matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; |
223 | matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; |
224 | } |
225 | }else if(out_ch_layout & AV_CH_FRONT_LEFT){ |
226 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { |
227 | matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2; |
228 | matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; |
229 | matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; |
230 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2; |
231 | } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
232 | matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2; |
233 | matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; |
234 | matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; |
235 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2; |
236 | } else { |
237 | matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level; |
238 | matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level; |
239 | } |
240 | }else if(out_ch_layout & AV_CH_FRONT_CENTER){ |
241 | matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2; |
242 | matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2; |
243 | }else |
244 | av_assert0(0); |
245 | } |
246 | |
247 | if(unaccounted & AV_CH_SIDE_LEFT){ |
248 | if(out_ch_layout & AV_CH_BACK_LEFT){ |
249 | /* if back channels do not exist in the input, just copy side |
250 | channels to back channels, otherwise mix side into back */ |
251 | if (in_ch_layout & AV_CH_BACK_LEFT) { |
252 | matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; |
253 | matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; |
254 | } else { |
255 | matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; |
256 | matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; |
257 | } |
258 | }else if(out_ch_layout & AV_CH_BACK_CENTER){ |
259 | matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; |
260 | matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; |
261 | }else if(out_ch_layout & AV_CH_FRONT_LEFT){ |
262 | if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { |
263 | matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2; |
264 | matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; |
265 | matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; |
266 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2; |
267 | } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { |
268 | matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2; |
269 | matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; |
270 | matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; |
271 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2; |
272 | } else { |
273 | matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level; |
274 | matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level; |
275 | } |
276 | }else if(out_ch_layout & AV_CH_FRONT_CENTER){ |
277 | matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2; |
278 | matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2; |
279 | }else |
280 | av_assert0(0); |
281 | } |
282 | |
283 | if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ |
284 | if(out_ch_layout & AV_CH_FRONT_LEFT){ |
285 | matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; |
286 | matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; |
287 | }else if(out_ch_layout & AV_CH_FRONT_CENTER){ |
288 | matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; |
289 | matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; |
290 | }else |
291 | av_assert0(0); |
292 | } |
293 | /* mix LFE into front left/right or center */ |
294 | if (unaccounted & AV_CH_LOW_FREQUENCY) { |
295 | if (out_ch_layout & AV_CH_FRONT_CENTER) { |
296 | matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level; |
297 | } else if (out_ch_layout & AV_CH_FRONT_LEFT) { |
298 | matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; |
299 | matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; |
300 | } else |
301 | av_assert0(0); |
302 | } |
303 | |
304 | for(out_i=i=0; i<64; i++){ |
305 | double sum=0; |
306 | int in_i=0; |
307 | if((out_ch_layout & (1ULL<<i)) == 0) |
308 | continue; |
309 | for(j=0; j<64; j++){ |
310 | if((in_ch_layout & (1ULL<<j)) == 0) |
311 | continue; |
312 | if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) |
313 | matrix_param[stride*out_i + in_i] = matrix[i][j]; |
314 | else |
315 | matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i)); |
316 | sum += fabs(matrix_param[stride*out_i + in_i]); |
317 | in_i++; |
318 | } |
319 | maxcoef= FFMAX(maxcoef, sum); |
320 | out_i++; |
321 | } |
322 | if(rematrix_volume < 0) |
323 | maxcoef = -rematrix_volume; |
324 | |
325 | if(maxcoef > maxval || rematrix_volume < 0){ |
326 | maxcoef /= maxval; |
327 | for(i=0; i<SWR_CH_MAX; i++) |
328 | for(j=0; j<SWR_CH_MAX; j++){ |
329 | matrix_param[stride*i + j] /= maxcoef; |
330 | } |
331 | } |
332 | |
333 | if(rematrix_volume > 0){ |
334 | for(i=0; i<SWR_CH_MAX; i++) |
335 | for(j=0; j<SWR_CH_MAX; j++){ |
336 | matrix_param[stride*i + j] *= rematrix_volume; |
337 | } |
338 | } |
339 | |
340 | av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n"); |
341 | for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){ |
342 | const char *c = |
343 | av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i)); |
344 | av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?"); |
345 | for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){ |
346 | c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j)); |
347 | av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]); |
348 | } |
349 | av_log(log_context, AV_LOG_DEBUG, "\n"); |
350 | } |
351 | return 0; |
352 | } |
353 | |
354 | av_cold static int auto_matrix(SwrContext *s) |
355 | { |
356 | double maxval; |
357 | int ret; |
358 | |
359 | if (s->rematrix_maxval > 0) { |
360 | maxval = s->rematrix_maxval; |
361 | } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT |
362 | || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) { |
363 | maxval = 1.0; |
364 | } else |
365 | maxval = INT_MAX; |
366 | |
367 | memset(s->matrix, 0, sizeof(s->matrix)); |
368 | ret = swr_build_matrix(s->in_ch_layout, s->out_ch_layout, |
369 | s->clev, s->slev, s->lfe_mix_level, |
370 | maxval, s->rematrix_volume, (double*)s->matrix, |
371 | s->matrix[1] - s->matrix[0], s->matrix_encoding, s); |
372 | |
373 | if (ret >= 0 && s->int_sample_fmt == AV_SAMPLE_FMT_FLTP) { |
374 | int i, j; |
375 | for (i = 0; i < FF_ARRAY_ELEMS(s->matrix[0]); i++) |
376 | for (j = 0; j < FF_ARRAY_ELEMS(s->matrix[0]); j++) |
377 | s->matrix_flt[i][j] = s->matrix[i][j]; |
378 | } |
379 | |
380 | return ret; |
381 | } |
382 | |
383 | av_cold int swri_rematrix_init(SwrContext *s){ |
384 | int i, j; |
385 | int nb_in = av_get_channel_layout_nb_channels(s->in_ch_layout); |
386 | int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout); |
387 | |
388 | s->mix_any_f = NULL; |
389 | |
390 | if (!s->rematrix_custom) { |
391 | int r = auto_matrix(s); |
392 | if (r) |
393 | return r; |
394 | } |
395 | if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){ |
396 | int maxsum = 0; |
397 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int)); |
398 | s->native_one = av_mallocz(sizeof(int)); |
399 | if (!s->native_matrix || !s->native_one) |
400 | return AVERROR(ENOMEM); |
401 | for (i = 0; i < nb_out; i++) { |
402 | double rem = 0; |
403 | int sum = 0; |
404 | |
405 | for (j = 0; j < nb_in; j++) { |
406 | double target = s->matrix[i][j] * 32768 + rem; |
407 | ((int*)s->native_matrix)[i * nb_in + j] = lrintf(target); |
408 | rem += target - ((int*)s->native_matrix)[i * nb_in + j]; |
409 | sum += FFABS(((int*)s->native_matrix)[i * nb_in + j]); |
410 | } |
411 | maxsum = FFMAX(maxsum, sum); |
412 | } |
413 | *((int*)s->native_one) = 32768; |
414 | if (maxsum <= 32768) { |
415 | s->mix_1_1_f = (mix_1_1_func_type*)copy_s16; |
416 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16; |
417 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s); |
418 | } else { |
419 | s->mix_1_1_f = (mix_1_1_func_type*)copy_clip_s16; |
420 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_clip_s16; |
421 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_clip_s16(s); |
422 | } |
423 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){ |
424 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float)); |
425 | s->native_one = av_mallocz(sizeof(float)); |
426 | if (!s->native_matrix || !s->native_one) |
427 | return AVERROR(ENOMEM); |
428 | for (i = 0; i < nb_out; i++) |
429 | for (j = 0; j < nb_in; j++) |
430 | ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; |
431 | *((float*)s->native_one) = 1.0; |
432 | s->mix_1_1_f = (mix_1_1_func_type*)copy_float; |
433 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_float; |
434 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s); |
435 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){ |
436 | s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double)); |
437 | s->native_one = av_mallocz(sizeof(double)); |
438 | if (!s->native_matrix || !s->native_one) |
439 | return AVERROR(ENOMEM); |
440 | for (i = 0; i < nb_out; i++) |
441 | for (j = 0; j < nb_in; j++) |
442 | ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; |
443 | *((double*)s->native_one) = 1.0; |
444 | s->mix_1_1_f = (mix_1_1_func_type*)copy_double; |
445 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_double; |
446 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s); |
447 | }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){ |
448 | // Only for dithering currently |
449 | // s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double)); |
450 | s->native_one = av_mallocz(sizeof(int)); |
451 | if (!s->native_one) |
452 | return AVERROR(ENOMEM); |
453 | // for (i = 0; i < nb_out; i++) |
454 | // for (j = 0; j < nb_in; j++) |
455 | // ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j]; |
456 | *((int*)s->native_one) = 32768; |
457 | s->mix_1_1_f = (mix_1_1_func_type*)copy_s32; |
458 | s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32; |
459 | s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s); |
460 | }else |
461 | av_assert0(0); |
462 | //FIXME quantize for integeres |
463 | for (i = 0; i < SWR_CH_MAX; i++) { |
464 | int ch_in=0; |
465 | for (j = 0; j < SWR_CH_MAX; j++) { |
466 | s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768); |
467 | if(s->matrix[i][j]) |
468 | s->matrix_ch[i][++ch_in]= j; |
469 | } |
470 | s->matrix_ch[i][0]= ch_in; |
471 | } |
472 | |
473 | if(HAVE_YASM && HAVE_MMX) |
474 | return swri_rematrix_init_x86(s); |
475 | |
476 | return 0; |
477 | } |
478 | |
479 | av_cold void swri_rematrix_free(SwrContext *s){ |
480 | av_freep(&s->native_matrix); |
481 | av_freep(&s->native_one); |
482 | av_freep(&s->native_simd_matrix); |
483 | av_freep(&s->native_simd_one); |
484 | } |
485 | |
486 | int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){ |
487 | int out_i, in_i, i, j; |
488 | int len1 = 0; |
489 | int off = 0; |
490 | |
491 | if(s->mix_any_f) { |
492 | s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len); |
493 | return 0; |
494 | } |
495 | |
496 | if(s->mix_2_1_simd || s->mix_1_1_simd){ |
497 | len1= len&~15; |
498 | off = len1 * out->bps; |
499 | } |
500 | |
501 | av_assert0(!s->out_ch_layout || out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout)); |
502 | av_assert0(!s-> in_ch_layout || in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout)); |
503 | |
504 | for(out_i=0; out_i<out->ch_count; out_i++){ |
505 | switch(s->matrix_ch[out_i][0]){ |
506 | case 0: |
507 | if(mustcopy) |
508 | memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt)); |
509 | break; |
510 | case 1: |
511 | in_i= s->matrix_ch[out_i][1]; |
512 | if(s->matrix[out_i][in_i]!=1.0){ |
513 | if(s->mix_1_1_simd && len1) |
514 | s->mix_1_1_simd(out->ch[out_i] , in->ch[in_i] , s->native_simd_matrix, in->ch_count*out_i + in_i, len1); |
515 | if(len != len1) |
516 | s->mix_1_1_f (out->ch[out_i]+off, in->ch[in_i]+off, s->native_matrix, in->ch_count*out_i + in_i, len-len1); |
517 | }else if(mustcopy){ |
518 | memcpy(out->ch[out_i], in->ch[in_i], len*out->bps); |
519 | }else{ |
520 | out->ch[out_i]= in->ch[in_i]; |
521 | } |
522 | break; |
523 | case 2: { |
524 | int in_i1 = s->matrix_ch[out_i][1]; |
525 | int in_i2 = s->matrix_ch[out_i][2]; |
526 | if(s->mix_2_1_simd && len1) |
527 | s->mix_2_1_simd(out->ch[out_i] , in->ch[in_i1] , in->ch[in_i2] , s->native_simd_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1); |
528 | else |
529 | s->mix_2_1_f (out->ch[out_i] , in->ch[in_i1] , in->ch[in_i2] , s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len1); |
530 | if(len != len1) |
531 | s->mix_2_1_f (out->ch[out_i]+off, in->ch[in_i1]+off, in->ch[in_i2]+off, s->native_matrix, in->ch_count*out_i + in_i1, in->ch_count*out_i + in_i2, len-len1); |
532 | break;} |
533 | default: |
534 | if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){ |
535 | for(i=0; i<len; i++){ |
536 | float v=0; |
537 | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
538 | in_i= s->matrix_ch[out_i][1+j]; |
539 | v+= ((float*)in->ch[in_i])[i] * s->matrix_flt[out_i][in_i]; |
540 | } |
541 | ((float*)out->ch[out_i])[i]= v; |
542 | } |
543 | }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){ |
544 | for(i=0; i<len; i++){ |
545 | double v=0; |
546 | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
547 | in_i= s->matrix_ch[out_i][1+j]; |
548 | v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i]; |
549 | } |
550 | ((double*)out->ch[out_i])[i]= v; |
551 | } |
552 | }else{ |
553 | for(i=0; i<len; i++){ |
554 | int v=0; |
555 | for(j=0; j<s->matrix_ch[out_i][0]; j++){ |
556 | in_i= s->matrix_ch[out_i][1+j]; |
557 | v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i]; |
558 | } |
559 | ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15; |
560 | } |
561 | } |
562 | } |
563 | } |
564 | return 0; |
565 | } |
566 |