00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <stdint.h>
00022
00023 #include "libavutil/common.h"
00024 #include "libavutil/libm.h"
00025 #include "libavutil/samplefmt.h"
00026 #include "avresample.h"
00027 #include "internal.h"
00028 #include "audio_data.h"
00029 #include "audio_mix.h"
00030
00031 static const char *coeff_type_names[] = { "q8", "q15", "flt" };
00032
00033 struct AudioMix {
00034 AVAudioResampleContext *avr;
00035 enum AVSampleFormat fmt;
00036 enum AVMixCoeffType coeff_type;
00037 uint64_t in_layout;
00038 uint64_t out_layout;
00039 int in_channels;
00040 int out_channels;
00041
00042 int ptr_align;
00043 int samples_align;
00044 int has_optimized_func;
00045 const char *func_descr;
00046 const char *func_descr_generic;
00047 mix_func *mix;
00048 mix_func *mix_generic;
00049
00050 int16_t *matrix_q8[AVRESAMPLE_MAX_CHANNELS];
00051 int32_t *matrix_q15[AVRESAMPLE_MAX_CHANNELS];
00052 float *matrix_flt[AVRESAMPLE_MAX_CHANNELS];
00053 void **matrix;
00054 };
00055
00056 void ff_audio_mix_set_func(AudioMix *am, enum AVSampleFormat fmt,
00057 enum AVMixCoeffType coeff_type, int in_channels,
00058 int out_channels, int ptr_align, int samples_align,
00059 const char *descr, void *mix_func)
00060 {
00061 if (fmt == am->fmt && coeff_type == am->coeff_type &&
00062 ( in_channels == am->in_channels || in_channels == 0) &&
00063 (out_channels == am->out_channels || out_channels == 0)) {
00064 char chan_str[16];
00065 am->mix = mix_func;
00066 am->func_descr = descr;
00067 am->ptr_align = ptr_align;
00068 am->samples_align = samples_align;
00069 if (ptr_align == 1 && samples_align == 1) {
00070 am->mix_generic = mix_func;
00071 am->func_descr_generic = descr;
00072 } else {
00073 am->has_optimized_func = 1;
00074 }
00075 if (in_channels) {
00076 if (out_channels)
00077 snprintf(chan_str, sizeof(chan_str), "[%d to %d] ",
00078 in_channels, out_channels);
00079 else
00080 snprintf(chan_str, sizeof(chan_str), "[%d to any] ",
00081 in_channels);
00082 } else if (out_channels) {
00083 snprintf(chan_str, sizeof(chan_str), "[any to %d] ",
00084 out_channels);
00085 }
00086 av_log(am->avr, AV_LOG_DEBUG, "audio_mix: found function: [fmt=%s] "
00087 "[c=%s] %s(%s)\n", av_get_sample_fmt_name(fmt),
00088 coeff_type_names[coeff_type],
00089 (in_channels || out_channels) ? chan_str : "", descr);
00090 }
00091 }
00092
00093 #define MIX_FUNC_NAME(fmt, cfmt) mix_any_ ## fmt ##_## cfmt ##_c
00094
00095 #define MIX_FUNC_GENERIC(fmt, cfmt, stype, ctype, sumtype, expr) \
00096 static void MIX_FUNC_NAME(fmt, cfmt)(stype **samples, ctype **matrix, \
00097 int len, int out_ch, int in_ch) \
00098 { \
00099 int i, in, out; \
00100 stype temp[AVRESAMPLE_MAX_CHANNELS]; \
00101 for (i = 0; i < len; i++) { \
00102 for (out = 0; out < out_ch; out++) { \
00103 sumtype sum = 0; \
00104 for (in = 0; in < in_ch; in++) \
00105 sum += samples[in][i] * matrix[out][in]; \
00106 temp[out] = expr; \
00107 } \
00108 for (out = 0; out < out_ch; out++) \
00109 samples[out][i] = temp[out]; \
00110 } \
00111 }
00112
00113 MIX_FUNC_GENERIC(FLTP, FLT, float, float, float, sum)
00114 MIX_FUNC_GENERIC(S16P, FLT, int16_t, float, float, av_clip_int16(lrintf(sum)))
00115 MIX_FUNC_GENERIC(S16P, Q15, int16_t, int32_t, int64_t, av_clip_int16(sum >> 15))
00116 MIX_FUNC_GENERIC(S16P, Q8, int16_t, int16_t, int32_t, av_clip_int16(sum >> 8))
00117
00118
00119
00120 static void mix_2_to_1_fltp_flt_c(float **samples, float **matrix, int len,
00121 int out_ch, int in_ch)
00122 {
00123 float *src0 = samples[0];
00124 float *src1 = samples[1];
00125 float *dst = src0;
00126 float m0 = matrix[0][0];
00127 float m1 = matrix[0][1];
00128
00129 while (len > 4) {
00130 *dst++ = *src0++ * m0 + *src1++ * m1;
00131 *dst++ = *src0++ * m0 + *src1++ * m1;
00132 *dst++ = *src0++ * m0 + *src1++ * m1;
00133 *dst++ = *src0++ * m0 + *src1++ * m1;
00134 len -= 4;
00135 }
00136 while (len > 0) {
00137 *dst++ = *src0++ * m0 + *src1++ * m1;
00138 len--;
00139 }
00140 }
00141
00142 static void mix_2_to_1_s16p_flt_c(int16_t **samples, float **matrix, int len,
00143 int out_ch, int in_ch)
00144 {
00145 int16_t *src0 = samples[0];
00146 int16_t *src1 = samples[1];
00147 int16_t *dst = src0;
00148 float m0 = matrix[0][0];
00149 float m1 = matrix[0][1];
00150
00151 while (len > 4) {
00152 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
00153 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
00154 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
00155 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
00156 len -= 4;
00157 }
00158 while (len > 0) {
00159 *dst++ = av_clip_int16(lrintf(*src0++ * m0 + *src1++ * m1));
00160 len--;
00161 }
00162 }
00163
00164 static void mix_2_to_1_s16p_q8_c(int16_t **samples, int16_t **matrix, int len,
00165 int out_ch, int in_ch)
00166 {
00167 int16_t *src0 = samples[0];
00168 int16_t *src1 = samples[1];
00169 int16_t *dst = src0;
00170 int16_t m0 = matrix[0][0];
00171 int16_t m1 = matrix[0][1];
00172
00173 while (len > 4) {
00174 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
00175 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
00176 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
00177 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
00178 len -= 4;
00179 }
00180 while (len > 0) {
00181 *dst++ = (*src0++ * m0 + *src1++ * m1) >> 8;
00182 len--;
00183 }
00184 }
00185
00186 static void mix_1_to_2_fltp_flt_c(float **samples, float **matrix, int len,
00187 int out_ch, int in_ch)
00188 {
00189 float v;
00190 float *dst0 = samples[0];
00191 float *dst1 = samples[1];
00192 float *src = dst0;
00193 float m0 = matrix[0][0];
00194 float m1 = matrix[1][0];
00195
00196 while (len > 4) {
00197 v = *src++;
00198 *dst0++ = v * m1;
00199 *dst1++ = v * m0;
00200 v = *src++;
00201 *dst0++ = v * m1;
00202 *dst1++ = v * m0;
00203 v = *src++;
00204 *dst0++ = v * m1;
00205 *dst1++ = v * m0;
00206 v = *src++;
00207 *dst0++ = v * m1;
00208 *dst1++ = v * m0;
00209 len -= 4;
00210 }
00211 while (len > 0) {
00212 v = *src++;
00213 *dst0++ = v * m1;
00214 *dst1++ = v * m0;
00215 len--;
00216 }
00217 }
00218
00219 static void mix_6_to_2_fltp_flt_c(float **samples, float **matrix, int len,
00220 int out_ch, int in_ch)
00221 {
00222 float v0, v1;
00223 float *src0 = samples[0];
00224 float *src1 = samples[1];
00225 float *src2 = samples[2];
00226 float *src3 = samples[3];
00227 float *src4 = samples[4];
00228 float *src5 = samples[5];
00229 float *dst0 = src0;
00230 float *dst1 = src1;
00231 float *m0 = matrix[0];
00232 float *m1 = matrix[1];
00233
00234 while (len > 0) {
00235 v0 = *src0++;
00236 v1 = *src1++;
00237 *dst0++ = v0 * m0[0] +
00238 v1 * m0[1] +
00239 *src2 * m0[2] +
00240 *src3 * m0[3] +
00241 *src4 * m0[4] +
00242 *src5 * m0[5];
00243 *dst1++ = v0 * m1[0] +
00244 v1 * m1[1] +
00245 *src2++ * m1[2] +
00246 *src3++ * m1[3] +
00247 *src4++ * m1[4] +
00248 *src5++ * m1[5];
00249 len--;
00250 }
00251 }
00252
00253 static void mix_2_to_6_fltp_flt_c(float **samples, float **matrix, int len,
00254 int out_ch, int in_ch)
00255 {
00256 float v0, v1;
00257 float *dst0 = samples[0];
00258 float *dst1 = samples[1];
00259 float *dst2 = samples[2];
00260 float *dst3 = samples[3];
00261 float *dst4 = samples[4];
00262 float *dst5 = samples[5];
00263 float *src0 = dst0;
00264 float *src1 = dst1;
00265
00266 while (len > 0) {
00267 v0 = *src0++;
00268 v1 = *src1++;
00269 *dst0++ = v0 * matrix[0][0] + v1 * matrix[0][1];
00270 *dst1++ = v0 * matrix[1][0] + v1 * matrix[1][1];
00271 *dst2++ = v0 * matrix[2][0] + v1 * matrix[2][1];
00272 *dst3++ = v0 * matrix[3][0] + v1 * matrix[3][1];
00273 *dst4++ = v0 * matrix[4][0] + v1 * matrix[4][1];
00274 *dst5++ = v0 * matrix[5][0] + v1 * matrix[5][1];
00275 len--;
00276 }
00277 }
00278
00279 static int mix_function_init(AudioMix *am)
00280 {
00281
00282
00283 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
00284 0, 0, 1, 1, "C", MIX_FUNC_NAME(FLTP, FLT));
00285
00286 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
00287 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, FLT));
00288
00289 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q15,
00290 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q15));
00291
00292 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
00293 0, 0, 1, 1, "C", MIX_FUNC_NAME(S16P, Q8));
00294
00295
00296
00297 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
00298 2, 1, 1, 1, "C", mix_2_to_1_fltp_flt_c);
00299
00300 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_FLT,
00301 2, 1, 1, 1, "C", mix_2_to_1_s16p_flt_c);
00302
00303 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_S16P, AV_MIX_COEFF_TYPE_Q8,
00304 2, 1, 1, 1, "C", mix_2_to_1_s16p_q8_c);
00305
00306 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
00307 1, 2, 1, 1, "C", mix_1_to_2_fltp_flt_c);
00308
00309 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
00310 6, 2, 1, 1, "C", mix_6_to_2_fltp_flt_c);
00311
00312 ff_audio_mix_set_func(am, AV_SAMPLE_FMT_FLTP, AV_MIX_COEFF_TYPE_FLT,
00313 2, 6, 1, 1, "C", mix_2_to_6_fltp_flt_c);
00314
00315 if (ARCH_X86)
00316 ff_audio_mix_init_x86(am);
00317
00318 if (!am->mix) {
00319 av_log(am->avr, AV_LOG_ERROR, "audio_mix: NO FUNCTION FOUND: [fmt=%s] "
00320 "[c=%s] [%d to %d]\n", av_get_sample_fmt_name(am->fmt),
00321 coeff_type_names[am->coeff_type], am->in_channels,
00322 am->out_channels);
00323 return AVERROR_PATCHWELCOME;
00324 }
00325 return 0;
00326 }
00327
00328 AudioMix *ff_audio_mix_alloc(AVAudioResampleContext *avr)
00329 {
00330 AudioMix *am;
00331 int ret;
00332
00333 am = av_mallocz(sizeof(*am));
00334 if (!am)
00335 return NULL;
00336 am->avr = avr;
00337
00338 if (avr->internal_sample_fmt != AV_SAMPLE_FMT_S16P &&
00339 avr->internal_sample_fmt != AV_SAMPLE_FMT_FLTP) {
00340 av_log(avr, AV_LOG_ERROR, "Unsupported internal format for "
00341 "mixing: %s\n",
00342 av_get_sample_fmt_name(avr->internal_sample_fmt));
00343 goto error;
00344 }
00345
00346 am->fmt = avr->internal_sample_fmt;
00347 am->coeff_type = avr->mix_coeff_type;
00348 am->in_layout = avr->in_channel_layout;
00349 am->out_layout = avr->out_channel_layout;
00350 am->in_channels = avr->in_channels;
00351 am->out_channels = avr->out_channels;
00352
00353
00354 if (avr->mix_matrix) {
00355 ret = ff_audio_mix_set_matrix(am, avr->mix_matrix, avr->in_channels);
00356 if (ret < 0)
00357 goto error;
00358 av_freep(&avr->mix_matrix);
00359 } else {
00360 int i, j;
00361 char in_layout_name[128];
00362 char out_layout_name[128];
00363 double *matrix_dbl = av_mallocz(avr->out_channels * avr->in_channels *
00364 sizeof(*matrix_dbl));
00365 if (!matrix_dbl)
00366 goto error;
00367
00368 ret = avresample_build_matrix(avr->in_channel_layout,
00369 avr->out_channel_layout,
00370 avr->center_mix_level,
00371 avr->surround_mix_level,
00372 avr->lfe_mix_level,
00373 avr->normalize_mix_level,
00374 matrix_dbl,
00375 avr->in_channels,
00376 avr->matrix_encoding);
00377 if (ret < 0) {
00378 av_free(matrix_dbl);
00379 goto error;
00380 }
00381
00382 av_get_channel_layout_string(in_layout_name, sizeof(in_layout_name),
00383 avr->in_channels, avr->in_channel_layout);
00384 av_get_channel_layout_string(out_layout_name, sizeof(out_layout_name),
00385 avr->out_channels, avr->out_channel_layout);
00386 av_log(avr, AV_LOG_DEBUG, "audio_mix: %s to %s\n",
00387 in_layout_name, out_layout_name);
00388 for (i = 0; i < avr->out_channels; i++) {
00389 for (j = 0; j < avr->in_channels; j++) {
00390 av_log(avr, AV_LOG_DEBUG, " %0.3f ",
00391 matrix_dbl[i * avr->in_channels + j]);
00392 }
00393 av_log(avr, AV_LOG_DEBUG, "\n");
00394 }
00395
00396 ret = ff_audio_mix_set_matrix(am, matrix_dbl, avr->in_channels);
00397 if (ret < 0) {
00398 av_free(matrix_dbl);
00399 goto error;
00400 }
00401 av_free(matrix_dbl);
00402 }
00403
00404 ret = mix_function_init(am);
00405 if (ret < 0)
00406 goto error;
00407
00408 return am;
00409
00410 error:
00411 av_free(am);
00412 return NULL;
00413 }
00414
00415 void ff_audio_mix_free(AudioMix **am_p)
00416 {
00417 AudioMix *am;
00418
00419 if (!*am_p)
00420 return;
00421 am = *am_p;
00422
00423 if (am->matrix) {
00424 av_free(am->matrix[0]);
00425 am->matrix = NULL;
00426 }
00427 memset(am->matrix_q8, 0, sizeof(am->matrix_q8 ));
00428 memset(am->matrix_q15, 0, sizeof(am->matrix_q15));
00429 memset(am->matrix_flt, 0, sizeof(am->matrix_flt));
00430
00431 av_freep(am_p);
00432 }
00433
00434 int ff_audio_mix(AudioMix *am, AudioData *src)
00435 {
00436 int use_generic = 1;
00437 int len = src->nb_samples;
00438
00439
00440
00441 if (am->has_optimized_func) {
00442 int aligned_len = FFALIGN(len, am->samples_align);
00443 if (!(src->ptr_align % am->ptr_align) &&
00444 src->samples_align >= aligned_len) {
00445 len = aligned_len;
00446 use_generic = 0;
00447 }
00448 }
00449 av_dlog(am->avr, "audio_mix: %d samples - %d to %d channels (%s)\n",
00450 src->nb_samples, am->in_channels, am->out_channels,
00451 use_generic ? am->func_descr_generic : am->func_descr);
00452
00453 if (use_generic)
00454 am->mix_generic(src->data, am->matrix, len, am->out_channels,
00455 am->in_channels);
00456 else
00457 am->mix(src->data, am->matrix, len, am->out_channels, am->in_channels);
00458
00459 ff_audio_data_set_channels(src, am->out_channels);
00460
00461 return 0;
00462 }
00463
00464 int ff_audio_mix_get_matrix(AudioMix *am, double *matrix, int stride)
00465 {
00466 int i, o;
00467
00468 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
00469 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
00470 av_log(am, AV_LOG_ERROR, "Invalid channel counts\n");
00471 return AVERROR(EINVAL);
00472 }
00473
00474 #define GET_MATRIX_CONVERT(suffix, scale) \
00475 if (!am->matrix_ ## suffix[0]) { \
00476 av_log(am, AV_LOG_ERROR, "matrix is not set\n"); \
00477 return AVERROR(EINVAL); \
00478 } \
00479 for (o = 0; o < am->out_channels; o++) \
00480 for (i = 0; i < am->in_channels; i++) \
00481 matrix[o * stride + i] = am->matrix_ ## suffix[o][i] * (scale);
00482
00483 switch (am->coeff_type) {
00484 case AV_MIX_COEFF_TYPE_Q8:
00485 GET_MATRIX_CONVERT(q8, 1.0 / 256.0);
00486 break;
00487 case AV_MIX_COEFF_TYPE_Q15:
00488 GET_MATRIX_CONVERT(q15, 1.0 / 32768.0);
00489 break;
00490 case AV_MIX_COEFF_TYPE_FLT:
00491 GET_MATRIX_CONVERT(flt, 1.0);
00492 break;
00493 default:
00494 av_log(am, AV_LOG_ERROR, "Invalid mix coeff type\n");
00495 return AVERROR(EINVAL);
00496 }
00497
00498 return 0;
00499 }
00500
00501 int ff_audio_mix_set_matrix(AudioMix *am, const double *matrix, int stride)
00502 {
00503 int i, o;
00504
00505 if ( am->in_channels <= 0 || am->in_channels > AVRESAMPLE_MAX_CHANNELS ||
00506 am->out_channels <= 0 || am->out_channels > AVRESAMPLE_MAX_CHANNELS) {
00507 av_log(am, AV_LOG_ERROR, "Invalid channel counts\n");
00508 return AVERROR(EINVAL);
00509 }
00510
00511 if (am->matrix) {
00512 av_free(am->matrix[0]);
00513 am->matrix = NULL;
00514 }
00515
00516 #define CONVERT_MATRIX(type, expr) \
00517 am->matrix_## type[0] = av_mallocz(am->out_channels * am->in_channels * \
00518 sizeof(*am->matrix_## type[0])); \
00519 if (!am->matrix_## type[0]) \
00520 return AVERROR(ENOMEM); \
00521 for (o = 0; o < am->out_channels; o++) { \
00522 if (o > 0) \
00523 am->matrix_## type[o] = am->matrix_## type[o - 1] + \
00524 am->in_channels; \
00525 for (i = 0; i < am->in_channels; i++) { \
00526 double v = matrix[o * stride + i]; \
00527 am->matrix_## type[o][i] = expr; \
00528 } \
00529 } \
00530 am->matrix = (void **)am->matrix_## type;
00531
00532 switch (am->coeff_type) {
00533 case AV_MIX_COEFF_TYPE_Q8:
00534 CONVERT_MATRIX(q8, av_clip_int16(lrint(256.0 * v)))
00535 break;
00536 case AV_MIX_COEFF_TYPE_Q15:
00537 CONVERT_MATRIX(q15, av_clipl_int32(llrint(32768.0 * v)))
00538 break;
00539 case AV_MIX_COEFF_TYPE_FLT:
00540 CONVERT_MATRIX(flt, v)
00541 break;
00542 default:
00543 av_log(am, AV_LOG_ERROR, "Invalid mix coeff type\n");
00544 return AVERROR(EINVAL);
00545 }
00546
00547
00548
00549
00550 return 0;
00551 }