X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavfilter%2Faf_agate.c;h=5fcf6eceb110e2f2836fd67d4ec043869a321f47;hb=252500a78fe1a31abc79e6070d16f50382c39343;hp=ba96863a688a53991a6c274d4fcf7f3322a71d8c;hpb=4dc1f06f0c84ebbd8b26cd77679450903244a3e8;p=ffmpeg diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c index ba96863a688..5fcf6eceb11 100644 --- a/libavfilter/af_agate.c +++ b/libavfilter/af_agate.c @@ -47,11 +47,13 @@ typedef struct AudioGateContext { double range; int link; int detection; + int mode; double thres; double knee_start; - double lin_knee_stop; double knee_stop; + double lin_knee_start; + double lin_knee_stop; double lin_slope; double attack_coeff; double release_coeff; @@ -61,10 +63,13 @@ typedef struct AudioGateContext { } AudioGateContext; #define OFFSET(x) offsetof(AudioGateContext, x) -#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM +#define A AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM static const AVOption options[] = { { "level_in", "set input level", OFFSET(level_in), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.015625, 64, A }, + { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, A, "mode" }, + { "downward",0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, A, "mode" }, + { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, A, "mode" }, { "range", "set max gain reduction", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=0.06125}, 0, 1, A }, { "threshold", "set threshold", OFFSET(threshold), AV_OPT_TYPE_DOUBLE, {.dbl=0.125}, 0, 1, A }, { "ratio", "set ratio", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=2}, 1, 9000, A }, @@ -88,7 +93,6 @@ static int agate_config_input(AVFilterLink *inlink) AudioGateContext *s = ctx->priv; double lin_threshold = s->threshold; double lin_knee_sqrt = sqrt(s->knee); - double lin_knee_start; if (s->detection) lin_threshold *= lin_threshold; @@ -96,9 +100,9 @@ static int agate_config_input(AVFilterLink *inlink) s->attack_coeff = FFMIN(1., 1. / (s->attack * inlink->sample_rate / 4000.)); s->release_coeff = FFMIN(1., 1. / (s->release * inlink->sample_rate / 4000.)); s->lin_knee_stop = lin_threshold * lin_knee_sqrt; - lin_knee_start = lin_threshold / lin_knee_sqrt; + s->lin_knee_start = lin_threshold / lin_knee_sqrt; s->thres = log(lin_threshold); - s->knee_start = log(lin_knee_start); + s->knee_start = log(s->lin_knee_start); s->knee_stop = log(s->lin_knee_stop); return 0; @@ -112,26 +116,26 @@ static int agate_config_input(AVFilterLink *inlink) static double output_gain(double lin_slope, double ratio, double thres, double knee, double knee_start, double knee_stop, - double lin_knee_stop, double range) + double range, int mode) { - if (lin_slope < lin_knee_stop) { - double slope = log(lin_slope); - double tratio = ratio; - double gain = 0.; - double delta = 0.; - - if (IS_FAKE_INFINITY(ratio)) - tratio = 1000.; - gain = (slope - thres) * tratio + thres; - delta = tratio; - - if (knee > 1. && slope > knee_start) { + double slope = log(lin_slope); + double tratio = ratio; + double gain = 0.; + double delta = 0.; + + if (IS_FAKE_INFINITY(ratio)) + tratio = 1000.; + gain = (slope - thres) * tratio + thres; + delta = tratio; + + if (mode) { + if (knee > 1. && slope < knee_stop) + gain = hermite_interpolation(slope, knee_stop, knee_start, ((knee_stop - thres) * tratio + thres), knee_start, delta, 1.); + } else { + if (knee > 1. && slope > knee_start) gain = hermite_interpolation(slope, knee_start, knee_stop, ((knee_start - thres) * tratio + thres), knee_stop, delta, 1.); - } - return FFMAX(range, exp(gain - slope)); } - - return 1.; + return FFMAX(range, exp(gain - slope)); } static void gate(AudioGateContext *s, @@ -146,6 +150,7 @@ static void gate(AudioGateContext *s, for (n = 0; n < nb_samples; n++, src += inlink->channels, dst += inlink->channels, scsrc += sclink->channels) { double abs_sample = fabs(scsrc[0] * level_sc), gain = 1.0; + int detected; if (s->link == 1) { for (c = 1; c < sclink->channels; c++) @@ -161,10 +166,16 @@ static void gate(AudioGateContext *s, abs_sample *= abs_sample; s->lin_slope += (abs_sample - s->lin_slope) * (abs_sample > s->lin_slope ? attack_coeff : release_coeff); - if (s->lin_slope > 0.0) + + if (s->mode) + detected = s->lin_slope > s->lin_knee_start; + else + detected = s->lin_slope < s->lin_knee_stop; + + if (s->lin_slope > 0.0 && detected) gain = output_gain(s->lin_slope, s->ratio, s->thres, s->knee, s->knee_start, s->knee_stop, - s->lin_knee_stop, s->range); + s->range, s->mode); for (c = 0; c < inlink->channels; c++) dst[c] = src[c] * level_in * gain * makeup; @@ -257,6 +268,8 @@ AVFilter ff_af_agate = { .priv_class = &agate_class, .inputs = inputs, .outputs = outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_AGATE_FILTER */ @@ -307,7 +320,7 @@ static int activate(AVFilterContext *ctx) dst = (double *)out->data[0]; out->pts = s->pts; - s->pts += nb_samples; + s->pts += av_rescale_q(nb_samples, (AVRational){1, ctx->outputs[0]->sample_rate}, ctx->outputs[0]->time_base); gate(s, (double *)in[0]->data[0], dst, (double *)in[1]->data[0], nb_samples, @@ -342,20 +355,20 @@ static int scquery_formats(AVFilterContext *ctx) }; int ret, i; - if (!ctx->inputs[0]->in_channel_layouts || - !ctx->inputs[0]->in_channel_layouts->nb_channel_layouts) { + if (!ctx->inputs[0]->incfg.channel_layouts || + !ctx->inputs[0]->incfg.channel_layouts->nb_channel_layouts) { av_log(ctx, AV_LOG_WARNING, "No channel layout for input 1\n"); return AVERROR(EAGAIN); } - if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->in_channel_layouts->channel_layouts[0])) < 0 || - (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->in_channel_layouts)) < 0) + if ((ret = ff_add_channel_layout(&layouts, ctx->inputs[0]->incfg.channel_layouts->channel_layouts[0])) < 0 || + (ret = ff_channel_layouts_ref(layouts, &ctx->outputs[0]->incfg.channel_layouts)) < 0) return ret; for (i = 0; i < 2; i++) { layouts = ff_all_channel_counts(); - if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->out_channel_layouts)) < 0) + if ((ret = ff_channel_layouts_ref(layouts, &ctx->inputs[i]->outcfg.channel_layouts)) < 0) return ret; } @@ -434,5 +447,7 @@ AVFilter ff_af_sidechaingate = { .uninit = uninit, .inputs = sidechaingate_inputs, .outputs = sidechaingate_outputs, + .process_command = ff_filter_process_command, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, }; #endif /* CONFIG_SIDECHAINGATE_FILTER */