avfilter/af_surround: add some more layouts

Signed-off-by: Paul B Mahol <onemda@gmail.com>
This commit is contained in:
Paul B Mahol 2017-11-19 20:20:55 +01:00
parent 460df96904
commit 69cbebbd3d

View File

@ -90,6 +90,15 @@ typedef struct AudioSurroundContext {
float mag_total,
float x, float y,
int n);
void (*upmix_5_0)(AVFilterContext *ctx,
float c_re, float c_im,
float mag_totall, float mag_totalr,
float fl_phase, float fr_phase,
float bl_phase, float br_phase,
float sl_phase, float sr_phase,
float xl, float yl,
float xr, float yr,
int n);
void (*upmix_5_1)(AVFilterContext *ctx,
float c_re, float c_im,
float lfe_re, float lfe_im,
@ -764,6 +773,66 @@ static void upmix_7_1(AVFilterContext *ctx,
dstrs[2 * n + 1] = rs_mag * sinf(r_phase);
}
static void upmix_7_1_5_0_side(AVFilterContext *ctx,
float c_re, float c_im,
float mag_totall, float mag_totalr,
float fl_phase, float fr_phase,
float bl_phase, float br_phase,
float sl_phase, float sr_phase,
float xl, float yl,
float xr, float yr,
int n)
{
float fl_mag, fr_mag, ls_mag, rs_mag, lb_mag, rb_mag;
float *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlb, *dstrb, *dstlfe;
float lfe_mag, c_phase, mag_total = (mag_totall + mag_totalr) * 0.5;
AudioSurroundContext *s = ctx->priv;
dstl = (float *)s->output->extended_data[0];
dstr = (float *)s->output->extended_data[1];
dstc = (float *)s->output->extended_data[2];
dstlfe = (float *)s->output->extended_data[3];
dstlb = (float *)s->output->extended_data[4];
dstrb = (float *)s->output->extended_data[5];
dstls = (float *)s->output->extended_data[6];
dstrs = (float *)s->output->extended_data[7];
c_phase = atan2f(c_im, c_re);
get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total);
fl_mag = sqrtf(.5f * (xl + 1.f)) * ((yl + 1.f) * .5f) * mag_totall;
fr_mag = sqrtf(.5f * (xr + 1.f)) * ((yr + 1.f) * .5f) * mag_totalr;
lb_mag = sqrtf(.5f * (-xl + 1.f)) * ((yl + 1.f) * .5f) * mag_totall;
rb_mag = sqrtf(.5f * (-xr + 1.f)) * ((yr + 1.f) * .5f) * mag_totalr;
ls_mag = sqrtf(1.f - fabsf(xl)) * ((yl + 1.f) * .5f) * mag_totall;
rs_mag = sqrtf(1.f - fabsf(xr)) * ((yr + 1.f) * .5f) * mag_totalr;
dstl[2 * n ] = fl_mag * cosf(fl_phase);
dstl[2 * n + 1] = fl_mag * sinf(fl_phase);
dstr[2 * n ] = fr_mag * cosf(fr_phase);
dstr[2 * n + 1] = fr_mag * sinf(fr_phase);
dstc[2 * n ] = c_re;
dstc[2 * n + 1] = c_im;
dstlfe[2 * n ] = lfe_mag * cosf(c_phase);
dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase);
dstlb[2 * n ] = lb_mag * cosf(bl_phase);
dstlb[2 * n + 1] = lb_mag * sinf(bl_phase);
dstrb[2 * n ] = rb_mag * cosf(br_phase);
dstrb[2 * n + 1] = rb_mag * sinf(br_phase);
dstls[2 * n ] = ls_mag * cosf(sl_phase);
dstls[2 * n + 1] = ls_mag * sinf(sl_phase);
dstrs[2 * n ] = rs_mag * cosf(sr_phase);
dstrs[2 * n + 1] = rs_mag * sinf(sr_phase);
}
static void upmix_7_1_5_1(AVFilterContext *ctx,
float c_re, float c_im,
float lfe_re, float lfe_im,
@ -918,6 +987,118 @@ static void filter_2_1(AVFilterContext *ctx)
}
}
static void filter_5_0_side(AVFilterContext *ctx)
{
AudioSurroundContext *s = ctx->priv;
float *srcl, *srcr, *srcc, *srcsl, *srcsr;
int n;
srcl = (float *)s->input->extended_data[0];
srcr = (float *)s->input->extended_data[1];
srcc = (float *)s->input->extended_data[2];
srcsl = (float *)s->input->extended_data[3];
srcsr = (float *)s->input->extended_data[4];
for (n = 0; n < s->buf_size; n++) {
float fl_re = srcl[2 * n], fr_re = srcr[2 * n];
float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1];
float c_re = srcc[2 * n], c_im = srcc[2 * n + 1];
float sl_re = srcsl[2 * n], sl_im = srcsl[2 * n + 1];
float sr_re = srcsr[2 * n], sr_im = srcsr[2 * n + 1];
float fl_mag = hypotf(fl_re, fl_im);
float fr_mag = hypotf(fr_re, fr_im);
float fl_phase = atan2f(fl_im, fl_re);
float fr_phase = atan2f(fr_im, fr_re);
float sl_mag = hypotf(sl_re, sl_im);
float sr_mag = hypotf(sr_re, sr_im);
float sl_phase = atan2f(sl_im, sl_re);
float sr_phase = atan2f(sr_im, sr_re);
float phase_difl = fabsf(fl_phase - sl_phase);
float phase_difr = fabsf(fr_phase - sr_phase);
float mag_difl = (fl_mag - sl_mag) / (fl_mag + sl_mag);
float mag_difr = (fr_mag - sr_mag) / (fr_mag + sr_mag);
float mag_totall = hypotf(fl_mag, sl_mag);
float mag_totalr = hypotf(fr_mag, sr_mag);
float bl_phase = atan2f(fl_im + sl_im, fl_re + sl_re);
float br_phase = atan2f(fr_im + sr_im, fr_re + sr_re);
float xl, yl;
float xr, yr;
if (phase_difl > M_PI)
phase_difl = 2 * M_PI - phase_difl;
if (phase_difr > M_PI)
phase_difr = 2 * M_PI - phase_difr;
stereo_position(mag_difl, phase_difl, &xl, &yl);
stereo_position(mag_difr, phase_difr, &xr, &yr);
s->upmix_5_0(ctx, c_re, c_im,
mag_totall, mag_totalr,
fl_phase, fr_phase,
bl_phase, br_phase,
sl_phase, sr_phase,
xl, yl, xr, yr, n);
}
}
static void filter_5_1_side(AVFilterContext *ctx)
{
AudioSurroundContext *s = ctx->priv;
float *srcl, *srcr, *srcc, *srclfe, *srcsl, *srcsr;
int n;
srcl = (float *)s->input->extended_data[0];
srcr = (float *)s->input->extended_data[1];
srcc = (float *)s->input->extended_data[2];
srclfe = (float *)s->input->extended_data[3];
srcsl = (float *)s->input->extended_data[4];
srcsr = (float *)s->input->extended_data[5];
for (n = 0; n < s->buf_size; n++) {
float fl_re = srcl[2 * n], fr_re = srcr[2 * n];
float fl_im = srcl[2 * n + 1], fr_im = srcr[2 * n + 1];
float c_re = srcc[2 * n], c_im = srcc[2 * n + 1];
float lfe_re = srclfe[2 * n], lfe_im = srclfe[2 * n + 1];
float sl_re = srcsl[2 * n], sl_im = srcsl[2 * n + 1];
float sr_re = srcsr[2 * n], sr_im = srcsr[2 * n + 1];
float fl_mag = hypotf(fl_re, fl_im);
float fr_mag = hypotf(fr_re, fr_im);
float fl_phase = atan2f(fl_im, fl_re);
float fr_phase = atan2f(fr_im, fr_re);
float sl_mag = hypotf(sl_re, sl_im);
float sr_mag = hypotf(sr_re, sr_im);
float sl_phase = atan2f(sl_im, sl_re);
float sr_phase = atan2f(sr_im, sr_re);
float phase_difl = fabsf(fl_phase - sl_phase);
float phase_difr = fabsf(fr_phase - sr_phase);
float mag_difl = (fl_mag - sl_mag) / (fl_mag + sl_mag);
float mag_difr = (fr_mag - sr_mag) / (fr_mag + sr_mag);
float mag_totall = hypotf(fl_mag, sl_mag);
float mag_totalr = hypotf(fr_mag, sr_mag);
float bl_phase = atan2f(fl_im + sl_im, fl_re + sl_re);
float br_phase = atan2f(fr_im + sr_im, fr_re + sr_re);
float xl, yl;
float xr, yr;
if (phase_difl > M_PI)
phase_difl = 2 * M_PI - phase_difl;
if (phase_difr > M_PI)
phase_difr = 2 * M_PI - phase_difr;
stereo_position(mag_difl, phase_difl, &xl, &yl);
stereo_position(mag_difr, phase_difr, &xr, &yr);
s->upmix_5_1(ctx, c_re, c_im, lfe_re, lfe_im,
mag_totall, mag_totalr,
fl_phase, fr_phase,
bl_phase, br_phase,
sl_phase, sr_phase,
xl, yl, xr, yr, n);
}
}
static void filter_5_1_back(AVFilterContext *ctx)
{
AudioSurroundContext *s = ctx->priv;
@ -1063,6 +1244,26 @@ static int init(AVFilterContext *ctx)
goto fail;
}
break;
case AV_CH_LAYOUT_5POINT0:
s->filter = filter_5_0_side;
switch (s->out_channel_layout) {
case AV_CH_LAYOUT_7POINT1:
s->upmix_5_0 = upmix_7_1_5_0_side;
break;
default:
goto fail;
}
break;
case AV_CH_LAYOUT_5POINT1:
s->filter = filter_5_1_side;
switch (s->out_channel_layout) {
case AV_CH_LAYOUT_7POINT1:
s->upmix_5_1 = upmix_7_1_5_1;
break;
default:
goto fail;
}
break;
case AV_CH_LAYOUT_5POINT1_BACK:
s->filter = filter_5_1_back;
switch (s->out_channel_layout) {