Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 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
#undef TEMPLATE_REMATRIX_S16
36
 
37
#define TEMPLATE_REMATRIX_S32
38
#include "rematrix_template.c"
39
#undef TEMPLATE_REMATRIX_S32
40
 
41
#define FRONT_LEFT             0
42
#define FRONT_RIGHT            1
43
#define FRONT_CENTER           2
44
#define LOW_FREQUENCY          3
45
#define BACK_LEFT              4
46
#define BACK_RIGHT             5
47
#define FRONT_LEFT_OF_CENTER   6
48
#define FRONT_RIGHT_OF_CENTER  7
49
#define BACK_CENTER            8
50
#define SIDE_LEFT              9
51
#define SIDE_RIGHT             10
52
#define TOP_CENTER             11
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
 
60
int swr_set_matrix(struct SwrContext *s, const double *matrix, int stride)
61
{
62
    int nb_in, nb_out, in, out;
63
 
64
    if (!s || s->in_convert) // s needs to be allocated but not initialized
65
        return AVERROR(EINVAL);
66
    memset(s->matrix, 0, sizeof(s->matrix));
67
    nb_in  = av_get_channel_layout_nb_channels(s->in_ch_layout);
68
    nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
69
    for (out = 0; out < nb_out; out++) {
70
        for (in = 0; in < nb_in; in++)
71
            s->matrix[out][in] = matrix[in];
72
        matrix += stride;
73
    }
74
    s->rematrix_custom = 1;
75
    return 0;
76
}
77
 
78
static int even(int64_t layout){
79
    if(!layout) return 1;
80
    if(layout&(layout-1)) return 1;
81
    return 0;
82
}
83
 
84
static int clean_layout(SwrContext *s, int64_t layout){
85
    if(layout && layout != AV_CH_FRONT_CENTER && !(layout&(layout-1))) {
86
        char buf[128];
87
        av_get_channel_layout_string(buf, sizeof(buf), -1, layout);
88
        av_log(s, AV_LOG_VERBOSE, "Treating %s as mono\n", buf);
89
        return AV_CH_FRONT_CENTER;
90
    }
91
 
92
    return layout;
93
}
94
 
95
static int sane_layout(int64_t layout){
96
    if(!(layout & AV_CH_LAYOUT_SURROUND)) // at least 1 front speaker
97
        return 0;
98
    if(!even(layout & (AV_CH_FRONT_LEFT | AV_CH_FRONT_RIGHT))) // no asymetric front
99
        return 0;
100
    if(!even(layout & (AV_CH_SIDE_LEFT | AV_CH_SIDE_RIGHT)))   // no asymetric side
101
        return 0;
102
    if(!even(layout & (AV_CH_BACK_LEFT | AV_CH_BACK_RIGHT)))
103
        return 0;
104
    if(!even(layout & (AV_CH_FRONT_LEFT_OF_CENTER | AV_CH_FRONT_RIGHT_OF_CENTER)))
105
        return 0;
106
    if(av_get_channel_layout_nb_channels(layout) >= SWR_CH_MAX)
107
        return 0;
108
 
109
    return 1;
110
}
111
 
112
av_cold static int auto_matrix(SwrContext *s)
113
{
114
    int i, j, out_i;
115
    double matrix[64][64]={{0}};
116
    int64_t unaccounted, in_ch_layout, out_ch_layout;
117
    double maxcoef=0;
118
    char buf[128];
119
    const int matrix_encoding = s->matrix_encoding;
120
    float maxval;
121
 
122
    in_ch_layout = clean_layout(s, s->in_ch_layout);
123
    out_ch_layout = clean_layout(s, s->out_ch_layout);
124
 
125
    if(   out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX
126
       && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0
127
    )
128
        out_ch_layout = AV_CH_LAYOUT_STEREO;
129
 
130
    if(!sane_layout(in_ch_layout)){
131
        av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout);
132
        av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf);
133
        return AVERROR(EINVAL);
134
    }
135
 
136
    if(!sane_layout(out_ch_layout)){
137
        av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout);
138
        av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf);
139
        return AVERROR(EINVAL);
140
    }
141
 
142
    memset(s->matrix, 0, sizeof(s->matrix));
