static int query_formats(AVFilterContext *ctx) { ChannelSplitContext *s = ctx->priv; AVFilterChannelLayouts *in_layouts = NULL; int i, ret; if ((ret = ff_set_common_formats(ctx, ff_planar_sample_fmts())) < 0 || (ret = ff_set_common_samplerates(ctx, ff_all_samplerates())) < 0) return ret; if ((ret = ff_add_channel_layout(&in_layouts, s->channel_layout)) < 0 || (ret = ff_channel_layouts_ref(in_layouts, &ctx->inputs[0]->out_channel_layouts)) < 0) return ret; for (i = 0; i < ctx->nb_outputs; i++) { AVFilterChannelLayouts *out_layouts = NULL; uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i); if ((ret = ff_add_channel_layout(&out_layouts, channel)) < 0 || (ret = ff_channel_layouts_ref(out_layouts, &ctx->outputs[i]->in_channel_layouts)) < 0) return ret; } return 0; }
static av_cold int init(AVFilterContext *ctx) { ChannelSplitContext *s = ctx->priv; int nb_channels; int ret = 0, i; if (!(s->channel_layout = av_get_channel_layout(s->channel_layout_str))) { av_log(ctx, AV_LOG_ERROR, "Error parsing channel layout '%s'.\n", s->channel_layout_str); ret = AVERROR(EINVAL); goto fail; } nb_channels = av_get_channel_layout_nb_channels(s->channel_layout); for (i = 0; i < nb_channels; i++) { uint64_t channel = av_channel_layout_extract_channel(s->channel_layout, i); AVFilterPad pad = { 0 }; pad.type = AVMEDIA_TYPE_AUDIO; pad.name = av_get_channel_name(channel); ff_insert_outpad(ctx, i, &pad); } fail: return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *buf) { AVFilterContext *ctx = inlink->dst; int i, ret = 0; for (i = 0; i < ctx->nb_outputs; i++) { AVFrame *buf_out = av_frame_clone(buf); if (!buf_out) { ret = AVERROR(ENOMEM); break; } buf_out->data[0] = buf_out->extended_data[0] = buf_out->extended_data[i]; buf_out->channel_layout = av_channel_layout_extract_channel(buf->channel_layout, i); av_frame_set_channels(buf_out, 1); ret = ff_filter_frame(ctx->outputs[i], buf_out); if (ret < 0) break; } av_frame_free(&buf); return ret; }
static int filter_frame(AVFilterLink *inlink, AVFrame *insamples) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; ShowVolumeContext *s = ctx->priv; int c, i, j, k; double values[VAR_VARS_NB]; if (!s->out || s->out->width != outlink->w || s->out->height != outlink->h) { av_frame_free(&s->out); s->out = ff_get_video_buffer(outlink, outlink->w, outlink->h); if (!s->out) { av_frame_free(&insamples); return AVERROR(ENOMEM); } for (i = 0; i < outlink->h; i++) memset(s->out->data[0] + i * s->out->linesize[0], 0, outlink->w * 4); } s->out->pts = insamples->pts; for (j = 0; j < outlink->h; j++) { uint8_t *dst = s->out->data[0] + j * s->out->linesize[0]; for (k = 0; k < s->w; k++) { dst[k * 4 + 0] = FFMAX(dst[k * 4 + 0] - s->f, 0); dst[k * 4 + 1] = FFMAX(dst[k * 4 + 1] - s->f, 0); dst[k * 4 + 2] = FFMAX(dst[k * 4 + 2] - s->f, 0); dst[k * 4 + 3] = FFMAX(dst[k * 4 + 3] - s->f, 0); } } for (c = 0; c < inlink->channels; c++) { float *src = (float *)insamples->extended_data[c]; float max = 0; int color; for (i = 0; i < insamples->nb_samples; i++) max = FFMAX(max, src[i]); max = av_clipf(max, 0, 1); values[VAR_VOLUME] = 20.0 * log(max) / M_LN10; color = av_expr_eval(s->c_expr, values, NULL); for (j = 0; j < s->h; j++) { uint8_t *dst = s->out->data[0] + (c * s->h + c * s->b + j) * s->out->linesize[0]; for (k = 0; k < s->w * max; k++) AV_WN32A(dst + k * 4, color); } if (s->h >= 8 && s->draw_text) drawtext(s->out, 2, c * (s->h + s->b) + (s->h - 8) / 2, av_get_channel_name(av_channel_layout_extract_channel(insamples->channel_layout, c))); } av_frame_free(&insamples); return ff_filter_frame(outlink, av_frame_clone(s->out)); }
/** * \fn computeChannelLayout * @return */ bool AUDMEncoder_Lavcodec::computeChannelLayout(void) { #define CHANMIX(x,y) case AV_CH_##y: *o=ADM_CH_##x;cprintf(" =>%s\n",ADM_printChannel(*o));o++;break; int channels=wavheader.channels; CHANNEL_TYPE *o=channelMapping; for(int i=0;i<channels;i++) { uint64_t chan=av_channel_layout_extract_channel(CONTEXT->channel_layout,i); cprintf("Channel %s ",av_get_channel_name(chan)) ; switch(chan) { CHANMIX(FRONT_LEFT,FRONT_LEFT) CHANMIX(FRONT_RIGHT,FRONT_RIGHT) CHANMIX(LFE,LOW_FREQUENCY) CHANMIX(FRONT_CENTER,FRONT_CENTER) CHANMIX(REAR_LEFT,BACK_LEFT) CHANMIX(REAR_RIGHT,BACK_RIGHT) default: ADM_warning("Channel no mapped : %s\n"); *o++=ADM_CH_FRONT_LEFT; break; } } return true; }
void from_ffmpeg_layout(uint64_t in_layout, SoundIoChannelLayout *out_layout) { int channel_count = av_get_channel_layout_nb_channels(in_layout); channel_count = min(channel_count, SOUNDIO_MAX_CHANNELS); out_layout->channel_count = channel_count; for (int i = 0; i < channel_count; i += 1) { uint64_t ffmpeg_channel_id = av_channel_layout_extract_channel(in_layout, i); enum SoundIoChannelId channel_id = from_ffmpeg_channel_id(ffmpeg_channel_id); out_layout->channels[i] = channel_id; } soundio_channel_layout_detect_builtin(out_layout); }
av_cold int swr_build_matrix(uint64_t in_ch_layout_param, uint64_t out_ch_layout_param, double center_mix_level, double surround_mix_level, double lfe_mix_level, double maxval, double rematrix_volume, double *matrix_param, int stride, enum AVMatrixEncoding matrix_encoding, void *log_context) { int i, j, out_i; double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; int64_t unaccounted, in_ch_layout, out_ch_layout; double maxcoef=0; char buf[128]; in_ch_layout = clean_layout(log_context, in_ch_layout_param); out_ch_layout = clean_layout(log_context, out_ch_layout_param); if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) out_ch_layout = AV_CH_LAYOUT_STEREO; if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) in_ch_layout = AV_CH_LAYOUT_STEREO; if(!sane_layout(in_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, in_ch_layout_param); av_log(log_context, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } if(!sane_layout(out_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, out_ch_layout_param); av_log(log_context, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){ if(in_ch_layout & out_ch_layout & (1ULL<<i)) matrix[i][i]= 1.0; } unaccounted= in_ch_layout & ~out_ch_layout; //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ if(in_ch_layout & AV_CH_LAYOUT_STEREO) { matrix[ FRONT_LEFT][FRONT_CENTER]+= center_mix_level; matrix[FRONT_RIGHT][FRONT_CENTER]+= center_mix_level; } else { matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; } }else av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; if(in_ch_layout & AV_CH_FRONT_CENTER) matrix[FRONT_CENTER][ FRONT_CENTER] = center_mix_level*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ if(out_ch_layout & AV_CH_BACK_LEFT){ matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || matrix_encoding == AV_MATRIX_ENCODING_DPLII) { if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level * M_SQRT1_2; } else { matrix[FRONT_LEFT ][BACK_CENTER] -= surround_mix_level; matrix[FRONT_RIGHT][BACK_CENTER] += surround_mix_level; } } else { matrix[ FRONT_LEFT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_CENTER]+= surround_mix_level * M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ if(in_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][BACK_LEFT ] -= surround_mix_level * SQRT3_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level * SQRT3_2; } else { matrix[ FRONT_LEFT][ BACK_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][BACK_RIGHT] += surround_mix_level; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_LEFT ]+= surround_mix_level*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= surround_mix_level*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_SIDE_LEFT){ if(out_ch_layout & AV_CH_BACK_LEFT){ /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ if (in_ch_layout & AV_CH_BACK_LEFT) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } }else if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= surround_mix_level * SQRT3_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += surround_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level * SQRT3_2; } else { matrix[ FRONT_LEFT][ SIDE_LEFT] += surround_mix_level; matrix[FRONT_RIGHT][SIDE_RIGHT] += surround_mix_level; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][SIDE_LEFT ]+= surround_mix_level * M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= surround_mix_level * M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ if(out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else av_assert0(0); } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { if (out_ch_layout & AV_CH_FRONT_CENTER) { matrix[FRONT_CENTER][LOW_FREQUENCY] += lfe_mix_level; } else if (out_ch_layout & AV_CH_FRONT_LEFT) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += lfe_mix_level * M_SQRT1_2; } else av_assert0(0); } for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; if((out_ch_layout & (1ULL<<i)) == 0) continue; for(j=0; j<64; j++){ if((in_ch_layout & (1ULL<<j)) == 0) continue; if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) matrix_param[stride*out_i + in_i] = matrix[i][j]; else matrix_param[stride*out_i + in_i] = i == j && (in_ch_layout & out_ch_layout & (1ULL<<i)); sum += fabs(matrix_param[stride*out_i + in_i]); in_i++; } maxcoef= FFMAX(maxcoef, sum); out_i++; } if(rematrix_volume < 0) maxcoef = -rematrix_volume; if(maxcoef > maxval || rematrix_volume < 0){ maxcoef /= maxval; for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ matrix_param[stride*i + j] /= maxcoef; } } if(rematrix_volume > 0){ for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ matrix_param[stride*i + j] *= rematrix_volume; } } av_log(log_context, AV_LOG_DEBUG, "Matrix coefficients:\n"); for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){ const char *c = av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i)); av_log(log_context, AV_LOG_DEBUG, "%s: ", c ? c : "?"); for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){ c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j)); av_log(log_context, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", matrix_param[stride*i + j]); } av_log(log_context, AV_LOG_DEBUG, "\n"); } return 0; }
av_cold static int auto_matrix(SwrContext *s) { int i, j, out_i; double matrix[NUM_NAMED_CHANNELS][NUM_NAMED_CHANNELS]={{0}}; int64_t unaccounted, in_ch_layout, out_ch_layout; double maxcoef=0; char buf[128]; const int matrix_encoding = s->matrix_encoding; float maxval; in_ch_layout = clean_layout(s, s->in_ch_layout); out_ch_layout = clean_layout(s, s->out_ch_layout); if( out_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (in_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) out_ch_layout = AV_CH_LAYOUT_STEREO; if( in_ch_layout == AV_CH_LAYOUT_STEREO_DOWNMIX && (out_ch_layout & AV_CH_LAYOUT_STEREO_DOWNMIX) == 0 ) in_ch_layout = AV_CH_LAYOUT_STEREO; if(!sane_layout(in_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, s->in_ch_layout); av_log(s, AV_LOG_ERROR, "Input channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } if(!sane_layout(out_ch_layout)){ av_get_channel_layout_string(buf, sizeof(buf), -1, s->out_ch_layout); av_log(s, AV_LOG_ERROR, "Output channel layout '%s' is not supported\n", buf); return AVERROR(EINVAL); } memset(s->matrix, 0, sizeof(s->matrix)); for(i=0; i<FF_ARRAY_ELEMS(matrix); i++){ if(in_ch_layout & out_ch_layout & (1ULL<<i)) matrix[i][i]= 1.0; } unaccounted= in_ch_layout & ~out_ch_layout; //FIXME implement dolby surround //FIXME implement full ac3 if(unaccounted & AV_CH_FRONT_CENTER){ if((out_ch_layout & AV_CH_LAYOUT_STEREO) == AV_CH_LAYOUT_STEREO){ if(in_ch_layout & AV_CH_LAYOUT_STEREO) { matrix[ FRONT_LEFT][FRONT_CENTER]+= s->clev; matrix[FRONT_RIGHT][FRONT_CENTER]+= s->clev; } else { matrix[ FRONT_LEFT][FRONT_CENTER]+= M_SQRT1_2; matrix[FRONT_RIGHT][FRONT_CENTER]+= M_SQRT1_2; } }else av_assert0(0); } if(unaccounted & AV_CH_LAYOUT_STEREO){ if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[FRONT_CENTER][ FRONT_LEFT]+= M_SQRT1_2; matrix[FRONT_CENTER][FRONT_RIGHT]+= M_SQRT1_2; if(in_ch_layout & AV_CH_FRONT_CENTER) matrix[FRONT_CENTER][ FRONT_CENTER] = s->clev*sqrt(2); }else av_assert0(0); } if(unaccounted & AV_CH_BACK_CENTER){ if(out_ch_layout & AV_CH_BACK_LEFT){ matrix[ BACK_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[BACK_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][BACK_CENTER]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_CENTER]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY || matrix_encoding == AV_MATRIX_ENCODING_DPLII) { if (unaccounted & (AV_CH_BACK_LEFT | AV_CH_SIDE_LEFT)) { matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER] += s->slev * M_SQRT1_2; } else { matrix[FRONT_LEFT ][BACK_CENTER] -= s->slev; matrix[FRONT_RIGHT][BACK_CENTER] += s->slev; } } else { matrix[ FRONT_LEFT][BACK_CENTER]+= s->slev*M_SQRT1_2; matrix[FRONT_RIGHT][BACK_CENTER]+= s->slev*M_SQRT1_2; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_CENTER]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_BACK_LEFT){ if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ BACK_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][BACK_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_SIDE_LEFT){ if(in_ch_layout & AV_CH_SIDE_LEFT){ matrix[ SIDE_LEFT][ BACK_LEFT]+= M_SQRT1_2; matrix[SIDE_RIGHT][BACK_RIGHT]+= M_SQRT1_2; }else{ matrix[ SIDE_LEFT][ BACK_LEFT]+= 1.0; matrix[SIDE_RIGHT][BACK_RIGHT]+= 1.0; } }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * M_SQRT1_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][BACK_LEFT ] -= s->slev * SQRT3_2; matrix[FRONT_LEFT ][BACK_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev * SQRT3_2; } else { matrix[ FRONT_LEFT][ BACK_LEFT] += s->slev; matrix[FRONT_RIGHT][BACK_RIGHT] += s->slev; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][BACK_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][BACK_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_SIDE_LEFT){ if(out_ch_layout & AV_CH_BACK_LEFT){ /* if back channels do not exist in the input, just copy side channels to back channels, otherwise mix side into back */ if (in_ch_layout & AV_CH_BACK_LEFT) { matrix[BACK_LEFT ][SIDE_LEFT ] += M_SQRT1_2; matrix[BACK_RIGHT][SIDE_RIGHT] += M_SQRT1_2; } else { matrix[BACK_LEFT ][SIDE_LEFT ] += 1.0; matrix[BACK_RIGHT][SIDE_RIGHT] += 1.0; } }else if(out_ch_layout & AV_CH_BACK_CENTER){ matrix[BACK_CENTER][ SIDE_LEFT]+= M_SQRT1_2; matrix[BACK_CENTER][SIDE_RIGHT]+= M_SQRT1_2; }else if(out_ch_layout & AV_CH_FRONT_LEFT){ if (matrix_encoding == AV_MATRIX_ENCODING_DOLBY) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * M_SQRT1_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * M_SQRT1_2; } else if (matrix_encoding == AV_MATRIX_ENCODING_DPLII) { matrix[FRONT_LEFT ][SIDE_LEFT ] -= s->slev * SQRT3_2; matrix[FRONT_LEFT ][SIDE_RIGHT] -= s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_LEFT ] += s->slev * M_SQRT1_2; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev * SQRT3_2; } else { matrix[ FRONT_LEFT][ SIDE_LEFT] += s->slev; matrix[FRONT_RIGHT][SIDE_RIGHT] += s->slev; } }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][SIDE_LEFT ]+= s->slev*M_SQRT1_2; matrix[ FRONT_CENTER][SIDE_RIGHT]+= s->slev*M_SQRT1_2; }else av_assert0(0); } if(unaccounted & AV_CH_FRONT_LEFT_OF_CENTER){ if(out_ch_layout & AV_CH_FRONT_LEFT){ matrix[ FRONT_LEFT][ FRONT_LEFT_OF_CENTER]+= 1.0; matrix[FRONT_RIGHT][FRONT_RIGHT_OF_CENTER]+= 1.0; }else if(out_ch_layout & AV_CH_FRONT_CENTER){ matrix[ FRONT_CENTER][ FRONT_LEFT_OF_CENTER]+= M_SQRT1_2; matrix[ FRONT_CENTER][FRONT_RIGHT_OF_CENTER]+= M_SQRT1_2; }else av_assert0(0); } /* mix LFE into front left/right or center */ if (unaccounted & AV_CH_LOW_FREQUENCY) { if (out_ch_layout & AV_CH_FRONT_CENTER) { matrix[FRONT_CENTER][LOW_FREQUENCY] += s->lfe_mix_level; } else if (out_ch_layout & AV_CH_FRONT_LEFT) { matrix[FRONT_LEFT ][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; matrix[FRONT_RIGHT][LOW_FREQUENCY] += s->lfe_mix_level * M_SQRT1_2; } else av_assert0(0); } for(out_i=i=0; i<64; i++){ double sum=0; int in_i=0; if((out_ch_layout & (1ULL<<i)) == 0) continue; for(j=0; j<64; j++){ if((in_ch_layout & (1ULL<<j)) == 0) continue; if (i < FF_ARRAY_ELEMS(matrix) && j < FF_ARRAY_ELEMS(matrix[0])) s->matrix[out_i][in_i]= matrix[i][j]; else s->matrix[out_i][in_i]= i == j && (in_ch_layout & out_ch_layout & (1ULL<<i)); sum += fabs(s->matrix[out_i][in_i]); in_i++; } maxcoef= FFMAX(maxcoef, sum); out_i++; } if(s->rematrix_volume < 0) maxcoef = -s->rematrix_volume; if (s->rematrix_maxval > 0) { maxval = s->rematrix_maxval; } else if ( av_get_packed_sample_fmt(s->out_sample_fmt) < AV_SAMPLE_FMT_FLT || av_get_packed_sample_fmt(s->int_sample_fmt) < AV_SAMPLE_FMT_FLT) { maxval = 1.0; } else maxval = INT_MAX; if(maxcoef > maxval || s->rematrix_volume < 0){ maxcoef /= maxval; for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] /= maxcoef; } } if(s->rematrix_volume > 0){ for(i=0; i<SWR_CH_MAX; i++) for(j=0; j<SWR_CH_MAX; j++){ s->matrix[i][j] *= s->rematrix_volume; } } av_log(s, AV_LOG_DEBUG, "Matrix coefficients:\n"); for(i=0; i<av_get_channel_layout_nb_channels(out_ch_layout); i++){ const char *c = av_get_channel_name(av_channel_layout_extract_channel(out_ch_layout, i)); av_log(s, AV_LOG_DEBUG, "%s: ", c ? c : "?"); for(j=0; j<av_get_channel_layout_nb_channels(in_ch_layout); j++){ c = av_get_channel_name(av_channel_layout_extract_channel(in_ch_layout, j)); av_log(s, AV_LOG_DEBUG, "%s:%f ", c ? c : "?", s->matrix[i][j]); } av_log(s, AV_LOG_DEBUG, "\n"); } return 0; }