X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faf_surround.c;h=d18b3146e7e5c6cc3ff8daa9104612af6f51c22f;hb=3a370868dc33061a20d1fd99274e65167d7a78ac;hp=fcd84155a7680e311653f4fcaf5a3f6767f91587;hpb=bad70b7af6b909691f5389e14eb7d0c03db10af9;p=ffmpeg diff --git a/libavfilter/af_surround.c b/libavfilter/af_surround.c index fcd84155a76..d18b3146e7e 100644 --- a/libavfilter/af_surround.c +++ b/libavfilter/af_surround.c @@ -18,13 +18,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/audio_fifo.h" #include "libavutil/channel_layout.h" #include "libavutil/opt.h" #include "libavcodec/avfft.h" #include "avfilter.h" #include "audio.h" +#include "filters.h" +#include "internal.h" #include "formats.h" +#include "window_func.h" typedef struct AudioSurroundContext { const AVClass *class; @@ -36,8 +40,48 @@ typedef struct AudioSurroundContext { float level_out; float fc_in; float fc_out; + float fl_in; + float fl_out; + float fr_in; + float fr_out; + float sl_in; + float sl_out; + float sr_in; + float sr_out; + float bl_in; + float bl_out; + float br_in; + float br_out; + float bc_in; + float bc_out; float lfe_in; float lfe_out; + int lfe_mode; + float angle; + int win_size; + int win_func; + float overlap; + + float all_x; + float all_y; + + float fc_x; + float fl_x; + float fr_x; + float bl_x; + float br_x; + float sl_x; + float sr_x; + float bc_x; + + float fc_y; + float fl_y; + float fr_y; + float bl_y; + float br_y; + float sl_y; + float sr_y; + float bc_y; float *input_levels; float *output_levels; @@ -64,6 +108,7 @@ typedef struct AudioSurroundContext { float *window_func_lut; int64_t pts; + int eof; void (*filter)(AVFilterContext *ctx); void (*upmix_stereo)(AVFilterContext *ctx, @@ -130,7 +175,7 @@ static int query_formats(AVFilterContext *ctx) if (ret) return ret; - ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts); if (ret) return ret; @@ -139,7 +184,7 @@ static int query_formats(AVFilterContext *ctx) if (ret) return ret; - ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->out_channel_layouts); + ret = ff_channel_layouts_ref(layouts, &ctx->inputs[0]->outcfg.channel_layouts); if (ret) return ret; @@ -173,6 +218,27 @@ static int config_input(AVFilterLink *inlink) ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_CENTER); if (ch >= 0) s->input_levels[ch] *= s->fc_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_LEFT); + if (ch >= 0) + s->input_levels[ch] *= s->fl_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_FRONT_RIGHT); + if (ch >= 0) + s->input_levels[ch] *= s->fr_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_SIDE_LEFT); + if (ch >= 0) + s->input_levels[ch] *= s->sl_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_SIDE_RIGHT); + if (ch >= 0) + s->input_levels[ch] *= s->sr_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_LEFT); + if (ch >= 0) + s->input_levels[ch] *= s->bl_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_RIGHT); + if (ch >= 0) + s->input_levels[ch] *= s->br_in; + ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_BACK_CENTER); + if (ch >= 0) + s->input_levels[ch] *= s->bc_in; ch = av_get_channel_layout_channel_index(inlink->channel_layout, AV_CH_LOW_FREQUENCY); if (ch >= 0) s->input_levels[ch] *= s->lfe_in; @@ -215,6 +281,27 @@ static int config_output(AVFilterLink *outlink) ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_CENTER); if (ch >= 0) s->output_levels[ch] *= s->fc_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_LEFT); + if (ch >= 0) + s->output_levels[ch] *= s->fl_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_FRONT_RIGHT); + if (ch >= 0) + s->output_levels[ch] *= s->fr_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_SIDE_LEFT); + if (ch >= 0) + s->output_levels[ch] *= s->sl_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_SIDE_RIGHT); + if (ch >= 0) + s->output_levels[ch] *= s->sr_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_LEFT); + if (ch >= 0) + s->output_levels[ch] *= s->bl_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_RIGHT); + if (ch >= 0) + s->output_levels[ch] *= s->br_out; + ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_BACK_CENTER); + if (ch >= 0) + s->output_levels[ch] *= s->bc_out; ch = av_get_channel_layout_channel_index(outlink->channel_layout, AV_CH_LOW_FREQUENCY); if (ch >= 0) s->output_levels[ch] *= s->lfe_out; @@ -227,19 +314,42 @@ static int config_output(AVFilterLink *outlink) return 0; } +static void stereo_transform(float *x, float *y, float angle) +{ + float reference, r, a; + + if (angle == 90.f) + return; + + reference = angle * M_PI / 180.f; + r = hypotf(*x, *y); + a = atan2f(*x, *y); + + if (fabsf(a) <= M_PI_4) + a *= reference / M_PI_2; + else + a = M_PI + 2 * (-2 * M_PI + reference) * (M_PI - fabsf(a)) * FFDIFFSIGN(a, 0) / (3 * M_PI); + + *x = av_clipf(sinf(a) * r, -1, 1); + *y = av_clipf(cosf(a) * r, -1, 1); +} + static void stereo_position(float a, float p, float *x, float *y) { - *x = av_clipf(a+FFMAX(0, sinf(p-M_PI_2))*FFDIFFSIGN(a,0), -1, 1); + av_assert2(a >= -1.f && a <= 1.f); + av_assert2(p >= 0.f && p <= M_PI); + *x = av_clipf(a+a*FFMAX(0, p*p-M_PI_2), -1, 1); *y = av_clipf(cosf(a*M_PI_2+M_PI)*cosf(M_PI_2-p/M_PI)*M_LN10+1, -1, 1); } static inline void get_lfe(int output_lfe, int n, float lowcut, float highcut, - float *lfe_mag, float *mag_total) + float *lfe_mag, float *mag_total, int lfe_mode) { if (output_lfe && n < highcut) { *lfe_mag = n < lowcut ? 1.f : .5f*(1.f+cosf(M_PI*(lowcut-n)/(lowcut-highcut))); *lfe_mag *= *mag_total; - *mag_total -= *lfe_mag; + if (lfe_mode) + *mag_total -= *lfe_mag; } else { *lfe_mag = 0.f; } @@ -258,7 +368,7 @@ static void upmix_1_0(AVFilterContext *ctx, dst = (float *)s->output->extended_data[0]; - mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; + mag = powf(1.f - fabsf(x), s->fc_x) * powf((y + 1.f) * .5f, s->fc_y) * mag_total; dst[2 * n ] = mag * cosf(c_phase); dst[2 * n + 1] = mag * sinf(c_phase); @@ -278,8 +388,8 @@ static void upmix_stereo(AVFilterContext *ctx, dstl = (float *)s->output->extended_data[0]; dstr = (float *)s->output->extended_data[1]; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * 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); @@ -303,10 +413,10 @@ static void upmix_2_1(AVFilterContext *ctx, 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); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * 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); @@ -333,9 +443,9 @@ static void upmix_3_0(AVFilterContext *ctx, dstr = (float *)s->output->extended_data[1]; dstc = (float *)s->output->extended_data[2]; - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; + 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); @@ -363,11 +473,11 @@ static void upmix_3_1(AVFilterContext *ctx, 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); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; + 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); @@ -399,10 +509,10 @@ static void upmix_3_1_surround(AVFilterContext *ctx, 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, &c_mag); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &c_mag, s->lfe_mode); - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * 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); @@ -425,18 +535,18 @@ static void upmix_4_0(AVFilterContext *ctx, float x, float y, int n) { - float b_mag, l_mag, r_mag, c_mag, *dstc, *dstl, *dstr, *dstb; 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 = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - b_mag = sqrtf(1.f - fabsf(x)) * ((1.f - y) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; + 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); @@ -459,8 +569,8 @@ static void upmix_4_1(AVFilterContext *ctx, float x, float y, int n) { - float lfe_mag, b_mag, l_mag, r_mag, c_mag, *dstc, *dstl, *dstr, *dstb, *dstlfe; 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]; @@ -468,15 +578,15 @@ static void upmix_4_1(AVFilterContext *ctx, 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); + 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 = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - b_mag = sqrtf(1.f - fabsf(x)) * ((1.f - y) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; + 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); @@ -499,8 +609,8 @@ static void upmix_5_0_back(AVFilterContext *ctx, float x, float y, int n) { - float l_mag, r_mag, ls_mag, rs_mag, c_mag, *dstc, *dstl, *dstr, *dstls, *dstrs; 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]; @@ -508,11 +618,11 @@ static void upmix_5_0_back(AVFilterContext *ctx, dstls = (float *)s->output->extended_data[3]; dstrs = (float *)s->output->extended_data[4]; - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; + 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); @@ -538,8 +648,8 @@ static void upmix_5_1_back(AVFilterContext *ctx, float x, float y, int n) { - float lfe_mag, l_mag, r_mag, ls_mag, rs_mag, c_mag, *dstc, *dstl, *dstr, *dstls, *dstrs, *dstlfe; 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]; @@ -548,13 +658,13 @@ static void upmix_5_1_back(AVFilterContext *ctx, 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); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; + 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); @@ -575,6 +685,100 @@ static void upmix_5_1_back(AVFilterContext *ctx, dstrs[2 * n + 1] = rs_mag * sinf(r_phase); } +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) +{ + 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); + + dstb[2 * n ] = b_mag * cosf(c_phase); + dstb[2 * n + 1] = b_mag * sinf(c_phase); +} + +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) +{ + 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); + + dstb[2 * n ] = b_mag * cosf(c_phase); + dstb[2 * n + 1] = b_mag * sinf(c_phase); +} + static void upmix_5_1_back_surround(AVFilterContext *ctx, float l_phase, float r_phase, @@ -595,12 +799,12 @@ static void upmix_5_1_back_surround(AVFilterContext *ctx, 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, &c_mag); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &c_mag, s->lfe_mode); - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * 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); @@ -642,11 +846,11 @@ static void upmix_5_1_back_2_1(AVFilterContext *ctx, dstls = (float *)s->output->extended_data[4]; dstrs = (float *)s->output->extended_data[5]; - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; + 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); @@ -687,13 +891,13 @@ static void upmix_7_0(AVFilterContext *ctx, dstls = (float *)s->output->extended_data[5]; dstrs = (float *)s->output->extended_data[6]; - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - lb_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rb_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - fabsf(y)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - fabsf(y)) * mag_total; + 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); @@ -738,15 +942,15 @@ static void upmix_7_1(AVFilterContext *ctx, 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); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - c_mag = sqrtf(1.f - fabsf(x)) * ((y + 1.f) * .5f) * mag_total; - l_mag = sqrtf(.5f * ( x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - r_mag = sqrtf(.5f * (-x + 1.f)) * ((y + 1.f) * .5f) * mag_total; - lb_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - rb_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - ((y + 1.f) * .5f)) * mag_total; - ls_mag = sqrtf(.5f * ( x + 1.f)) * (1.f - fabsf(y)) * mag_total; - rs_mag = sqrtf(.5f * (-x + 1.f)) * (1.f - fabsf(y)) * mag_total; + 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); @@ -799,14 +1003,14 @@ static void upmix_7_1_5_0_side(AVFilterContext *ctx, c_phase = atan2f(c_im, c_re); - get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total); + get_lfe(s->output_lfe, n, s->lowcut, s->highcut, &lfe_mag, &mag_total, s->lfe_mode); - 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; + fl_mag = powf(.5f * (xl + 1.f), s->fl_x) * powf((yl + 1.f) * .5f, s->fl_y) * mag_totall; + fr_mag = powf(.5f * (xr + 1.f), s->fr_x) * powf((yr + 1.f) * .5f, s->fr_y) * mag_totalr; + lb_mag = powf(.5f * (-xl + 1.f), s->bl_x) * powf((yl + 1.f) * .5f, s->bl_y) * mag_totall; + rb_mag = powf(.5f * (-xr + 1.f), s->br_x) * powf((yr + 1.f) * .5f, s->br_y) * mag_totalr; + ls_mag = powf(1.f - fabsf(xl), s->sl_x) * powf((yl + 1.f) * .5f, s->sl_y) * mag_totall; + rs_mag = powf(1.f - fabsf(xr), s->sr_x) * powf((yr + 1.f) * .5f, s->sr_y) * mag_totalr; dstl[2 * n ] = fl_mag * cosf(fl_phase); dstl[2 * n + 1] = fl_mag * sinf(fl_phase); @@ -857,12 +1061,12 @@ static void upmix_7_1_5_1(AVFilterContext *ctx, dstls = (float *)s->output->extended_data[6]; dstrs = (float *)s->output->extended_data[7]; - 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; + fl_mag = powf(.5f * (xl + 1.f), s->fl_x) * powf((yl + 1.f) * .5f, s->fl_y) * mag_totall; + fr_mag = powf(.5f * (xr + 1.f), s->fr_x) * powf((yr + 1.f) * .5f, s->fr_y) * mag_totalr; + lb_mag = powf(.5f * (-xl + 1.f), s->bl_x) * powf((yl + 1.f) * .5f, s->bl_y) * mag_totall; + rb_mag = powf(.5f * (-xr + 1.f), s->br_x) * powf((yr + 1.f) * .5f, s->br_y) * mag_totalr; + ls_mag = powf(1.f - fabsf(xl), s->sl_x) * powf((yl + 1.f) * .5f, s->sl_y) * mag_totall; + rs_mag = powf(1.f - fabsf(xr), s->sr_x) * powf((yr + 1.f) * .5f, s->sr_y) * mag_totalr; dstl[2 * n ] = fl_mag * cosf(fl_phase); dstl[2 * n + 1] = fl_mag * sinf(fl_phase); @@ -907,7 +1111,8 @@ static void filter_stereo(AVFilterContext *ctx) float l_phase = atan2f(l_im, l_re); float r_phase = atan2f(r_im, r_re); float phase_dif = fabsf(l_phase - r_phase); - float mag_dif = (l_mag - r_mag) / (l_mag + r_mag); + float mag_sum = l_mag + r_mag; + float mag_dif = mag_sum < 0.000001 ? FFDIFFSIGN(l_mag, r_mag) : (l_mag - r_mag) / mag_sum; float mag_total = hypotf(l_mag, r_mag); float x, y; @@ -915,6 +1120,7 @@ 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); } @@ -941,7 +1147,8 @@ static void filter_surround(AVFilterContext *ctx) float l_phase = atan2f(l_im, l_re); float r_phase = atan2f(r_im, r_re); float phase_dif = fabsf(l_phase - r_phase); - float mag_dif = (l_mag - r_mag) / (l_mag + r_mag); + float mag_sum = l_mag + r_mag; + float mag_dif = mag_sum < 0.000001 ? FFDIFFSIGN(l_mag, r_mag) : (l_mag - r_mag) / mag_sum; float mag_total = hypotf(l_mag, r_mag); float x, y; @@ -949,6 +1156,7 @@ static void filter_surround(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_3_0(ctx, l_phase, r_phase, c_phase, c_mag, mag_total, x, y, n); } @@ -974,7 +1182,8 @@ static void filter_2_1(AVFilterContext *ctx) float l_phase = atan2f(l_im, l_re); float r_phase = atan2f(r_im, r_re); float phase_dif = fabsf(l_phase - r_phase); - float mag_dif = (l_mag - r_mag) / (l_mag + r_mag); + float mag_sum = l_mag + r_mag; + float mag_dif = mag_sum < 0.000001 ? FFDIFFSIGN(l_mag, r_mag) : (l_mag - r_mag) / mag_sum; float mag_total = hypotf(l_mag, r_mag); float x, y; @@ -982,6 +1191,7 @@ static void filter_2_1(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_2_1(ctx, l_phase, r_phase, c_phase, mag_total, lfe_re, lfe_im, x, y, n); } @@ -1015,8 +1225,10 @@ static void filter_5_0_side(AVFilterContext *ctx) 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 magl_sum = fl_mag + sl_mag; + float magr_sum = fr_mag + sr_mag; + float mag_difl = magl_sum < 0.000001 ? FFDIFFSIGN(fl_mag, sl_mag) : (fl_mag - sl_mag) / magl_sum; + float mag_difr = magr_sum < 0.000001 ? FFDIFFSIGN(fr_mag, sr_mag) : (fr_mag - sr_mag) / magr_sum; 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); @@ -1072,8 +1284,10 @@ static void filter_5_1_side(AVFilterContext *ctx) 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 magl_sum = fl_mag + sl_mag; + float magr_sum = fr_mag + sr_mag; + float mag_difl = magl_sum < 0.000001 ? FFDIFFSIGN(fl_mag, sl_mag) : (fl_mag - sl_mag) / magl_sum; + float mag_difr = magr_sum < 0.000001 ? FFDIFFSIGN(fr_mag, sr_mag) : (fr_mag - sr_mag) / magr_sum; 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); @@ -1129,8 +1343,10 @@ static void filter_5_1_back(AVFilterContext *ctx) float br_phase = atan2f(br_im, br_re); float phase_difl = fabsf(fl_phase - bl_phase); float phase_difr = fabsf(fr_phase - br_phase); - float mag_difl = (fl_mag - bl_mag) / (fl_mag + bl_mag); - float mag_difr = (fr_mag - br_mag) / (fr_mag + br_mag); + float magl_sum = fl_mag + bl_mag; + float magr_sum = fr_mag + br_mag; + float mag_difl = magl_sum < 0.000001 ? FFDIFFSIGN(fl_mag, bl_mag) : (fl_mag - bl_mag) / magl_sum; + float mag_difr = magr_sum < 0.000001 ? FFDIFFSIGN(fr_mag, br_mag) : (fr_mag - br_mag) / magr_sum; float mag_totall = hypotf(fl_mag, bl_mag); float mag_totalr = hypotf(fr_mag, br_mag); float sl_phase = atan2f(fl_im + bl_im, fl_re + bl_re); @@ -1156,7 +1372,7 @@ static void filter_5_1_back(AVFilterContext *ctx) } } -static int init(AVFilterContext *ctx) +static av_cold int init(AVFilterContext *ctx) { AudioSurroundContext *s = ctx->priv; float overlap; @@ -1211,6 +1427,12 @@ static int init(AVFilterContext *ctx) case AV_CH_LAYOUT_5POINT1_BACK: s->upmix_stereo = upmix_5_1_back; break; + case AV_CH_LAYOUT_6POINT0: + s->upmix_stereo = upmix_6_0; + break; + case AV_CH_LAYOUT_6POINT1: + s->upmix_stereo = upmix_6_1; + break; case AV_CH_LAYOUT_7POINT0: s->upmix_stereo = upmix_7_0; break; @@ -1281,17 +1503,27 @@ fail: return AVERROR(EINVAL); } - s->buf_size = 4096; + s->buf_size = 1 << av_log2(s->win_size); s->pts = AV_NOPTS_VALUE; s->window_func_lut = av_calloc(s->buf_size, sizeof(*s->window_func_lut)); if (!s->window_func_lut) return AVERROR(ENOMEM); + generate_window_func(s->window_func_lut, s->buf_size, s->win_func, &overlap); + if (s->overlap == 1) + s->overlap = overlap; + for (i = 0; i < s->buf_size; i++) - s->window_func_lut[i] = sqrtf(0.5 * (1 - cosf(2 * M_PI * i / s->buf_size)) / s->buf_size); - overlap = .5; - s->hop_size = s->buf_size * (1. - overlap); + s->window_func_lut[i] = sqrtf(s->window_func_lut[i] / s->buf_size); + s->hop_size = s->buf_size * (1. - s->overlap); + if (s->hop_size <= 0) + return AVERROR(EINVAL); + + if (s->all_x >= 0.f) + s->fc_x = s->fl_x = s->fr_x = s->bc_x = s->sl_x = s->sr_x = s->bl_x = s->br_x = s->all_x; + if (s->all_y >= 0.f) + s->fc_y = s->fl_y = s->fr_y = s->bc_y = s->sl_y = s->sr_y = s->bl_y = s->br_y = s->all_y; return 0; } @@ -1345,70 +1577,91 @@ static int ifft_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs) return 0; } -static int filter_frame(AVFilterLink *inlink, AVFrame *in) +static int filter_frame(AVFilterLink *inlink) { AVFilterContext *ctx = inlink->dst; AVFilterLink *outlink = ctx->outputs[0]; AudioSurroundContext *s = ctx->priv; + AVFrame *out; int ret; - ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, - in->nb_samples); - if (ret >= 0 && s->pts == AV_NOPTS_VALUE) - s->pts = in->pts; - - av_frame_free(&in); + ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size); if (ret < 0) return ret; - while (av_audio_fifo_size(s->fifo) >= s->buf_size) { - AVFrame *out; + ctx->internal->execute(ctx, fft_channel, NULL, NULL, inlink->channels); - ret = av_audio_fifo_peek(s->fifo, (void **)s->input->extended_data, s->buf_size); - if (ret < 0) - return ret; + s->filter(ctx); - ctx->internal->execute(ctx, fft_channel, NULL, NULL, inlink->channels); + out = ff_get_audio_buffer(outlink, s->hop_size); + if (!out) + return AVERROR(ENOMEM); - s->filter(ctx); + ctx->internal->execute(ctx, ifft_channel, out, NULL, outlink->channels); - out = ff_get_audio_buffer(outlink, s->hop_size); - if (!out) - return AVERROR(ENOMEM); + out->pts = s->pts; + if (s->pts != AV_NOPTS_VALUE) + s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); + av_audio_fifo_drain(s->fifo, FFMIN(av_audio_fifo_size(s->fifo), s->hop_size)); + + return ff_filter_frame(outlink, out); +} + +static int activate(AVFilterContext *ctx) +{ + AVFilterLink *inlink = ctx->inputs[0]; + AVFilterLink *outlink = ctx->outputs[0]; + AudioSurroundContext *s = ctx->priv; + AVFrame *in = NULL; + int ret = 0, status; + int64_t pts; - ctx->internal->execute(ctx, ifft_channel, out, NULL, outlink->channels); + FF_FILTER_FORWARD_STATUS_BACK(outlink, inlink); - out->pts = s->pts; - if (s->pts != AV_NOPTS_VALUE) - s->pts += av_rescale_q(out->nb_samples, (AVRational){1, outlink->sample_rate}, outlink->time_base); - av_audio_fifo_drain(s->fifo, s->hop_size); - ret = ff_filter_frame(outlink, out); + if (!s->eof && av_audio_fifo_size(s->fifo) < s->buf_size) { + ret = ff_inlink_consume_frame(inlink, &in); if (ret < 0) return ret; - } - return 0; -} + if (ret > 0) { + ret = av_audio_fifo_write(s->fifo, (void **)in->extended_data, + in->nb_samples); + if (ret >= 0 && s->pts == AV_NOPTS_VALUE) + s->pts = in->pts; -static int request_frame(AVFilterLink *outlink) -{ - AVFilterContext *ctx = outlink->src; - AudioSurroundContext *s = ctx->priv; - int ret = 0; + av_frame_free(&in); + if (ret < 0) + return ret; + } + } - ret = ff_request_frame(ctx->inputs[0]); + if ((av_audio_fifo_size(s->fifo) >= s->buf_size) || + (av_audio_fifo_size(s->fifo) > 0 && s->eof)) { + ret = filter_frame(inlink); + if (av_audio_fifo_size(s->fifo) >= s->buf_size) + ff_filter_set_ready(ctx, 100); + return ret; + } - if (ret == AVERROR_EOF && av_audio_fifo_size(s->fifo) > 0 && av_audio_fifo_size(s->fifo) < s->buf_size) { - AVFrame *in; + if (!s->eof && ff_inlink_acknowledge_status(inlink, &status, &pts)) { + if (status == AVERROR_EOF) { + s->eof = 1; + if (av_audio_fifo_size(s->fifo) >= 0) { + ff_filter_set_ready(ctx, 100); + return 0; + } + } + } - in = ff_get_audio_buffer(outlink, s->buf_size - av_audio_fifo_size(s->fifo)); - if (!in) - return AVERROR(ENOMEM); - ret = filter_frame(ctx->inputs[0], in); - av_audio_fifo_drain(s->fifo, s->buf_size); + if (s->eof && av_audio_fifo_size(s->fifo) <= 0) { + ff_outlink_set_status(outlink, AVERROR_EOF, s->pts); + return 0; } - return ret; + if (!s->eof) + FF_FILTER_FORWARD_WANTED(outlink, inlink); + + return FFERROR_NOT_READY; } static av_cold void uninit(AVFilterContext *ctx) @@ -1445,10 +1698,70 @@ static const AVOption surround_options[] = { { "lfe", "output LFE", OFFSET(output_lfe), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS }, { "lfe_low", "LFE low cut off", OFFSET(lowcutf), AV_OPT_TYPE_INT, {.i64=128}, 0, 256, FLAGS }, { "lfe_high", "LFE high cut off", OFFSET(highcutf), AV_OPT_TYPE_INT, {.i64=256}, 0, 512, FLAGS }, + { "lfe_mode", "set LFE channel mode", OFFSET(lfe_mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "lfe_mode" }, + { "add", "just add LFE channel", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 1, FLAGS, "lfe_mode" }, + { "sub", "substract LFE channel with others", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 1, FLAGS, "lfe_mode" }, + { "angle", "set soundfield transform angle", OFFSET(angle), AV_OPT_TYPE_FLOAT, {.dbl=90}, 0, 360, FLAGS }, { "fc_in", "set front center channel input level", OFFSET(fc_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, { "fc_out", "set front center channel output level", OFFSET(fc_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "fl_in", "set front left channel input level", OFFSET(fl_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "fl_out", "set front left channel output level", OFFSET(fl_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "fr_in", "set front right channel input level", OFFSET(fr_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "fr_out", "set front right channel output level", OFFSET(fr_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "sl_in", "set side left channel input level", OFFSET(sl_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "sl_out", "set side left channel output level", OFFSET(sl_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "sr_in", "set side right channel input level", OFFSET(sr_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "sr_out", "set side right channel output level", OFFSET(sr_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "bl_in", "set back left channel input level", OFFSET(bl_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "bl_out", "set back left channel output level", OFFSET(bl_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "br_in", "set back right channel input level", OFFSET(br_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "br_out", "set back right channel output level", OFFSET(br_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "bc_in", "set back center channel input level", OFFSET(bc_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "bc_out", "set back center channel output level", OFFSET(bc_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, { "lfe_in", "set lfe channel input level", OFFSET(lfe_in), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, { "lfe_out", "set lfe channel output level", OFFSET(lfe_out), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 10, FLAGS }, + { "allx", "set all channel's x spread", OFFSET(all_x), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 15, FLAGS }, + { "ally", "set all channel's y spread", OFFSET(all_y), AV_OPT_TYPE_FLOAT, {.dbl=-1}, -1, 15, FLAGS }, + { "fcx", "set front center channel x spread", OFFSET(fc_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "flx", "set front left channel x spread", OFFSET(fl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "frx", "set front right channel x spread", OFFSET(fr_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "blx", "set back left channel x spread", OFFSET(bl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "brx", "set back right channel x spread", OFFSET(br_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "slx", "set side left channel x spread", OFFSET(sl_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "srx", "set side right channel x spread", OFFSET(sr_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "bcx", "set back center channel x spread", OFFSET(bc_x), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "fcy", "set front center channel y spread", OFFSET(fc_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "fly", "set front left channel y spread", OFFSET(fl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "fry", "set front right channel y spread", OFFSET(fr_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "bly", "set back left channel y spread", OFFSET(bl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "bry", "set back right channel y spread", OFFSET(br_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "sly", "set side left channel y spread", OFFSET(sl_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "sry", "set side right channel y spread", OFFSET(sr_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "bcy", "set back center channel y spread", OFFSET(bc_y), AV_OPT_TYPE_FLOAT, {.dbl=1}, 0, 15, FLAGS }, + { "win_size", "set window size", OFFSET(win_size), AV_OPT_TYPE_INT, {.i64 = 4096}, 1024, 65536, FLAGS }, + { "win_func", "set window function", OFFSET(win_func), AV_OPT_TYPE_INT, {.i64 = WFUNC_HANNING}, 0, NB_WFUNC-1, FLAGS, "win_func" }, + { "rect", "Rectangular", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_RECT}, 0, 0, FLAGS, "win_func" }, + { "bartlett", "Bartlett", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BARTLETT}, 0, 0, FLAGS, "win_func" }, + { "hann", "Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" }, + { "hanning", "Hanning", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HANNING}, 0, 0, FLAGS, "win_func" }, + { "hamming", "Hamming", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_HAMMING}, 0, 0, FLAGS, "win_func" }, + { "blackman", "Blackman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BLACKMAN}, 0, 0, FLAGS, "win_func" }, + { "welch", "Welch", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_WELCH}, 0, 0, FLAGS, "win_func" }, + { "flattop", "Flat-top", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_FLATTOP}, 0, 0, FLAGS, "win_func" }, + { "bharris", "Blackman-Harris", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHARRIS}, 0, 0, FLAGS, "win_func" }, + { "bnuttall", "Blackman-Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BNUTTALL}, 0, 0, FLAGS, "win_func" }, + { "bhann", "Bartlett-Hann", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BHANN}, 0, 0, FLAGS, "win_func" }, + { "sine", "Sine", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_SINE}, 0, 0, FLAGS, "win_func" }, + { "nuttall", "Nuttall", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_NUTTALL}, 0, 0, FLAGS, "win_func" }, + { "lanczos", "Lanczos", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_LANCZOS}, 0, 0, FLAGS, "win_func" }, + { "gauss", "Gauss", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_GAUSS}, 0, 0, FLAGS, "win_func" }, + { "tukey", "Tukey", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_TUKEY}, 0, 0, FLAGS, "win_func" }, + { "dolph", "Dolph-Chebyshev", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_DOLPH}, 0, 0, FLAGS, "win_func" }, + { "cauchy", "Cauchy", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_CAUCHY}, 0, 0, FLAGS, "win_func" }, + { "parzen", "Parzen", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_PARZEN}, 0, 0, FLAGS, "win_func" }, + { "poisson", "Poisson", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_POISSON}, 0, 0, FLAGS, "win_func" }, + { "bohman", "Bohman", 0, AV_OPT_TYPE_CONST, {.i64=WFUNC_BOHMAN}, 0, 0, FLAGS, "win_func" }, + { "overlap", "set window overlap", OFFSET(overlap), AV_OPT_TYPE_FLOAT, {.dbl=0.5}, 0, 1, FLAGS }, { NULL } }; @@ -1458,7 +1771,6 @@ static const AVFilterPad inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .filter_frame = filter_frame, .config_props = config_input, }, { NULL } @@ -1468,7 +1780,6 @@ static const AVFilterPad outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_AUDIO, - .request_frame = request_frame, .config_props = config_output, }, { NULL } @@ -1482,6 +1793,7 @@ AVFilter ff_af_surround = { .priv_class = &surround_class, .init = init, .uninit = uninit, + .activate = activate, .inputs = inputs, .outputs = outputs, .flags = AVFILTER_FLAG_SLICE_THREADS,