diff options
author | Paul B Mahol <onemda@gmail.com> | 2019-04-17 23:33:51 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2019-04-17 23:36:39 +0200 |
commit | 8a3ed5a3136461bc0460de8d0de48f3093719de6 (patch) | |
tree | 56c0c1867a8e5b5163120761b16d13f9f35beeff /libavfilter/af_agate.c | |
parent | a0559fcd81f42f446c93357a943699f9d44eeb79 (diff) | |
download | ffmpeg-8a3ed5a3136461bc0460de8d0de48f3093719de6.tar.gz |
avfilter/af_agate: implement mode option
Diffstat (limited to 'libavfilter/af_agate.c')
-rw-r--r-- | libavfilter/af_agate.c | 57 |
1 files changed, 34 insertions, 23 deletions
diff --git a/libavfilter/af_agate.c b/libavfilter/af_agate.c index ba96863a68..0609dc222e 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; @@ -65,6 +67,9 @@ typedef struct AudioGateContext { 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; |