2 * Copyright (C) 2011-2012 Michael Niedermayer (michaelni@gmx.at)
4 * This file is part of libswresample
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.
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.
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
21 #include "swresample_internal.h"
22 #include "libavutil/avassert.h"
23 #include "libavutil/channel_layout.h"
25 #define TEMPLATE_REMATRIX_FLT
26 #include "rematrix_template.c"
27 #undef TEMPLATE_REMATRIX_FLT
29 #define TEMPLATE_REMATRIX_DBL
30 #include "rematrix_template.c"
31 #undef TEMPLATE_REMATRIX_DBL
33 #define TEMPLATE_REMATRIX_S16
34 #include "rematrix_template.c"
35 #undef TEMPLATE_REMATRIX_S16
37 #define TEMPLATE_REMATRIX_S32
38 #include "rematrix_template.c"
39 #undef TEMPLATE_REMATRIX_S32
43 #define FRONT_CENTER 2
44 #define LOW_FREQUENCY 3
47 #define FRONT_LEFT_OF_CENTER 6
48 #define FRONT_RIGHT_OF_CENTER 7
53 #define TOP_FRONT_LEFT 12
54 #define TOP_FRONT_CENTER 13
55 #define TOP_FRONT_RIGHT 14
56 #define TOP_BACK_LEFT 15
57 #define TOP_BACK_CENTER 16
58 #define TOP_BACK_RIGHT 17
59 #define NUM_NAMED_CHANNELS 18
61 int swr_set_matrix(struct SwrContext
*s
, const double *matrix
, int stride
)
63 int nb_in
, nb_out
, in
, out
;
65 if (!s
|| s
->in_convert
) // s needs to be allocated but not initialized
66 return AVERROR(EINVAL
);
67 memset(s
->matrix
, 0, sizeof(s
->matrix
));
68 nb_in
= av_get_channel_layout_nb_channels(s
->in_ch_layout
);
69 nb_out
= av_get_channel_layout_nb_channels(s
->out_ch_layout
);
70 for (out
= 0; out
< nb_out
; out
++) {
71 for (in
= 0; in
< nb_in
; in
++)
72 s
->matrix
[out
][in
] = matrix
[in
];
75 s
->rematrix_custom
= 1;
79 static int even(int64_t layout
){
81 if(layout
&(layout
-1)) return 1;
85 static int clean_layout(SwrContext
*s
, int64_t layout
){
86 if(layout
&& layout
!= AV_CH_FRONT_CENTER
&& !(layout
&(layout
-1))) {
88 av_get_channel_layout_string(buf
, sizeof(buf
), -1, layout
);
89 av_log(s
, AV_LOG_VERBOSE
, "Treating %s as mono\n", buf
);
90 return AV_CH_FRONT_CENTER
;
96 static int sane_layout(int64_t layout
){
97 if(!(layout
& AV_CH_LAYOUT_SURROUND
)) // at least 1 front speaker
99 if(!even(layout
& (AV_CH_FRONT_LEFT
| AV_CH_FRONT_RIGHT
))) // no asymetric front
101 if(!even(layout
& (AV_CH_SIDE_LEFT
| AV_CH_SIDE_RIGHT
))) // no asymetric side
103 if(!even(layout
& (AV_CH_BACK_LEFT
| AV_CH_BACK_RIGHT
)))
105 if(!even(layout
& (AV_CH_FRONT_LEFT_OF_CENTER
| AV_CH_FRONT_RIGHT_OF_CENTER
)))
107 if(av_get_channel_layout_nb_channels(layout
) >= SWR_CH_MAX
)
113 av_cold
static int auto_matrix(SwrContext
*s
)
116 double matrix
[NUM_NAMED_CHANNELS
][NUM_NAMED_CHANNELS
]={{0}};
117 int64_t unaccounted
, in_ch_layout
, out_ch_layout
;
120 const int matrix_encoding
= s
->matrix_encoding
;
123 in_ch_layout
= clean_layout(s
, s
->in_ch_layout
);
124 out_ch_layout
= clean_layout(s
, s
->out_ch_layout
);
126 if( out_ch_layout
== AV_CH_LAYOUT_STEREO_DOWNMIX
127 && (in_ch_layout
& AV_CH_LAYOUT_STEREO_DOWNMIX
) == 0
129 out_ch_layout
= AV_CH_LAYOUT_STEREO
;
131 if( in_ch_layout
== AV_CH_LAYOUT_STEREO_DOWNMIX
132 && (out_ch_layout
& AV_CH_LAYOUT_STEREO_DOWNMIX
) == 0
134 in_ch_layout
= AV_CH_LAYOUT_STEREO
;
136 if(!sane_layout(in_ch_layout
)){
137 av_get_channel_layout_string(buf
, sizeof(buf
), -1, s
->in_ch_layout
);
138 av_log(s
, AV_LOG_ERROR
, "Input channel layout '%s' is not supported\n", buf
);
139 return AVERROR(EINVAL
);
142 if(!sane_layout(out_ch_layout
)){
143 av_get_channel_layout_string(buf
, sizeof(buf
), -1, s
->out_ch_layout
);
144 av_log(s
, AV_LOG_ERROR
, "Output channel layout '%s' is not supported\n", buf
);
145 return AVERROR(EINVAL
);
148 memset(s
->matrix
, 0, sizeof(s
->matrix
));
149 for(i
=0; i
<FF_ARRAY_ELEMS(matrix
); i
++){
150 if(in_ch_layout
& out_ch_layout
& (1ULL<<i
))
154 unaccounted
= in_ch_layout
& ~out_ch_layout
;
156 //FIXME implement dolby surround
157 //FIXME implement full ac3
160 if(unaccounted
& AV_CH_FRONT_CENTER
){
161 if((out_ch_layout
& AV_CH_LAYOUT_STEREO
) == AV_CH_LAYOUT_STEREO
){
162 if(in_ch_layout
& AV_CH_LAYOUT_STEREO
) {
163 matrix
[ FRONT_LEFT
][FRONT_CENTER
]+= s
->clev
;
164 matrix
[FRONT_RIGHT
][FRONT_CENTER
]+= s
->clev
;
166 matrix
[ FRONT_LEFT
][FRONT_CENTER
]+= M_SQRT1_2
;
167 matrix
[FRONT_RIGHT
][FRONT_CENTER
]+= M_SQRT1_2
;
172 if(unaccounted
& AV_CH_LAYOUT_STEREO
){
173 if(out_ch_layout
& AV_CH_FRONT_CENTER
){
174 matrix
[FRONT_CENTER
][ FRONT_LEFT
]+= M_SQRT1_2
;
175 matrix
[FRONT_CENTER
][FRONT_RIGHT
]+= M_SQRT1_2
;
176 if(in_ch_layout
& AV_CH_FRONT_CENTER
)
177 matrix
[FRONT_CENTER
][ FRONT_CENTER
] = s
->clev
*sqrt(2);
182 if(unaccounted
& AV_CH_BACK_CENTER
){
183 if(out_ch_layout
& AV_CH_BACK_LEFT
){
184 matrix
[ BACK_LEFT
][BACK_CENTER
]+= M_SQRT1_2
;
185 matrix
[BACK_RIGHT
][BACK_CENTER
]+= M_SQRT1_2
;
186 }else if(out_ch_layout
& AV_CH_SIDE_LEFT
){
187 matrix
[ SIDE_LEFT
][BACK_CENTER
]+= M_SQRT1_2
;
188 matrix
[SIDE_RIGHT
][BACK_CENTER
]+= M_SQRT1_2
;
189 }else if(out_ch_layout
& AV_CH_FRONT_LEFT
){
190 if (matrix_encoding
== AV_MATRIX_ENCODING_DOLBY
||
191 matrix_encoding
== AV_MATRIX_ENCODING_DPLII
) {
192 if (unaccounted
& (AV_CH_BACK_LEFT
| AV_CH_SIDE_LEFT
)) {
193 matrix
[FRONT_LEFT
][BACK_CENTER
] -= s
->slev
* M_SQRT1_2
;
194 matrix
[FRONT_RIGHT
][BACK_CENTER
] += s
->slev
* M_SQRT1_2
;
196 matrix
[FRONT_LEFT
][BACK_CENTER
] -= s
->slev
;
197 matrix
[FRONT_RIGHT
][BACK_CENTER
] += s
->slev
;
200 matrix
[ FRONT_LEFT
][BACK_CENTER
]+= s
->slev
*M_SQRT1_2
;
201 matrix
[FRONT_RIGHT
][BACK_CENTER
]+= s
->slev
*M_SQRT1_2
;
203 }else if(out_ch_layout
& AV_CH_FRONT_CENTER
){
204 matrix
[ FRONT_CENTER
][BACK_CENTER
]+= s
->slev
*M_SQRT1_2
;
208 if(unaccounted
& AV_CH_BACK_LEFT
){
209 if(out_ch_layout
& AV_CH_BACK_CENTER
){
210 matrix
[BACK_CENTER
][ BACK_LEFT
]+= M_SQRT1_2
;
211 matrix
[BACK_CENTER
][BACK_RIGHT
]+= M_SQRT1_2
;
212 }else if(out_ch_layout
& AV_CH_SIDE_LEFT
){
213 if(in_ch_layout
& AV_CH_SIDE_LEFT
){
214 matrix
[ SIDE_LEFT
][ BACK_LEFT
]+= M_SQRT1_2
;
215 matrix
[SIDE_RIGHT
][BACK_RIGHT
]+= M_SQRT1_2
;
217 matrix
[ SIDE_LEFT
][ BACK_LEFT
]+= 1.0;
218 matrix
[SIDE_RIGHT
][BACK_RIGHT
]+= 1.0;
220 }else if(out_ch_layout
& AV_CH_FRONT_LEFT
){
221 if (matrix_encoding
== AV_MATRIX_ENCODING_DOLBY
) {
222 matrix
[FRONT_LEFT
][BACK_LEFT
] -= s
->slev
* M_SQRT1_2
;
223 matrix
[FRONT_LEFT
][BACK_RIGHT
] -= s
->slev
* M_SQRT1_2
;
224 matrix
[FRONT_RIGHT
][BACK_LEFT
] += s
->slev
* M_SQRT1_2
;
225 matrix
[FRONT_RIGHT
][BACK_RIGHT
] += s
->slev
* M_SQRT1_2
;
226 } else if (matrix_encoding
== AV_MATRIX_ENCODING_DPLII
) {
227 matrix
[FRONT_LEFT
][BACK_LEFT
] -= s
->slev
* SQRT3_2
;
228 matrix
[FRONT_LEFT
][BACK_RIGHT
] -= s
->slev
* M_SQRT1_2
;
229 matrix
[FRONT_RIGHT
][BACK_LEFT
] += s
->slev
* M_SQRT1_2
;
230 matrix
[FRONT_RIGHT
][BACK_RIGHT
] += s
->slev
* SQRT3_2
;
232 matrix
[ FRONT_LEFT
][ BACK_LEFT
] += s
->slev
;
233 matrix
[FRONT_RIGHT
][BACK_RIGHT
] += s
->slev
;
235 }else if(out_ch_layout
& AV_CH_FRONT_CENTER
){
236 matrix
[ FRONT_CENTER
][BACK_LEFT
]+= s
->slev
*M_SQRT1_2
;
237 matrix
[ FRONT_CENTER
][BACK_RIGHT
]+= s
->slev
*M_SQRT1_2
;
242 if(unaccounted
& AV_CH_SIDE_LEFT
){
243 if(out_ch_layout
& AV_CH_BACK_LEFT
){
244 /* if back channels do not exist in the input, just copy side
245 channels to back channels, otherwise mix side into back */
246 if (in_ch_layout
& AV_CH_BACK_LEFT
) {
247 matrix
[BACK_LEFT
][SIDE_LEFT
] += M_SQRT1_2
;
248 matrix
[BACK_RIGHT
][SIDE_RIGHT
] += M_SQRT1_2
;
250 matrix
[BACK_LEFT
][SIDE_LEFT
] += 1.0;
251 matrix
[BACK_RIGHT
][SIDE_RIGHT
] += 1.0;
253 }else if(out_ch_layout
& AV_CH_BACK_CENTER
){
254 matrix
[BACK_CENTER
][ SIDE_LEFT
]+= M_SQRT1_2
;
255 matrix
[BACK_CENTER
][SIDE_RIGHT
]+= M_SQRT1_2
;
256 }else if(out_ch_layout
& AV_CH_FRONT_LEFT
){
257 if (matrix_encoding
== AV_MATRIX_ENCODING_DOLBY
) {
258 matrix
[FRONT_LEFT
][SIDE_LEFT
] -= s
->slev
* M_SQRT1_2
;
259 matrix
[FRONT_LEFT
][SIDE_RIGHT
] -= s
->slev
* M_SQRT1_2
;
260 matrix
[FRONT_RIGHT
][SIDE_LEFT
] += s
->slev
* M_SQRT1_2
;
261 matrix
[FRONT_RIGHT
][SIDE_RIGHT
] += s
->slev
* M_SQRT1_2
;
262 } else if (matrix_encoding
== AV_MATRIX_ENCODING_DPLII
) {
263 matrix
[FRONT_LEFT
][SIDE_LEFT
] -= s
->slev
* SQRT3_2
;
264 matrix
[FRONT_LEFT
][SIDE_RIGHT
] -= s
->slev
* M_SQRT1_2
;
265 matrix
[FRONT_RIGHT
][SIDE_LEFT
] += s
->slev
* M_SQRT1_2
;
266 matrix
[FRONT_RIGHT
][SIDE_RIGHT
] += s
->slev
* SQRT3_2
;
268 matrix
[ FRONT_LEFT
][ SIDE_LEFT
] += s
->slev
;
269 matrix
[FRONT_RIGHT
][SIDE_RIGHT
] += s
->slev
;
271 }else if(out_ch_layout
& AV_CH_FRONT_CENTER
){
272 matrix
[ FRONT_CENTER
][SIDE_LEFT
]+= s
->slev
*M_SQRT1_2
;
273 matrix
[ FRONT_CENTER
][SIDE_RIGHT
]+= s
->slev
*M_SQRT1_2
;
278 if(unaccounted
& AV_CH_FRONT_LEFT_OF_CENTER
){
279 if(out_ch_layout
& AV_CH_FRONT_LEFT
){
280 matrix
[ FRONT_LEFT
][ FRONT_LEFT_OF_CENTER
]+= 1.0;
281 matrix
[FRONT_RIGHT
][FRONT_RIGHT_OF_CENTER
]+= 1.0;
282 }else if(out_ch_layout
& AV_CH_FRONT_CENTER
){
283 matrix
[ FRONT_CENTER
][ FRONT_LEFT_OF_CENTER
]+= M_SQRT1_2
;
284 matrix
[ FRONT_CENTER
][FRONT_RIGHT_OF_CENTER
]+= M_SQRT1_2
;
288 /* mix LFE into front left/right or center */
289 if (unaccounted
& AV_CH_LOW_FREQUENCY
) {
290 if (out_ch_layout
& AV_CH_FRONT_CENTER
) {
291 matrix
[FRONT_CENTER
][LOW_FREQUENCY
] += s
->lfe_mix_level
;
292 } else if (out_ch_layout
& AV_CH_FRONT_LEFT
) {
293 matrix
[FRONT_LEFT
][LOW_FREQUENCY
] += s
->lfe_mix_level
* M_SQRT1_2
;
294 matrix
[FRONT_RIGHT
][LOW_FREQUENCY
] += s
->lfe_mix_level
* M_SQRT1_2
;
299 for(out_i
=i
=0; i
<64; i
++){
302 if((out_ch_layout
& (1ULL<<i
)) == 0)
305 if((in_ch_layout
& (1ULL<<j
)) == 0)
307 if (i
< FF_ARRAY_ELEMS(matrix
) && j
< FF_ARRAY_ELEMS(matrix
[0]))
308 s
->matrix
[out_i
][in_i
]= matrix
[i
][j
];
310 s
->matrix
[out_i
][in_i
]= i
== j
&& (in_ch_layout
& out_ch_layout
& (1ULL<<i
));
311 sum
+= fabs(s
->matrix
[out_i
][in_i
]);
314 maxcoef
= FFMAX(maxcoef
, sum
);
317 if(s
->rematrix_volume
< 0)
318 maxcoef
= -s
->rematrix_volume
;
320 if (s
->rematrix_maxval
> 0) {
321 maxval
= s
->rematrix_maxval
;
322 } else if ( av_get_packed_sample_fmt(s
->out_sample_fmt
) < AV_SAMPLE_FMT_FLT
323 || av_get_packed_sample_fmt(s
->int_sample_fmt
) < AV_SAMPLE_FMT_FLT
) {
328 if(maxcoef
> maxval
|| s
->rematrix_volume
< 0){
330 for(i
=0; i
<SWR_CH_MAX
; i
++)
331 for(j
=0; j
<SWR_CH_MAX
; j
++){
332 s
->matrix
[i
][j
] /= maxcoef
;
336 if(s
->rematrix_volume
> 0){
337 for(i
=0; i
<SWR_CH_MAX
; i
++)
338 for(j
=0; j
<SWR_CH_MAX
; j
++){
339 s
->matrix
[i
][j
] *= s
->rematrix_volume
;
343 for(i
=0; i
<av_get_channel_layout_nb_channels(out_ch_layout
); i
++){
344 for(j
=0; j
<av_get_channel_layout_nb_channels(in_ch_layout
); j
++){
345 av_log(NULL
, AV_LOG_DEBUG
, "%f ", s
->matrix
[i
][j
]);
347 av_log(NULL
, AV_LOG_DEBUG
, "\n");
352 av_cold
int swri_rematrix_init(SwrContext
*s
){
354 int nb_in
= av_get_channel_layout_nb_channels(s
->in_ch_layout
);
355 int nb_out
= av_get_channel_layout_nb_channels(s
->out_ch_layout
);
359 if (!s
->rematrix_custom
) {
360 int r
= auto_matrix(s
);
364 if (s
->midbuf
.fmt
== AV_SAMPLE_FMT_S16P
){
365 s
->native_matrix
= av_calloc(nb_in
* nb_out
, sizeof(int));
366 s
->native_one
= av_mallocz(sizeof(int));
367 for (i
= 0; i
< nb_out
; i
++)
368 for (j
= 0; j
< nb_in
; j
++)
369 ((int*)s
->native_matrix
)[i
* nb_in
+ j
] = lrintf(s
->matrix
[i
][j
] * 32768);
370 *((int*)s
->native_one
) = 32768;
371 s
->mix_1_1_f
= (mix_1_1_func_type
*)copy_s16
;
372 s
->mix_2_1_f
= (mix_2_1_func_type
*)sum2_s16
;
373 s
->mix_any_f
= (mix_any_func_type
*)get_mix_any_func_s16(s
);
374 }else if(s
->midbuf
.fmt
== AV_SAMPLE_FMT_FLTP
){
375 s
->native_matrix
= av_calloc(nb_in
* nb_out
, sizeof(float));
376 s
->native_one
= av_mallocz(sizeof(float));
377 for (i
= 0; i
< nb_out
; i
++)
378 for (j
= 0; j
< nb_in
; j
++)
379 ((float*)s
->native_matrix
)[i
* nb_in
+ j
] = s
->matrix
[i
][j
];
380 *((float*)s
->native_one
) = 1.0;
381 s
->mix_1_1_f
= (mix_1_1_func_type
*)copy_float
;
382 s
->mix_2_1_f
= (mix_2_1_func_type
*)sum2_float
;
383 s
->mix_any_f
= (mix_any_func_type
*)get_mix_any_func_float(s
);
384 }else if(s
->midbuf
.fmt
== AV_SAMPLE_FMT_DBLP
){
385 s
->native_matrix
= av_calloc(nb_in
* nb_out
, sizeof(double));
386 s
->native_one
= av_mallocz(sizeof(double));
387 for (i
= 0; i
< nb_out
; i
++)
388 for (j
= 0; j
< nb_in
; j
++)
389 ((double*)s
->native_matrix
)[i
* nb_in
+ j
] = s
->matrix
[i
][j
];
390 *((double*)s
->native_one
) = 1.0;
391 s
->mix_1_1_f
= (mix_1_1_func_type
*)copy_double
;
392 s
->mix_2_1_f
= (mix_2_1_func_type
*)sum2_double
;
393 s
->mix_any_f
= (mix_any_func_type
*)get_mix_any_func_double(s
);
394 }else if(s
->midbuf
.fmt
== AV_SAMPLE_FMT_S32P
){
395 // Only for dithering currently
396 // s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
397 s
->native_one
= av_mallocz(sizeof(int));
398 // for (i = 0; i < nb_out; i++)
399 // for (j = 0; j < nb_in; j++)
400 // ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
401 *((int*)s
->native_one
) = 32768;
402 s
->mix_1_1_f
= (mix_1_1_func_type
*)copy_s32
;
403 s
->mix_2_1_f
= (mix_2_1_func_type
*)sum2_s32
;
404 s
->mix_any_f
= (mix_any_func_type
*)get_mix_any_func_s32(s
);
407 //FIXME quantize for integeres
408 for (i
= 0; i
< SWR_CH_MAX
; i
++) {
410 for (j
= 0; j
< SWR_CH_MAX
; j
++) {
411 s
->matrix32
[i
][j
]= lrintf(s
->matrix
[i
][j
] * 32768);
413 s
->matrix_ch
[i
][++ch_in
]= j
;
415 s
->matrix_ch
[i
][0]= ch_in
;
418 if(HAVE_YASM
&& HAVE_MMX
) swri_rematrix_init_x86(s
);
423 av_cold
void swri_rematrix_free(SwrContext
*s
){
424 av_freep(&s
->native_matrix
);
425 av_freep(&s
->native_one
);
426 av_freep(&s
->native_simd_matrix
);
427 av_freep(&s
->native_simd_one
);
430 int swri_rematrix(SwrContext
*s
, AudioData
*out
, AudioData
*in
, int len
, int mustcopy
){
431 int out_i
, in_i
, i
, j
;
436 s
->mix_any_f(out
->ch
, (const uint8_t **)in
->ch
, s
->native_matrix
, len
);
440 if(s
->mix_2_1_simd
|| s
->mix_1_1_simd
){
442 off
= len1
* out
->bps
;
445 av_assert0(!s
->out_ch_layout
|| out
->ch_count
== av_get_channel_layout_nb_channels(s
->out_ch_layout
));
446 av_assert0(!s
-> in_ch_layout
|| in
->ch_count
== av_get_channel_layout_nb_channels(s
-> in_ch_layout
));
448 for(out_i
=0; out_i
<out
->ch_count
; out_i
++){
449 switch(s
->matrix_ch
[out_i
][0]){
452 memset(out
->ch
[out_i
], 0, len
* av_get_bytes_per_sample(s
->int_sample_fmt
));
455 in_i
= s
->matrix_ch
[out_i
][1];
456 if(s
->matrix
[out_i
][in_i
]!=1.0){
457 if(s
->mix_1_1_simd
&& len1
)
458 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
);
460 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
);
462 memcpy(out
->ch
[out_i
], in
->ch
[in_i
], len
*out
->bps
);
464 out
->ch
[out_i
]= in
->ch
[in_i
];
468 int in_i1
= s
->matrix_ch
[out_i
][1];
469 int in_i2
= s
->matrix_ch
[out_i
][2];
470 if(s
->mix_2_1_simd
&& len1
)
471 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
);
473 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
);
475 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
);
478 if(s
->int_sample_fmt
== AV_SAMPLE_FMT_FLTP
){
479 for(i
=0; i
<len
; i
++){
481 for(j
=0; j
<s
->matrix_ch
[out_i
][0]; j
++){
482 in_i
= s
->matrix_ch
[out_i
][1+j
];
483 v
+= ((float*)in
->ch
[in_i
])[i
] * s
->matrix
[out_i
][in_i
];
485 ((float*)out
->ch
[out_i
])[i
]= v
;
487 }else if(s
->int_sample_fmt
== AV_SAMPLE_FMT_DBLP
){
488 for(i
=0; i
<len
; i
++){
490 for(j
=0; j
<s
->matrix_ch
[out_i
][0]; j
++){
491 in_i
= s
->matrix_ch
[out_i
][1+j
];
492 v
+= ((double*)in
->ch
[in_i
])[i
] * s
->matrix
[out_i
][in_i
];
494 ((double*)out
->ch
[out_i
])[i
]= v
;
497 for(i
=0; i
<len
; i
++){
499 for(j
=0; j
<s
->matrix_ch
[out_i
][0]; j
++){
500 in_i
= s
->matrix_ch
[out_i
][1+j
];
501 v
+= ((int16_t*)in
->ch
[in_i
])[i
] * s
->matrix32
[out_i
][in_i
];
503 ((int16_t*)out
->ch
[out_i
])[i
]= (v
+ 16384)>>15;