143
    for(i=0; i<64; i++){
144
        if(in_ch_layout & out_ch_layout & (1ULL<
145
            matrix[i][i]= 1.0;
146
    }
147
 
148
    unaccounted= in_ch_layout & ~out_ch_layout;
149
 
150
//FIXME implement dolby surround
151
//FIXME implement full ac3
152
 
153
 
154
    if(unaccounted & AV_CH_FRONT_CENTER){
155
        if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){
156
            if(in_ch_layout & AV_CH_LAYOUT_STEREO) {
157
                matrix[ FRONT_LEFT][FRONT_CENTER]+= s->clev;
158
                matrix[FRONT_RIGHT][FRONT_CENTER]+= s->clev;
159
            } else {
160
                matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2;
161
                matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2;
162
            }
163
        }else
164
            av_assert0(0);
165
    }
166
    if(unaccounted & AV_CH_LAYOUT_STEREO){
167
        if(out_ch_layout & AV_CH_FRONT_CENTER){
168
            matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2;
169
            matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2;
170
            if(in_ch_layout & AV_CH_FRONT_CENTER)
171
                matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2);
172
        }else
173
            av_assert0(0);
174
    }
175
 
176
    if(unaccounted & AV_CH_BACK_CENTER){
177
        if(out_ch_layout & AV_CH_BACK_LEFT){
178
            matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2;
179
            matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2;
180
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
181
            matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2;
182
            matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2;
183
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
184
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY ||
185
                matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
186
                if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) {
187
                    matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev * M_SQRT1_2;
188
                    matrix[FRONT_RIGHT][BACK_CENTER] += s->slev * M_SQRT1_2;
189
                } else {
190
                    matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev;
191
                    matrix[FRONT_RIGHT][BACK_CENTER] += s->slev;
192
                }
193
            } else {
194
                matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2;
195
                matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2;
196
            }
197
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
198
            matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2;
199
        }else
200
            av_assert0(0);
201
    }
202
    if(unaccounted & AV_CH_BACK_LEFT){
203
        if(out_ch_layout & AV_CH_BACK_CENTER){
204
            matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2;
205
            matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2;
206
        }else if(out_ch_layout & AV_CH_SIDE_LEFT){
207
            if(in_ch_layout & AV_CH_SIDE_LEFT){
208
                matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2;
209
                matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2;
210
            }else{
211
            matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0;
212
            matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0;
213
            }
214
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
215
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
216
                matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * M_SQRT1_2;
217
                matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
218
                matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
219
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * M_SQRT1_2;
220
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
221
                matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * SQRT3_2;
222
                matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2;
223
                matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2;
224
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * SQRT3_2;
225
            } else {
226
                matrix[ FRONT_LEFT][ BACK_LEFT] += s->slev;
227
                matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev;
228
            }
229
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
230
            matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2;
231
            matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2;
232
        }else
233
            av_assert0(0);
234
    }
235
 
236
    if(unaccounted & AV_CH_SIDE_LEFT){
237
        if(out_ch_layout & AV_CH_BACK_LEFT){
238
            /* if back channels do not exist in the input, just copy side
239
               channels to back channels, otherwise mix side into back */
240
            if (in_ch_layout & AV_CH_BACK_LEFT) {
241
                matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2;
242
                matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2;
243
            } else {
244
                matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0;
245
                matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0;
246
            }
247
        }else if(out_ch_layout & AV_CH_BACK_CENTER){
248
            matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2;
249
            matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2;
250
        }else if(out_ch_layout & AV_CH_FRONT_LEFT){
251
            if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) {
252
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * M_SQRT1_2;
253
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
254
                matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
255
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * M_SQRT1_2;
256
            } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) {
257
                matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * SQRT3_2;
258
                matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2;
259
                matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2;
260
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * SQRT3_2;
261
            } else {
262
                matrix[ FRONT_LEFT][ SIDE_LEFT] += s->slev;
263
                matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev;
264
            }
265
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
266
            matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2;
267
            matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2;
268
        }else
269
            av_assert0(0);
270
    }
271
 
272
    if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){
273
        if(out_ch_layout & AV_CH_FRONT_LEFT){
274
            matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0;
275
            matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0;
276
        }else if(out_ch_layout & AV_CH_FRONT_CENTER){
277
            matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2;
278
            matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2;
279
        }else
280
            av_assert0(0);
281
    }
282
    /* mix LFE into front left/right or center */
283
    if (unaccounted & AV_CH_LOW_FREQUENCY) {
284
        if (out_ch_layout & AV_CH_FRONT_CENTER) {
285
            matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level;
286
        } else if (out_ch_layout & AV_CH_FRONT_LEFT) {
287
            matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
288
            matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2;
289
        } else
290
            av_assert0(0);
291
    }
292
 
