|
|
|
@ -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; |
|
|
|
|