Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
52868 views
1
/*
2
* Copyright (c) 2012 Justin Ruggles <[email protected]>
3
*
4
* This file is part of FFmpeg.
5
*
6
* FFmpeg 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
* FFmpeg 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 FFmpeg; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
*/
20
21
#include <stdint.h>
22
23
#include "libavutil/common.h"
24
#include "libavutil/libm.h"
25
#include "libavutil/samplefmt.h"
26
#include "avresample.h"
27
#include "internal.h"
28
#include "audio_data.h"
29
#include "audio_mix.h"
30
31
static const char * const coeff_type_names[] = { "q8", "q15", "flt" };
32
33
struct AudioMix {
34
AVAudioResampleContext *avr;
35
enum AVSampleFormat fmt;
36
enum AVMixCoeffType coeff_type;
37
uint64_t in_layout;
38
uint64_t out_layout;
39
int in_channels;
40
int out_channels;
41
42
int ptr_align;
43
int samples_align;
44
int has_optimized_func;
45
const char *func_descr;
46
const char *func_descr_generic;
47
mix_func *mix;
48
mix_func *mix_generic;
49
50
int in_matrix_channels;
51
int out_matrix_channels;
52
int output_zero[AVRESAMPLE_MAX_CHANNELS];
53
int input_skip[AVRESAMPLE_MAX_CHANNELS];
54
int output_skip[AVRESAMPLE_MAX_CHANNELS];
55
int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
56
int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
57
float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
58
void **matrix;
59
};
60
61
void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
62
enum AVMixCoeffType coeff_type, int in_channels,
63
int out_channels, int ptr_align, int samples_align,
64
const char *descr, void *mix_func)
65
{
66
if (fmt == am->fmt && coeff_type == am->coeff_type &&
67
( in_channels == am->in_matrix_channels || in_channels == 0) &&
68
(out_channels == am->out_matrix_channels || out_channels == 0)) {
69
char chan_str[16];
70
am->mix = mix_func;
71
am->func_descr = descr;
72
am->ptr_align = ptr_align;
73
am->samples_align = samples_align;
74
if (ptr_align == 1 && samples_align == 1) {
75
am->mix_generic = mix_func;
76
am->func_descr_generic = descr;
77
} else {
78
am->has_optimized_func = 1;
79
}
80
if (in_channels) {
81
if (out_channels)
82
snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
83
in_channels, out_channels);
84
else
85
snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
86
in_channels);
87
} else if (out_channels) {
88
snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
89
out_channels);
90
} else {
91
snprintf(chan_str, sizeof(chan_str), "[any to any] ");
92
}
93
av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
94
"[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
95
coeff_type_names[coeff_type], chan_str, descr);
96
}
97
}
98
99
#define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
100
101
#define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
102
static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
103
int len, int out_ch, int in_ch) \
104
{ \
105
int i, in, out; \
106
stype temp[AVRESAMPLE_MAX_CHANNELS]; \
107
for (i = 0; i < len; i++) { \
108
for (out = 0; out < out_ch; out++) { \
109
sumtype sum = 0; \
110
for (in = 0; in < in_ch; in++) \
111
sum += samples[in][i] * matrix[out][in]; \
112
temp[out] = expr; \
113
} \
114
for (out = 0; out < out_ch; out++) \
115
samples[out][i] = temp[out]; \
116
} \
117
}
118
119
MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
120
MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
121
MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
122
MIX_FUNC_GENERIC(S16P, Q8, int16_t, int16_t, int32_t, av_clip_int16(sum >> 8))
123
124
/* TODO: templatize the channel-specific C functions */
125
126
static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
127
int out_ch, int in_ch)
128
{
129
float *src0 = samples[0];
130
float *src1 = samples[1];
131
float *dst = src0;
132
float m0 = matrix[0][0];
133
float m1 = matrix[0][1];
134
135
while (len > 4) {
136
*dst++ = *src0++ * m0 + *src1++ * m1;
137
*dst++ = *src0++ * m0 + *src1++ * m1;
138
*dst++ = *src0++ * m0 + *src1++ * m1;
139
*dst++ = *src0++ * m0 + *src1++ * m1;
140
len -= 4;
141
}
142
while (len > 0) {
143
*dst++ = *src0++ * m0 + *src1++ * m1;
144
len--;
145
}
146
}
147
148
static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
149
int out_ch, int in_ch)
150
{
151
int16_t *src0 = samples[0];
152
int16_t *src1 = samples[1];
153
int16_t *dst = src0;
154
float m0 = matrix[0][0];
155
float m1 = matrix[0][1];
156
157
while (len > 4) {
158
*dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
159
*dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
160
*dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
161
*dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
162
len -= 4;
163
}
164
while (len > 0) {
165
*dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
166
len--;
167
}
168
}
169
170
static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
171
int out_ch, int in_ch)
172
{
173
int16_t *src0 = samples[0];
174
int16_t *src1 = samples[1];
175
int16_t *dst = src0;
176
int16_t m0 = matrix[0][0];
177
int16_t m1 = matrix[0][1];
178
179
while (len > 4) {
180
*dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
181
*dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
182
*dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
183
*dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
184
len -= 4;
185
}
186
while (len > 0) {
187
*dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
188
len--;
189
}
190
}
191
192
static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
193
int out_ch, int in_ch)
194
{
195
float v;
196
float *dst0 = samples[0];
197
float *dst1 = samples[1];
198
float *src = dst0;
199
float m0 = matrix[0][0];
200
float m1 = matrix[1][0];
201
202
while (len > 4) {
203
v = *src++;
204
*dst0++ = v * m0;
205
*dst1++ = v * m1;
206
v = *src++;
207
*dst0++ = v * m0;
208
*dst1++ = v * m1;
209
v = *src++;
210
*dst0++ = v * m0;
211
*dst1++ = v * m1;
212
v = *src++;
213
*dst0++ = v * m0;
214
*dst1++ = v * m1;
215
len -= 4;
216
}
217
while (len > 0) {
218
v = *src++;
219
*dst0++ = v * m0;
220
*dst1++ = v * m1;
221
len--;
222
}
223
}
224
225
static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
226
int out_ch, int in_ch)
227
{
228
float v0, v1;
229
float *src0 = samples[0];
230
float *src1 = samples[1];
231
float *src2 = samples[2];
232
float *src3 = samples[3];
233
float *src4 = samples[4];
234
float *src5 = samples[5];
235
float *dst0 = src0;
236
float *dst1 = src1;
237
float *m0 = matrix[0];
238
float *m1 = matrix[1];
239
240
while (len > 0) {
241
v0 = *src0++;
242
v1 = *src1++;
243
*dst0++ = v0 * m0[0] +
244
v1 * m0[1] +
245
*src2 * m0[2] +
246
*src3 * m0[3] +
247
*src4 * m0[4] +
248
*src5 * m0[5];
249
*dst1++ = v0 * m1[0] +
250
v1 * m1[1] +
251
*src2++ * m1[2] +
252
*src3++ * m1[3] +
253
*src4++ * m1[4] +
254
*src5++ * m1[5];
255
len--;
256
}
257
}
258
259
static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
260
int out_ch, int in_ch)
261
{
262
float v0, v1;
263
float *dst0 = samples[0];
264
float *dst1 = samples[1];
265
float *dst2 = samples[2];
266
float *dst3 = samples[3];
267
float *dst4 = samples[4];
268
float *dst5 = samples[5];
269
float *src0 = dst0;
270
float *src1 = dst1;
271
272
while (len > 0) {
273
v0 = *src0++;
274
v1 = *src1++;
275
*dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
276
*dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
277
*dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
278
*dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
279
*dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
280
*dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
281
len--;
282
}
283
}
284
285
static av_cold int mix_function_init(AudioMix *am)
286
{
287
am->func_descr = am->func_descr_generic = "n/a";
288
am->mix = am->mix_generic = NULL;
289
290
/* no need to set a mix function when we're skipping mixing */
291
if (!am->in_matrix_channels || !am->out_matrix_channels)
292
return 0;
293
294
/* any-to-any C versions */
295
296
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
297
0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
298
299
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
300
0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
301
302
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
303
0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
304
305
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
306
0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
307
308
/* channel-specific C versions */
309
310
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
311
2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
312
313
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
314
2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
315
316
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
317
2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
318
319
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
320
1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
321
322
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
323
6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
324
325
ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
326
2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
327
328
if (ARCH_X86)
329
ff_audio_mix_init_x86(am);
330
331
if (!am->mix) {
332
av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
333
"[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
334
coeff_type_names[am->coeff_type], am->in_channels,
335
am->out_channels);
336
return AVERROR_PATCHWELCOME;
337
}
338
return 0;
339
}
340
341
AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
342
{
343
AudioMix *am;
344
int ret;
345
346
am = av_mallocz(sizeof(*am));
347
if (!am)
348
return NULL;
349
am->avr = avr;
350
351
if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
352
avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
353
av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
354
"mixing: %s\n",
355
av_get_sample_fmt_name(avr->internal_sample_fmt));
356
goto error;
357
}
358
359
am->fmt = avr->internal_sample_fmt;
360
am->coeff_type = avr->mix_coeff_type;
361
am->in_layout = avr->in_channel_layout;
362
am->out_layout = avr->out_channel_layout;
363
am->in_channels = avr->in_channels;
364
am->out_channels = avr->out_channels;
365
366
/* build matrix if the user did not already set one */
367
if (avr->mix_matrix) {
368
ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
369
if (ret < 0)
370
goto error;
371
av_freep(&avr->mix_matrix);
372
} else {
373
double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
374
sizeof(*matrix_dbl));
375
if (!matrix_dbl)
376
goto error;
377
378
ret = avresample_build_matrix(avr->in_channel_layout,
379
avr->out_channel_layout,
380
avr->center_mix_level,
381
avr->surround_mix_level,
382
avr->lfe_mix_level,
383
avr->normalize_mix_level,
384
matrix_dbl,
385
avr->in_channels,
386
avr->matrix_encoding);
387
if (ret < 0) {
388
av_free(matrix_dbl);
389
goto error;
390
}
391
392
ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
393
if (ret < 0) {
394
av_log(avr, AV_LOG_ERROR, "error setting mix matrix\n");
395
av_free(matrix_dbl);
396
goto error;
397
}
398
399
av_free(matrix_dbl);
400
}
401
402
return am;
403
404
error:
405
av_free(am);
406
return NULL;
407
}
408
409
void ff_audio_mix_free(AudioMix **am_p)
410
{
411
AudioMix *am;
412
413
if (!*am_p)
414
return;
415
am = *am_p;
416
417
if (am->matrix) {
418
av_free(am->matrix[0]);
419
am->matrix = NULL;
420
}
421
memset(am->matrix_q8, 0, sizeof(am->matrix_q8 ));
422
memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
423
memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
424
425
av_freep(am_p);
426
}
427
428
int ff_audio_mix(AudioMix *am, AudioData *src)
429
{
430
int use_generic = 1;
431
int len = src->nb_samples;
432
int i, j;
433
434
/* determine whether to use the optimized function based on pointer and
435
samples alignment in both the input and output */
436
if (am->has_optimized_func) {
437
int aligned_len = FFALIGN(len, am->samples_align);
438
if (!(src->ptr_align % am->ptr_align) &&
439
src->samples_align >= aligned_len) {
440
len = aligned_len;
441
use_generic = 0;
442
}
443
}
444
av_log(am->avr, AV_LOG_TRACE, "audio_mix: %d samples - %d to %d channels (%s)\n",
445
src->nb_samples, am->in_channels, am->out_channels,
446
use_generic ? am->func_descr_generic : am->func_descr);
447
448
if (am->in_matrix_channels && am->out_matrix_channels) {
449
uint8_t **data;
450
uint8_t *data0[AVRESAMPLE_MAX_CHANNELS] = { NULL };
451
452
if (am->out_matrix_channels < am->out_channels ||
453
am->in_matrix_channels < am->in_channels) {
454
for (i = 0, j = 0; i < FFMAX(am->in_channels, am->out_channels); i++) {
455
if (am->input_skip[i] || am->output_skip[i] || am->output_zero[i])
456
continue;
457
data0[j++] = src->data[i];
458
}
459
data = data0;
460
} else {
461
data = src->data;
462
}
463
464
if (use_generic)
465
am->mix_generic(data, am->matrix, len, am->out_matrix_channels,
466
am->in_matrix_channels);
467
else
468
am->mix(data, am->matrix, len, am->out_matrix_channels,
469
am->in_matrix_channels);
470
}
471
472
if (am->out_matrix_channels < am->out_channels) {
473
for (i = 0; i < am->out_channels; i++)
474
if (am->output_zero[i])
475
av_samples_set_silence(&src->data[i], 0, len, 1, am->fmt);
476
}
477
478
ff_audio_data_set_channels(src, am->out_channels);
479
480
return 0;
481
}
482
483
int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
484
{
485
int i, o, i0, o0;
486
487
if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
488
am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
489
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
490
return AVERROR(EINVAL);
491
}
492
493
#define GET_MATRIX_CONVERT(suffix, scale) \
494
if (!am->matrix_ ## suffix[0]) { \
495
av_log(am->avr, AV_LOG_ERROR, "matrix is not set\n"); \
496
return AVERROR(EINVAL); \
497
} \
498
for (o = 0, o0 = 0; o < am->out_channels; o++) { \
499
for (i = 0, i0 = 0; i < am->in_channels; i++) { \
500
if (am->input_skip[i] || am->output_zero[o]) \
501
matrix[o * stride + i] = 0.0; \
502
else \
503
matrix[o * stride + i] = am->matrix_ ## suffix[o0][i0] * \
504
(scale); \
505
if (!am->input_skip[i]) \
506
i0++; \
507
} \
508
if (!am->output_zero[o]) \
509
o0++; \
510
}
511
512
switch (am->coeff_type) {
513
case AV_MIX_COEFF_TYPE_Q8:
514
GET_MATRIX_CONVERT(q8, 1.0 / 256.0);
515
break;
516
case AV_MIX_COEFF_TYPE_Q15:
517
GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);
518
break;
519
case AV_MIX_COEFF_TYPE_FLT:
520
GET_MATRIX_CONVERT(flt, 1.0);
521
break;
522
default:
523
av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
524
return AVERROR(EINVAL);
525
}
526
527
return 0;
528
}
529
530
static void reduce_matrix(AudioMix *am, const double *matrix, int stride)
531
{
532
int i, o;
533
534
memset(am->output_zero, 0, sizeof(am->output_zero));
535
memset(am->input_skip, 0, sizeof(am->input_skip));
536
memset(am->output_skip, 0, sizeof(am->output_skip));
537
538
/* exclude output channels if they can be zeroed instead of mixed */
539
for (o = 0; o < am->out_channels; o++) {
540
int zero = 1;
541
542
/* check if the output is always silent */
543
for (i = 0; i < am->in_channels; i++) {
544
if (matrix[o * stride + i] != 0.0) {
545
zero = 0;
546
break;
547
}
548
}
549
/* check if the corresponding input channel makes a contribution to
550
any output channel */
551
if (o < am->in_channels) {
552
for (i = 0; i < am->out_channels; i++) {
553
if (matrix[i * stride + o] != 0.0) {
554
zero = 0;
555
break;
556
}
557
}
558
}
559
if (zero) {
560
am->output_zero[o] = 1;
561
am->out_matrix_channels--;
562
if (o < am->in_channels)
563
am->in_matrix_channels--;
564
}
565
}
566
if (am->out_matrix_channels == 0 || am->in_matrix_channels == 0) {
567
am->out_matrix_channels = 0;
568
am->in_matrix_channels = 0;
569
return;
570
}
571
572
/* skip input channels that contribute fully only to the corresponding
573
output channel */
574
for (i = 0; i < FFMIN(am->in_channels, am->out_channels); i++) {
575
int skip = 1;
576
577
for (o = 0; o < am->out_channels; o++) {
578
int i0;
579
if ((o != i && matrix[o * stride + i] != 0.0) ||
580
(o == i && matrix[o * stride + i] != 1.0)) {
581
skip = 0;
582
break;
583
}
584
/* if the input contributes fully to the output, also check that no
585
other inputs contribute to this output */
586
if (o == i) {
587
for (i0 = 0; i0 < am->in_channels; i0++) {
588
if (i0 != i && matrix[o * stride + i0] != 0.0) {
589
skip = 0;
590
break;
591
}
592
}
593
}
594
}
595
if (skip) {
596
am->input_skip[i] = 1;
597
am->in_matrix_channels--;
598
}
599
}
600
/* skip input channels that do not contribute to any output channel */
601
for (; i < am->in_channels; i++) {
602
int contrib = 0;
603
604
for (o = 0; o < am->out_channels; o++) {
605
if (matrix[o * stride + i] != 0.0) {
606
contrib = 1;
607
break;
608
}
609
}
610
if (!contrib) {
611
am->input_skip[i] = 1;
612
am->in_matrix_channels--;
613
}
614
}
615
if (am->in_matrix_channels == 0) {
616
am->out_matrix_channels = 0;
617
return;
618
}
619
620
/* skip output channels that only get full contribution from the
621
corresponding input channel */
622
for (o = 0; o < FFMIN(am->in_channels, am->out_channels); o++) {
623
int skip = 1;
624
int o0;
625
626
for (i = 0; i < am->in_channels; i++) {
627
if ((o != i && matrix[o * stride + i] != 0.0) ||
628
(o == i && matrix[o * stride + i] != 1.0)) {
629
skip = 0;
630
break;
631
}
632
}
633
/* check if the corresponding input channel makes a contribution to
634
any other output channel */
635
i = o;
636
for (o0 = 0; o0 < am->out_channels; o0++) {
637
if (o0 != i && matrix[o0 * stride + i] != 0.0) {
638
skip = 0;
639
break;
640
}
641
}
642
if (skip) {
643
am->output_skip[o] = 1;
644
am->out_matrix_channels--;
645
}
646
}
647
if (am->out_matrix_channels == 0) {
648
am->in_matrix_channels = 0;
649
return;
650
}
651
}
652
653
int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
654
{
655
int i, o, i0, o0, ret;
656
char in_layout_name[128];
657
char out_layout_name[128];
658
659
if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
660
am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
661
av_log(am->avr, AV_LOG_ERROR, "Invalid channel counts\n");
662
return AVERROR(EINVAL);
663
}
664
665
if (am->matrix) {
666
av_free(am->matrix[0]);
667
am->matrix = NULL;
668
}
669
670
am->in_matrix_channels = am->in_channels;
671
am->out_matrix_channels = am->out_channels;
672
673
reduce_matrix(am, matrix, stride);
674
675
#define CONVERT_MATRIX(type, expr) \
676
am->matrix_## type[0] = av_mallocz(am->out_matrix_channels * \
677
am->in_matrix_channels * \
678
sizeof(*am->matrix_## type[0])); \
679
if (!am->matrix_## type[0]) \
680
return AVERROR(ENOMEM); \
681
for (o = 0, o0 = 0; o < am->out_channels; o++) { \
682
if (am->output_zero[o] || am->output_skip[o]) \
683
continue; \
684
if (o0 > 0) \
685
am->matrix_## type[o0] = am->matrix_## type[o0 - 1] + \
686
am->in_matrix_channels; \
687
for (i = 0, i0 = 0; i < am->in_channels; i++) { \
688
double v; \
689
if (am->input_skip[i] || am->output_zero[i]) \
690
continue; \
691
v = matrix[o * stride + i]; \
692
am->matrix_## type[o0][i0] = expr; \
693
i0++; \
694
} \
695
o0++; \
696
} \
697
am->matrix = (void **)am->matrix_## type;
698
699
if (am->in_matrix_channels && am->out_matrix_channels) {
700
switch (am->coeff_type) {
701
case AV_MIX_COEFF_TYPE_Q8:
702
CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
703
break;
704
case AV_MIX_COEFF_TYPE_Q15:
705
CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
706
break;
707
case AV_MIX_COEFF_TYPE_FLT:
708
CONVERT_MATRIX(flt, v)
709
break;
710
default:
711
av_log(am->avr, AV_LOG_ERROR, "Invalid mix coeff type\n");
712
return AVERROR(EINVAL);
713
}
714
}
715
716
ret = mix_function_init(am);
717
if (ret < 0)
718
return ret;
719
720
av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
721
am->in_channels, am->in_layout);
722
av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
723
am->out_channels, am->out_layout);
724
av_log(am->avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
725
in_layout_name, out_layout_name);
726
av_log(am->avr, AV_LOG_DEBUG, "matrix size: %d x %d\n",
727
am->in_matrix_channels, am->out_matrix_channels);
728
for (o = 0; o < am->out_channels; o++) {
729
for (i = 0; i < am->in_channels; i++) {
730
if (am->output_zero[o])
731
av_log(am->avr, AV_LOG_DEBUG, " (ZERO)");
732
else if (am->input_skip[i] || am->output_zero[i] || am->output_skip[o])
733
av_log(am->avr, AV_LOG_DEBUG, " (SKIP)");
734
else
735
av_log(am->avr, AV_LOG_DEBUG, " %0.3f ",
736
matrix[o * am->in_channels + i]);
737
}
738
av_log(am->avr, AV_LOG_DEBUG, "\n");
739
}
740
741
return 0;
742
}
743
744