1/* 2 * Copyright (c) 2012 Justin Ruggles <justin.ruggles@gmail.com> 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 31static const char * const coeff_type_names[] = { "q8", "q15", "flt" }; 32 33struct 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 61void 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) \ 102static 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 119MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum) 120MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum))) 121MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15)) 122MIX_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 126static 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 148static 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 170static 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 192static 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 225static 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 259static 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 285static 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 341AudioMix *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 404error: 405 av_free(am); 406 return NULL; 407} 408 409void 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 428int 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 483int 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 530static 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 653int 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