annotate ffmpeg/libavresample/audio_mix.c @ 13:844d341cf643 tip

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