diff options
author | Paul B Mahol <onemda@gmail.com> | 2022-11-13 13:30:38 +0100 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2022-11-14 22:04:14 +0100 |
commit | e0fbf89939cbf101341d4f0fb98434f38fbbc364 (patch) | |
tree | 01990f6f0627002dca27903aa5ec4a8c8cbcfc82 /libavfilter | |
parent | 104b516a13c3281e020fbaf751185b368baae5af (diff) | |
download | ffmpeg-e0fbf89939cbf101341d4f0fb98434f38fbbc364.tar.gz |
avfilter/af_surround: speed up slice threading for stereo upmixing
And add stereo->octagonal/8.0 upmix.
Diffstat (limited to 'libavfilter')
-rw-r--r-- | libavfilter/af_surround.c | 1303 |
1 files changed, 831 insertions, 472 deletions
diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index e7bcb2e585..c5be5f456f 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -85,6 +85,7 @@ typedef struct AudioSurroundContext { float *input_levels; float *output_levels; int output_lfe; + int have_lfe; int lowcutf; int highcutf; @@ -103,20 +104,23 @@ typedef struct AudioSurroundContext { AVFrame *overlap_buffer; AVFrame *window; + float *x_pos; + float *y_pos; + float *l_phase; + float *r_phase; + float *c_phase; + float *lfe_mag; + float *mag_total; + int buf_size; + int rdft_size; int hop_size; AVTXContext **rdft, **irdft; av_tx_fn tx_fn, itx_fn; float *window_func_lut; void (*filter)(AVFilterContext *ctx); - void (*upmix_stereo)(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n); + int (*upmix)(AVFilterContext *ctx, void *arg, int ch, int nb_jobs); void (*upmix_2_1)(AVFilterContext *ctx, float l_phase, float r_phase, @@ -279,6 +283,7 @@ static int config_output(AVFilterLink *outlink) if (ret < 0) return ret; } + s->output_levels = av_malloc_array(s->nb_out_channels, sizeof(*s->output_levels)); if (!s->output_levels) return AVERROR(ENOMEM); @@ -318,6 +323,19 @@ static int config_output(AVFilterLink *outlink) if (!s->overlap_buffer || !s->output || !s->output_out) return AVERROR(ENOMEM); + s->rdft_size = s->buf_size / 2 + 1; + + s->x_pos = av_calloc(s->rdft_size, sizeof(*s->x_pos)); + s->y_pos = av_calloc(s->rdft_size, sizeof(*s->y_pos)); + s->l_phase = av_calloc(s->rdft_size, sizeof(*s->l_phase)); + s->r_phase = av_calloc(s->rdft_size, sizeof(*s->r_phase)); + s->c_phase = av_calloc(s->rdft_size, sizeof(*s->c_phase)); + s->mag_total = av_calloc(s->rdft_size, sizeof(*s->mag_total)); + s->lfe_mag = av_calloc(s->rdft_size, sizeof(*s->lfe_mag)); + if (!s->x_pos || !s->y_pos || !s->l_phase || !s->r_phase || + !s->c_phase || !s->lfe_mag) + return AVERROR(ENOMEM); + return 0; } @@ -362,141 +380,132 @@ static inline void get_lfe(int output_lfe, int n, float lowcut, float highcut, } } -static void upmix_1_0(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +#define TRANSFORM \ + dst[2 * n ] = mag * cosf(ph); \ + dst[2 * n + 1] = mag * sinf(ph); + +static int upmix_1_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float mag, *dst; - - dst = (float *)s->output->extended_data[0]; - - mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; + float *dst = (float *)s->output->extended_data[0]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *phase = s->c_phase; + const float *x = s->x_pos; + const float *y = s->y_pos; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + + for (int n = 0; n < rdft_size; n++) { + float mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + float ph = phase[n]; + + TRANSFORM + } - dst[2 * n ] = mag * cosf(c_phase); - dst[2 * n + 1] = mag * sinf(c_phase); + return 0; } -static void upmix_stereo(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_stereo(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float l_mag, r_mag, *dstl, *dstr; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *phase = ch ? s->r_phase : s->l_phase; + const float f_x = ch ? s->fr_x : s->fl_x; + const float f_y = ch ? s->fr_y : s->fl_y; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float neg = ch ? -1.f : 1.f; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag = powf(.5f * (neg * x[n] + 1.f), f_x) * powf((y[n] + 1.f) * .5f, f_y) * mag_total[n]; + float ph = phase[n]; + + TRANSFORM + } - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); + return 0; } -static void upmix_2_1(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_2_1(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float lfe_mag, l_mag, r_mag, *dstl, *dstr, *dstlfe; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstlfe = (float *)s->output->extended_data[2]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *phase = ch == 2 ? s->c_phase : ch == 1 ? s->r_phase : s->l_phase; + const float *lfe_mag = s->lfe_mag; + const float f_x = ch ? s->fr_x : s->fl_x; + const float f_y = ch ? s->fr_y : s->fl_y; + const float neg = ch ? -1.f : 1.f; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag = ch == 2 ? lfe_mag[n] : powf(.5f * (neg * x[n] + 1.f), f_x) * powf((y[n] + 1.f) * .5f, f_y) * mag_total[n]; + float ph = phase[n]; + + TRANSFORM + } - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); + return 0; } -static void upmix_3_0(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_3_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float l_mag, r_mag, c_mag, *dstc, *dstl, *dstr; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstc = (float *)s->output->extended_data[2]; - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *phase = ch == 2 ? s->c_phase : ch == 1 ? s->r_phase : s->l_phase; + const float f_x = ch ? s->fr_x : s->fl_x; + const float f_y = ch ? s->fr_y : s->fl_y; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float neg = ch ? -1.f : 1.f; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag = ch == 2 ? + powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n] : + powf(.5f * (neg * x[n] + 1.f), f_x) * powf((y[n] + 1.f) * .5f, f_y) * mag_total[n]; + float ph = phase[n]; + + TRANSFORM + } - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); + return 0; } -static void upmix_3_1(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_3_1(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float lfe_mag, l_mag, r_mag, c_mag, *dstc, *dstl, *dstr, *dstlfe; - - 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]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *phase = ch >= 2 ? s->c_phase : ch == 1 ? s->r_phase : s->l_phase; + const float f_x = ch ? s->fr_x : s->fl_x; + const float f_y = ch ? s->fr_y : s->fl_y; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float neg = ch ? -1.f : 1.f; + const float *lfe_mag = s->lfe_mag; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag = ch == 3 ? lfe_mag[n] : ch == 2 ? + powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n] : + powf(.5f * (neg * x[n] + 1.f), f_x) * powf((y[n] + 1.f) * .5f, f_y) * mag_total[n]; + float ph = phase[n]; + + TRANSFORM + } - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); + return 0; } static void upmix_3_1_surround(AVFilterContext *ctx, @@ -534,256 +543,385 @@ static void upmix_3_1_surround(AVFilterContext *ctx, dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); } -static void upmix_4_0(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_4_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float b_mag, l_mag, r_mag, c_mag, *dstc, *dstl, *dstr, *dstb; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstc = (float *)s->output->extended_data[2]; - dstb = (float *)s->output->extended_data[3]; - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - b_mag = powf(1.f - fabsf(x), s->bc_x) * powf((1.f - y) * .5f, s->bc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float bc_x = s->bc_x; + const float bc_y = s->bc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag, ph; + + switch (ch) { + case 0: + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + break; + case 1: + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + break; + case 2: + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + break; + case 3: + mag = powf(1.f - fabsf(x[n]), bc_x) * powf((1.f - y[n]) * .5f, bc_y) * mag_total[n]; + ph = c_phase[n]; + break; + } - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); + TRANSFORM + } - dstb[2 * n ] = b_mag * cosf(c_phase); - dstb[2 * n + 1] = b_mag * sinf(c_phase); + return 0; } -static void upmix_4_1(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_4_1(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float lfe_mag, b_mag, l_mag, r_mag, c_mag, *dstc, *dstl, *dstr, *dstb, *dstlfe; - - 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]; - dstb = (float *)s->output->extended_data[4]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - b_mag = powf(1.f - fabsf(x), s->bc_x) * powf((1.f - y) * .5f, s->bc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *lfe_mag = s->lfe_mag; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float bc_x = s->bc_x; + const float bc_y = s->bc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag, ph; + + switch (ch) { + case 0: + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + break; + case 1: + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + break; + case 2: + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + break; + case 3: + mag = lfe_mag[n]; + ph = c_phase[n]; + break; + case 4: + mag = powf(1.f - fabsf(x[n]), bc_x) * powf((1.f - y[n]) * .5f, bc_y) * mag_total[n]; + ph = c_phase[n]; + break; + } - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); + TRANSFORM + } - dstb[2 * n ] = b_mag * cosf(c_phase); - dstb[2 * n + 1] = b_mag * sinf(c_phase); + return 0; } -static void upmix_5_0_back(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_5_0_back(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float l_mag, r_mag, ls_mag, rs_mag, c_mag, *dstc, *dstl, *dstr, *dstls, *dstrs; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstc = (float *)s->output->extended_data[2]; - dstls = (float *)s->output->extended_data[3]; - dstrs = (float *)s->output->extended_data[4]; - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + + for (int n = 0; n < rdft_size; n++) { + float mag, ph; + + switch (ch) { + case 2: + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + break; + case 0: + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + break; + case 1: + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + break; + case 3: + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + break; + case 4: + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + break; + } - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); + TRANSFORM + } - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + return 0; } -static void upmix_5_1_back(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_5_1_back(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float lfe_mag, l_mag, r_mag, ls_mag, rs_mag, c_mag, *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlfe; - - 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]; - dstls = (float *)s->output->extended_data[4]; - dstrs = (float *)s->output->extended_data[5]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); - - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); - - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const float *lfe_mag = s->lfe_mag; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = lfe_mag[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + return 0; } -static void upmix_6_0(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_6_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float l_mag, r_mag, ls_mag, rs_mag, c_mag, b_mag, *dstc, *dstb, *dstl, *dstr, *dstls, *dstrs; - - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstc = (float *)s->output->extended_data[2]; - dstb = (float *)s->output->extended_data[3]; - dstls = (float *)s->output->extended_data[4]; - dstrs = (float *)s->output->extended_data[5]; - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - b_mag = powf(1.f - fabsf(x), s->bc_x) * powf((1.f - y) * .5f, s->bc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); - - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); - - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float bc_x = s->bc_x; + const float bc_y = s->bc_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), bc_x) * powf((1.f - y[n]) * .5f, bc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - dstb[2 * n ] = b_mag * cosf(c_phase); - dstb[2 * n + 1] = b_mag * sinf(c_phase); + return 0; } -static void upmix_6_1(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_6_1(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float lfe_mag, l_mag, r_mag, ls_mag, rs_mag, c_mag, b_mag, *dstc, *dstb, *dstl, *dstr, *dstls, *dstrs, *dstlfe; - - 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]; - dstb = (float *)s->output->extended_data[4]; - dstls = (float *)s->output->extended_data[5]; - dstrs = (float *)s->output->extended_data[6]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - b_mag = powf(1.f - fabsf(x), s->bc_x) * powf((1.f - y) * .5f, s->bc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); - - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); - - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); - - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *lfe_mag = s->lfe_mag; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float bc_x = s->bc_x; + const float bc_y = s->bc_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = lfe_mag[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), bc_x) * powf((1.f - y[n]) * .5f, bc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 6: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - dstb[2 * n ] = b_mag * cosf(c_phase); - dstb[2 * n + 1] = b_mag * sinf(c_phase); + return 0; } static void upmix_5_1_back_surround(AVFilterContext *ctx, @@ -878,110 +1016,176 @@ static void upmix_5_1_back_2_1(AVFilterContext *ctx, dstrs[2 * n + 1] = rs_mag * sinf(r_phase); } -static void upmix_7_0(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_7_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { - float l_mag, r_mag, ls_mag, rs_mag, c_mag, lb_mag, rb_mag; - float *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlb, *dstrb; AudioSurroundContext *s = ctx->priv; + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float sl_x = s->sl_x; + const float sl_y = s->sl_y; + const float sr_x = s->sr_x; + const float sr_y = s->sr_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), sl_x) * powf(1.f - fabsf(y[n]), sl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 6: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), sr_x) * powf(1.f - fabsf(y[n]), sr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - dstl = (float *)s->output->extended_data[0]; - dstr = (float *)s->output->extended_data[1]; - dstc = (float *)s->output->extended_data[2]; - dstlb = (float *)s->output->extended_data[3]; - dstrb = (float *)s->output->extended_data[4]; - dstls = (float *)s->output->extended_data[5]; - dstrs = (float *)s->output->extended_data[6]; - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - lb_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rb_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->sl_x) * powf(1.f - fabsf(y), s->sl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->sr_x) * powf(1.f - fabsf(y), s->sr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); - - dstlb[2 * n ] = lb_mag * cosf(l_phase); - dstlb[2 * n + 1] = lb_mag * sinf(l_phase); - - dstrb[2 * n ] = rb_mag * cosf(r_phase); - dstrb[2 * n + 1] = rb_mag * sinf(r_phase); - - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); - - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + return 0; } -static void upmix_7_1(AVFilterContext *ctx, - float l_phase, - float r_phase, - float c_phase, - float mag_total, - float x, float y, - int n) +static int upmix_7_1(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { - float lfe_mag, l_mag, r_mag, ls_mag, rs_mag, c_mag, lb_mag, rb_mag; - float *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlb, *dstrb, *dstlfe; AudioSurroundContext *s = ctx->priv; + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *lfe_mag = s->lfe_mag; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float sl_x = s->sl_x; + const float sl_y = s->sl_y; + const float sr_x = s->sr_x; + const float sr_y = s->sr_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = lfe_mag[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 6: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), sl_x) * powf(1.f - fabsf(y[n]), sl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 7: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), sr_x) * powf(1.f - fabsf(y[n]), sr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - 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]; - - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - - c_mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; - l_mag = powf(.5f * ( x + 1.f), s->fl_x) * powf((y + 1.f) * .5f, s->fl_y) * mag_total; - r_mag = powf(.5f * (-x + 1.f), s->fr_x) * powf((y + 1.f) * .5f, s->fr_y) * mag_total; - lb_mag = powf(.5f * ( x + 1.f), s->bl_x) * powf(1.f - ((y + 1.f) * .5f), s->bl_y) * mag_total; - rb_mag = powf(.5f * (-x + 1.f), s->br_x) * powf(1.f - ((y + 1.f) * .5f), s->br_y) * mag_total; - ls_mag = powf(.5f * ( x + 1.f), s->sl_x) * powf(1.f - fabsf(y), s->sl_y) * mag_total; - rs_mag = powf(.5f * (-x + 1.f), s->sr_x) * powf(1.f - fabsf(y), s->sr_y) * mag_total; - - dstl[2 * n ] = l_mag * cosf(l_phase); - dstl[2 * n + 1] = l_mag * sinf(l_phase); - - dstr[2 * n ] = r_mag * cosf(r_phase); - dstr[2 * n + 1] = r_mag * sinf(r_phase); - - dstc[2 * n ] = c_mag * cosf(c_phase); - dstc[2 * n + 1] = c_mag * sinf(c_phase); - - dstlfe[2 * n ] = lfe_mag * cosf(c_phase); - dstlfe[2 * n + 1] = lfe_mag * sinf(c_phase); - - dstlb[2 * n ] = lb_mag * cosf(l_phase); - dstlb[2 * n + 1] = lb_mag * sinf(l_phase); - - dstrb[2 * n ] = rb_mag * cosf(r_phase); - dstrb[2 * n + 1] = rb_mag * sinf(r_phase); - - dstls[2 * n ] = ls_mag * cosf(l_phase); - dstls[2 * n + 1] = ls_mag * sinf(l_phase); - - dstrs[2 * n ] = rs_mag * cosf(r_phase); - dstrs[2 * n + 1] = rs_mag * sinf(r_phase); + return 0; } static void upmix_7_1_5_0_side(AVFilterContext *ctx, @@ -1100,16 +1304,116 @@ static void upmix_7_1_5_1(AVFilterContext *ctx, dstrs[2 * n + 1] = rs_mag * sinf(sr_phase); } -static void filter_stereo(AVFilterContext *ctx) +static int upmix_8_0(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) { AudioSurroundContext *s = ctx->priv; - float *srcl, *srcr; - int n; + float *dst = (float *)s->output->extended_data[ch]; + const float *mag_total = s->mag_total; + const int rdft_size = s->rdft_size; + const float *l_phase = s->l_phase; + const float *r_phase = s->r_phase; + const float *c_phase = s->c_phase; + const float fl_x = s->fl_x; + const float fl_y = s->fl_y; + const float fr_x = s->fr_x; + const float fr_y = s->fr_y; + const float fc_x = s->fc_x; + const float fc_y = s->fc_y; + const float bl_x = s->bl_x; + const float bl_y = s->bl_y; + const float br_x = s->br_x; + const float br_y = s->br_y; + const float sl_x = s->sl_x; + const float sl_y = s->sl_y; + const float sr_x = s->sr_x; + const float sr_y = s->sr_y; + const float bc_x = s->bc_x; + const float bc_y = s->bc_y; + const float *x = s->x_pos; + const float *y = s->y_pos; + float mag, ph; + + switch (ch) { + case 0: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), fl_x) * powf((y[n] + 1.f) * .5f, fl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 1: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), fr_x) * powf((y[n] + 1.f) * .5f, fr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 2: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), fc_x) * powf((y[n] + 1.f) * .5f, fc_y) * mag_total[n]; + ph = c_phase[n]; + TRANSFORM + } + break; + case 3: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), bl_x) * powf(1.f - ((y[n] + 1.f) * .5f), bl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 4: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), br_x) * powf(1.f - ((y[n] + 1.f) * .5f), br_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + case 5: + for (int n = 0; n < rdft_size; n++) { + mag = powf(1.f - fabsf(x[n]), bc_x) * powf((1.f - y[n]) * .5f, bc_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 6: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * ( x[n] + 1.f), sl_x) * powf(1.f - fabsf(y[n]), sl_y) * mag_total[n]; + ph = l_phase[n]; + TRANSFORM + } + break; + case 7: + for (int n = 0; n < rdft_size; n++) { + mag = powf(.5f * (-x[n] + 1.f), sr_x) * powf(1.f - fabsf(y[n]), sr_y) * mag_total[n]; + ph = r_phase[n]; + TRANSFORM + } + break; + } - srcl = (float *)s->input->extended_data[0]; - srcr = (float *)s->input->extended_data[1]; + return 0; +} - for (n = 0; n < s->buf_size / 2 + 1; n++) { +static void filter_stereo(AVFilterContext *ctx) +{ + AudioSurroundContext *s = ctx->priv; + const float *srcl = (const float *)s->input->extended_data[0]; + const float *srcr = (const float *)s->input->extended_data[1]; + const int output_lfe = s->output_lfe && s->have_lfe; + const int lfe_mode = s->lfe_mode; + const float highcut = s->highcut; + const float lowcut = s->lowcut; + const float angle = s->angle; + float *magtotal = s->mag_total; + float *lfemag = s->lfe_mag; + float *lphase = s->l_phase; + float *rphase = s->r_phase; + float *cphase = s->c_phase; + float *xpos = s->x_pos; + float *ypos = s->y_pos; + + for (int n = 0; n < s->rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_phase = atan2f(l_im + r_im, l_re + r_re); @@ -1127,9 +1431,15 @@ static void filter_stereo(AVFilterContext *ctx) phase_dif = 2 * M_PI - phase_dif; stereo_position(mag_dif, phase_dif, &x, &y); - stereo_transform(&x, &y, s->angle); - - s->upmix_stereo(ctx, l_phase, r_phase, c_phase, mag_total, x, y, n); + stereo_transform(&x, &y, angle); + get_lfe(output_lfe, n, lowcut, highcut, &lfemag[n], &mag_total, lfe_mode); + + xpos[n] = x; + ypos[n] = y; + lphase[n] = l_phase; + rphase[n] = r_phase; + cphase[n] = c_phase; + magtotal[n] = mag_total; } } @@ -1143,7 +1453,7 @@ static void filter_surround(AVFilterContext *ctx) srcr = (float *)s->input->extended_data[1]; srcc = (float *)s->input->extended_data[2]; - for (n = 0; n < s->buf_size / 2 + 1; n++) { + for (n = 0; n < s->rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float c_re = srcc[2 * n], c_im = srcc[2 * n + 1]; @@ -1179,7 +1489,7 @@ static void filter_2_1(AVFilterContext *ctx) srcr = (float *)s->input->extended_data[1]; srclfe = (float *)s->input->extended_data[2]; - for (n = 0; n < s->buf_size / 2 + 1; n++) { + for (n = 0; n < s->rdft_size; n++) { float l_re = srcl[2 * n], r_re = srcr[2 * n]; float l_im = srcl[2 * n + 1], r_im = srcr[2 * n + 1]; float lfe_re = srclfe[2 * n], lfe_im = srclfe[2 * n + 1]; @@ -1216,7 +1526,7 @@ static void filter_5_0_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[3]; srcsr = (float *)s->input->extended_data[4]; - for (n = 0; n < s->buf_size / 2 + 1; n++) { + for (n = 0; n < s->rdft_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]; @@ -1274,7 +1584,7 @@ static void filter_5_1_side(AVFilterContext *ctx) srcsl = (float *)s->input->extended_data[4]; srcsr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->buf_size / 2 + 1; n++) { + for (n = 0; n < s->rdft_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]; @@ -1333,7 +1643,7 @@ static void filter_5_1_back(AVFilterContext *ctx) srcbl = (float *)s->input->extended_data[4]; srcbr = (float *)s->input->extended_data[5]; - for (n = 0; n < s->buf_size / 2 + 1; n++) { + for (n = 0; n < s->rdft_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]; @@ -1409,48 +1719,59 @@ static av_cold int init(AVFilterContext *ctx) out_channel_layout = s->out_channel_layout.order == AV_CHANNEL_ORDER_NATIVE ? s->out_channel_layout.u.mask : 0; + s->have_lfe = 0; + switch (in_channel_layout) { case AV_CH_LAYOUT_STEREO: s->filter = filter_stereo; switch (out_channel_layout) { case AV_CH_LAYOUT_MONO: - s->upmix_stereo = upmix_1_0; + s->upmix = upmix_1_0; break; case AV_CH_LAYOUT_STEREO: - s->upmix_stereo = upmix_stereo; + s->upmix = upmix_stereo; break; case AV_CH_LAYOUT_2POINT1: - s->upmix_stereo = upmix_2_1; + s->upmix = upmix_2_1; + s->have_lfe = 1; break; case AV_CH_LAYOUT_SURROUND: - s->upmix_stereo = upmix_3_0; + s->upmix = upmix_3_0; break; case AV_CH_LAYOUT_3POINT1: - s->upmix_stereo = upmix_3_1; + s->upmix = upmix_3_1; + s->have_lfe = 1; break; case AV_CH_LAYOUT_4POINT0: - s->upmix_stereo = upmix_4_0; + s->upmix = upmix_4_0; break; case AV_CH_LAYOUT_4POINT1: - s->upmix_stereo = upmix_4_1; + s->upmix = upmix_4_1; + s->have_lfe = 1; break; case AV_CH_LAYOUT_5POINT0_BACK: - s->upmix_stereo = upmix_5_0_back; + s->upmix = upmix_5_0_back; break; case AV_CH_LAYOUT_5POINT1_BACK: - s->upmix_stereo = upmix_5_1_back; + s->upmix = upmix_5_1_back; + s->have_lfe = 1; break; case AV_CH_LAYOUT_6POINT0: - s->upmix_stereo = upmix_6_0; + s->upmix = upmix_6_0; break; case AV_CH_LAYOUT_6POINT1: - s->upmix_stereo = upmix_6_1; + s->upmix = upmix_6_1; + s->have_lfe = 1; break; case AV_CH_LAYOUT_7POINT0: - s->upmix_stereo = upmix_7_0; + s->upmix = upmix_7_0; break; case AV_CH_LAYOUT_7POINT1: - s->upmix_stereo = upmix_7_1; + s->upmix = upmix_7_1; + s->have_lfe = 1; + break; + case AV_CH_LAYOUT_OCTAGONAL: + s->upmix = upmix_8_0; break; default: goto fail; @@ -1461,6 +1782,7 @@ static av_cold int init(AVFilterContext *ctx) switch (out_channel_layout) { case AV_CH_LAYOUT_5POINT1_BACK: s->upmix_2_1 = upmix_5_1_back_2_1; + s->have_lfe = 1; break; default: goto fail; @@ -1471,9 +1793,11 @@ static av_cold int init(AVFilterContext *ctx) switch (out_channel_layout) { case AV_CH_LAYOUT_3POINT1: s->upmix_3_0 = upmix_3_1_surround; + s->have_lfe = 1; break; case AV_CH_LAYOUT_5POINT1_BACK: s->upmix_3_0 = upmix_5_1_back_surround; + s->have_lfe = 1; break; default: goto fail; @@ -1484,6 +1808,7 @@ static av_cold int init(AVFilterContext *ctx) switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_0 = upmix_7_1_5_0_side; + s->have_lfe = 1; break; default: goto fail; @@ -1494,6 +1819,7 @@ static av_cold int init(AVFilterContext *ctx) switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_1 = upmix_7_1_5_1; + s->have_lfe = 1; break; default: goto fail; @@ -1504,6 +1830,7 @@ static av_cold int init(AVFilterContext *ctx) switch (out_channel_layout) { case AV_CH_LAYOUT_7POINT1: s->upmix_5_1 = upmix_7_1_5_1; + s->have_lfe = 1; break; default: goto fail; @@ -1540,35 +1867,43 @@ fail: return 0; } -static int fft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) +static int fft_channel(AVFilterContext *ctx, AVFrame *in, int ch) { AudioSurroundContext *s = ctx->priv; float *src = (float *)s->input_in->extended_data[ch]; float *win = (float *)s->window->extended_data[ch]; const int offset = s->buf_size - s->hop_size; const float level_in = s->input_levels[ch]; - AVFrame *in = arg; memmove(src, &src[s->hop_size], offset * sizeof(float)); memcpy(&src[offset], in->extended_data[ch], in->nb_samples * sizeof(float)); memset(&src[offset + in->nb_samples], 0, (s->hop_size - in->nb_samples) * sizeof(float)); - for (int n = 0; n < s->buf_size; n++) { + for (int n = 0; n < s->buf_size; n++) win[n] = src[n] * s->window_func_lut[n] * level_in; - } s->tx_fn(s->rdft[ch], (float *)s->input->extended_data[ch], win, sizeof(float)); return 0; } -static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) +static int fft_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AVFrame *in = arg; + const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) + fft_channel(ctx, in, ch); + + return 0; +} + +static int ifft_channel(AVFilterContext *ctx, AVFrame *out, int ch) { AudioSurroundContext *s = ctx->priv; const float level_out = s->output_levels[ch]; - AVFrame *out = arg; float *dst, *ptr; - int n; dst = (float *)s->output_out->extended_data[ch]; ptr = (float *)s->overlap_buffer->extended_data[ch]; @@ -1580,9 +1915,8 @@ static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) memset(s->overlap_buffer->extended_data[ch] + s->buf_size * sizeof(float), 0, s->hop_size * sizeof(float)); - for (n = 0; n < s->buf_size; n++) { + for (int n = 0; n < s->buf_size; n++) ptr[n] += dst[n] * s->window_func_lut[n] * level_out; - } ptr = (float *)s->overlap_buffer->extended_data[ch]; dst = (float *)out->extended_data[ch]; @@ -1591,6 +1925,18 @@ static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) return 0; } +static int ifft_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) +{ + AVFrame *out = arg; + const int start = (out->ch_layout.nb_channels * jobnr) / nb_jobs; + const int end = (out->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; + + for (int ch = start; ch < end; ch++) + ifft_channel(ctx, out, ch); + + return 0; +} + static int filter_frame(AVFilterLink *inlink, AVFrame *in) { AVFilterContext *ctx = inlink->dst; @@ -1598,15 +1944,20 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in) AudioSurroundContext *s = ctx->priv; AVFrame *out; - ff_filter_execute(ctx, fft_channel, in, NULL, inlink->ch_layout.nb_channels); + ff_filter_execute(ctx, fft_channels, in, NULL, + FFMIN(inlink->ch_layout.nb_channels, + ff_filter_get_nb_threads(ctx))); s->filter(ctx); + ff_filter_execute(ctx, s->upmix, NULL, NULL, outlink->ch_layout.nb_channels); out = ff_get_audio_buffer(outlink, s->hop_size); if (!out) return AVERROR(ENOMEM); - ff_filter_execute(ctx, ifft_channel, out, NULL, outlink->ch_layout.nb_channels); + ff_filter_execute(ctx, ifft_channels, out, NULL, + FFMIN(outlink->ch_layout.nb_channels, + ff_filter_get_nb_threads(ctx))); out->pts = in->pts; out->nb_samples = in->nb_samples; @@ -1670,6 +2021,14 @@ static av_cold void uninit(AVFilterContext *ctx) av_freep(&s->rdft); av_freep(&s->irdft); av_freep(&s->window_func_lut); + + av_freep(&s->x_pos); + av_freep(&s->y_pos); + av_freep(&s->l_phase); + av_freep(&s->r_phase); + av_freep(&s->c_phase); + av_freep(&s->mag_total); + av_freep(&s->lfe_mag); } #define OFFSET(x) offsetof(AudioSurroundContext, x) |