293
    for(out_i=i=0; i<64; i++){
294
        double sum=0;
295
        int in_i=0;
296
        for(j=0; j<64; j++){
297
            s->matrix[out_i][in_i]= matrix[i][j];
298
            if(matrix[i][j]){
299
                sum += fabs(matrix[i][j]);
300
            }
301
            if(in_ch_layout & (1ULL<
302
                in_i++;
303
        }
304
        maxcoef= FFMAX(maxcoef, sum);
305
        if(out_ch_layout & (1ULL<
306
            out_i++;
307
    }
308
    if(s->rematrix_volume  < 0)
309
        maxcoef = -s->rematrix_volume;
310
 
311
    if (s->rematrix_maxval > 0) {
312
        maxval = s->rematrix_maxval;
313
    } else if (   av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT
314
               || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) {
315
        maxval = 1.0;
316
    } else
317
        maxval = INT_MAX;
318
 
319
    if(maxcoef > maxval || s->rematrix_volume  < 0){
320
        maxcoef /= maxval;
321
        for(i=0; i
322
            for(j=0; j
323
                s->matrix[i][j] /= maxcoef;
324
            }
325
    }
326
 
327
    if(s->rematrix_volume > 0){
328
        for(i=0; i
329
            for(j=0; j
330
                s->matrix[i][j] *= s->rematrix_volume;
331
            }
332
    }
333
 
334
    for(i=0; i
335
        for(j=0; j
336
            av_log(NULL, AV_LOG_DEBUG, "%f ", s->matrix[i][j]);
337
        }
338
        av_log(NULL, AV_LOG_DEBUG, "\n");
339
    }
340
    return 0;
341
}
342
 
343
av_cold int swri_rematrix_init(SwrContext *s){
344
    int i, j;
345
    int nb_in  = av_get_channel_layout_nb_channels(s->in_ch_layout);
346
    int nb_out = av_get_channel_layout_nb_channels(s->out_ch_layout);
347
 
348
    s->mix_any_f = NULL;
349
 
350
    if (!s->rematrix_custom) {
351
        int r = auto_matrix(s);
352
        if (r)
353
            return r;
354
    }
355
    if (s->midbuf.fmt == AV_SAMPLE_FMT_S16P){
356
        s->native_matrix = av_calloc(nb_in * nb_out, sizeof(int));
357
        s->native_one    = av_mallocz(sizeof(int));
358
        for (i = 0; i < nb_out; i++)
359
            for (j = 0; j < nb_in; j++)
360
                ((int*)s->native_matrix)[i * nb_in + j] = lrintf(s->matrix[i][j] * 32768);
361
        *((int*)s->native_one) = 32768;
362
        s->mix_1_1_f = (mix_1_1_func_type*)copy_s16;
363
        s->mix_2_1_f = (mix_2_1_func_type*)sum2_s16;
364
        s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s16(s);
365
    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_FLTP){
366
        s->native_matrix = av_calloc(nb_in * nb_out, sizeof(float));
367
        s->native_one    = av_mallocz(sizeof(float));
368
        for (i = 0; i < nb_out; i++)
369
            for (j = 0; j < nb_in; j++)
370
                ((float*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
371
        *((float*)s->native_one) = 1.0;
372
        s->mix_1_1_f = (mix_1_1_func_type*)copy_float;
373
        s->mix_2_1_f = (mix_2_1_func_type*)sum2_float;
374
        s->mix_any_f = (mix_any_func_type*)get_mix_any_func_float(s);
375
    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_DBLP){
376
        s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
377
        s->native_one    = av_mallocz(sizeof(double));
378
        for (i = 0; i < nb_out; i++)
379
            for (j = 0; j < nb_in; j++)
380
                ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
381
        *((double*)s->native_one) = 1.0;
382
        s->mix_1_1_f = (mix_1_1_func_type*)copy_double;
383
        s->mix_2_1_f = (mix_2_1_func_type*)sum2_double;
384
        s->mix_any_f = (mix_any_func_type*)get_mix_any_func_double(s);
385
    }else if(s->midbuf.fmt == AV_SAMPLE_FMT_S32P){
386
        // Only for dithering currently
387
//         s->native_matrix = av_calloc(nb_in * nb_out, sizeof(double));
388
        s->native_one    = av_mallocz(sizeof(int));
389
//         for (i = 0; i < nb_out; i++)
390
//             for (j = 0; j < nb_in; j++)
391
//                 ((double*)s->native_matrix)[i * nb_in + j] = s->matrix[i][j];
392
        *((int*)s->native_one) = 32768;
393
        s->mix_1_1_f = (mix_1_1_func_type*)copy_s32;
394
        s->mix_2_1_f = (mix_2_1_func_type*)sum2_s32;
395
        s->mix_any_f = (mix_any_func_type*)get_mix_any_func_s32(s);
396
    }else
397
        av_assert0(0);
398
    //FIXME quantize for integeres
399
    for (i = 0; i < SWR_CH_MAX; i++) {
400
        int ch_in=0;
401
        for (j = 0; j < SWR_CH_MAX; j++) {
402
            s->matrix32[i][j]= lrintf(s->matrix[i][j] * 32768);
403
            if(s->matrix[i][j])
404
                s->matrix_ch[i][++ch_in]= j;
405
        }
406
        s->matrix_ch[i][0]= ch_in;
407
    }
408
 
409
    if(HAVE_YASM && HAVE_MMX) swri_rematrix_init_x86(s);
410
 
411
    return 0;
412
}
413
 
414
av_cold void swri_rematrix_free(SwrContext *s){
415
    av_freep(&s->native_matrix);
416
    av_freep(&s->native_one);
417
    av_freep(&s->native_simd_matrix);
418
    av_freep(&s->native_simd_one);
419
}
420
 
421
int swri_rematrix(SwrContext *s, AudioData *out, AudioData *in, int len, int mustcopy){
422
    int out_i, in_i, i, j;
423
    int len1 = 0;
424
    int off = 0;
425
 
426
    if(s->mix_any_f) {
427
        s->mix_any_f(out->ch, (const uint8_t **)in->ch, s->native_matrix, len);
428
        return 0;
429
    }
430
 
431
    if(s->mix_2_1_simd || s->mix_1_1_simd){
432
        len1= len&~15;
433
        off = len1 * out->bps;
434
    }
435
 
436
    av_assert0(out->ch_count == av_get_channel_layout_nb_channels(s->out_ch_layout));
437
    av_assert0(in ->ch_count == av_get_channel_layout_nb_channels(s-> in_ch_layout));
438
 
439
    for(out_i=0; out_ich_count; out_i++){
440
        switch(s->matrix_ch[out_i][0]){
441
        case 0:
442
            if(mustcopy)
443
                memset(out->ch[out_i], 0, len * av_get_bytes_per_sample(s->int_sample_fmt));
444
            break;
445
        case 1:
446
            in_i= s->matrix_ch[out_i][1];
447
            if(s->matrix[out_i][in_i]!=1.0){
448
                if(s->mix_1_1_simd && len1)
449
                    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);
450
                if(len != len1)
451
                    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);
452
            }else if(mustcopy){
453
                memcpy(out->ch[out_i], in->ch[in_i], len*out->bps);
454
            }else{
455
                out->ch[out_i]= in->ch[in_i];
456
            }
457
            break;
458
        case 2: {
459
            int in_i1 = s->matrix_ch[out_i][1];
460
            int in_i2 = s->matrix_ch[out_i][2];
461
            if(s->mix_2_1_simd && len1)
462
                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);
463
            else
464
                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);
465
            if(len != len1)
466
                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);
467
            break;}
468
        default:
469
            if(s->int_sample_fmt == AV_SAMPLE_FMT_FLTP){
470
                for(i=0; i
471
                    float v=0;
472
                    for(j=0; jmatrix_ch[out_i][0]; j++){
473
                        in_i= s->matrix_ch[out_i][1+j];
474
                        v+= ((float*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
475
                    }
476
                    ((float*)out->ch[out_i])[i]= v;
477
                }
478
            }else if(s->int_sample_fmt == AV_SAMPLE_FMT_DBLP){
479
                for(i=0; i
480
                    double v=0;
481
                    for(j=0; jmatrix_ch[out_i][0]; j++){
482
                        in_i= s->matrix_ch[out_i][1+j];
483
                        v+= ((double*)in->ch[in_i])[i] * s->matrix[out_i][in_i];
484
                    }
485
                    ((double*)out->ch[out_i])[i]= v;
486
                }
487
            }else{
488
                for(i=0; i
489
                    int v=0;
490
                    for(j=0; jmatrix_ch[out_i][0]; j++){
491
                        in_i= s->matrix_ch[out_i][1+j];
492
                        v+= ((int16_t*)in->ch[in_i])[i] * s->matrix32[out_i][in_i];
493
                    }
494
                    ((int16_t*)out->ch[out_i])[i]= (v + 16384)>>15;
495
                }
496
            }
497
        }
498
    }
499
    return 0;
500
}