avfilter/af_adynamicequalizer: merge direction option with mode option
More user-friendly and self-explanatory what certain mode does.
This commit is contained in:
@@ -1054,12 +1054,16 @@ Set the mode of filter operation, can be one of the following:
|
|||||||
@table @samp
|
@table @samp
|
||||||
@item listen
|
@item listen
|
||||||
Output only isolated detection signal.
|
Output only isolated detection signal.
|
||||||
@item cut
|
@item cutbelow
|
||||||
|
Cut frequencies below detection threshold.
|
||||||
|
@item cutabove
|
||||||
Cut frequencies above detection threshold.
|
Cut frequencies above detection threshold.
|
||||||
@item boost
|
@item boostbelow
|
||||||
Boost frequencies bellow detection threshold.
|
Boost frequencies below detection threshold.
|
||||||
|
@item boostabove
|
||||||
|
Boost frequencies above detection threshold.
|
||||||
@end table
|
@end table
|
||||||
Default mode is @samp{cut}.
|
Default mode is @samp{cutbelow}.
|
||||||
|
|
||||||
@item dftype
|
@item dftype
|
||||||
Set the type of detection filter, can be one of the following:
|
Set the type of detection filter, can be one of the following:
|
||||||
@@ -1082,16 +1086,6 @@ Set the type of target filter, can be one of the following:
|
|||||||
@end table
|
@end table
|
||||||
Default type is @samp{bell}.
|
Default type is @samp{bell}.
|
||||||
|
|
||||||
@item direction
|
|
||||||
Set processing direction relative to threshold.
|
|
||||||
@table @samp
|
|
||||||
@item downward
|
|
||||||
Boost/Cut if threshold is higher/lower than detected volume.
|
|
||||||
@item upward
|
|
||||||
Boost/Cut if threshold is lower/higher than detected volume.
|
|
||||||
@end table
|
|
||||||
Default direction is @samp{downward}.
|
|
||||||
|
|
||||||
@item auto
|
@item auto
|
||||||
Automatically gather threshold from detection filter. By default
|
Automatically gather threshold from detection filter. By default
|
||||||
is @samp{disabled}.
|
is @samp{disabled}.
|
||||||
|
@@ -157,7 +157,6 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
|
|||||||
const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
|
const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs;
|
||||||
const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
|
const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
|
||||||
const int detection = s->detection;
|
const int detection = s->detection;
|
||||||
const int direction = s->direction;
|
|
||||||
const int tftype = s->tftype;
|
const int tftype = s->tftype;
|
||||||
const int mode = s->mode;
|
const int mode = s->mode;
|
||||||
const ftype *da = fn(s->da);
|
const ftype *da = fn(s->da);
|
||||||
@@ -177,7 +176,7 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
|
|||||||
fn(cc->threshold) = threshold;
|
fn(cc->threshold) = threshold;
|
||||||
|
|
||||||
for (int n = 0; n < out->nb_samples; n++) {
|
for (int n = 0; n < out->nb_samples; n++) {
|
||||||
ftype detect, v, listen;
|
ftype detect, v, listen, new_gain = ONE;
|
||||||
ftype k, g;
|
ftype k, g;
|
||||||
|
|
||||||
detect = listen = fn(get_svf)(src[n], dm, da, dstate);
|
detect = listen = fn(get_svf)(src[n], dm, da, dstate);
|
||||||
@@ -186,31 +185,38 @@ static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int n
|
|||||||
if (detection > 0)
|
if (detection > 0)
|
||||||
fn(cc->threshold) = FMAX(fn(cc->threshold), detect);
|
fn(cc->threshold) = FMAX(fn(cc->threshold), detect);
|
||||||
|
|
||||||
if (mode >= 0) {
|
switch (mode) {
|
||||||
if (direction == 0 && detect < threshold) {
|
case LISTEN:
|
||||||
detect = CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range);
|
break;
|
||||||
if (!mode)
|
case CUT_BELOW:
|
||||||
detect = ONE / detect;
|
if (detect < threshold)
|
||||||
} else if (direction == 1 && detect > threshold) {
|
new_gain = ONE / CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range);
|
||||||
detect = CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range);
|
break;
|
||||||
if (!mode)
|
case CUT_ABOVE:
|
||||||
detect = ONE / detect;
|
if (detect > threshold)
|
||||||
} else {
|
new_gain = ONE / CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range);
|
||||||
detect = ONE;
|
break;
|
||||||
}
|
case BOOST_BELOW:
|
||||||
|
if (detect < threshold)
|
||||||
{
|
new_gain = CLIP(ONE + makeup + (threshold - detect) * ratio, ONE, range);
|
||||||
ftype delta = detect - gain;
|
break;
|
||||||
|
case BOOST_ABOVE:
|
||||||
if (delta > EPSILON)
|
if (detect > threshold)
|
||||||
detect = gain + attack * delta;
|
new_gain = CLIP(ONE + makeup + (detect - threshold) * ratio, ONE, range);
|
||||||
else if (delta < -EPSILON)
|
break;
|
||||||
detect = gain + release * delta;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gain != detect) {
|
if (mode > LISTEN) {
|
||||||
gain = detect;
|
ftype delta = new_gain - gain;
|
||||||
|
|
||||||
|
if (delta > EPSILON)
|
||||||
|
new_gain = gain + attack * delta;
|
||||||
|
else if (delta < -EPSILON)
|
||||||
|
new_gain = gain + release * delta;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gain != new_gain) {
|
||||||
|
gain = new_gain;
|
||||||
|
|
||||||
switch (tftype) {
|
switch (tftype) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@@ -23,6 +23,15 @@
|
|||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
|
|
||||||
|
enum FilterModes {
|
||||||
|
LISTEN = -1,
|
||||||
|
CUT_BELOW,
|
||||||
|
CUT_ABOVE,
|
||||||
|
BOOST_BELOW,
|
||||||
|
BOOST_ABOVE,
|
||||||
|
NB_MODES,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct ChannelContext {
|
typedef struct ChannelContext {
|
||||||
double fa_double[3], fm_double[3];
|
double fa_double[3], fm_double[3];
|
||||||
double dstate_double[2];
|
double dstate_double[2];
|
||||||
@@ -52,7 +61,6 @@ typedef struct AudioDynamicEqualizerContext {
|
|||||||
double attack_coef;
|
double attack_coef;
|
||||||
double release_coef;
|
double release_coef;
|
||||||
int mode;
|
int mode;
|
||||||
int direction;
|
|
||||||
int detection;
|
int detection;
|
||||||
int tftype;
|
int tftype;
|
||||||
int dftype;
|
int dftype;
|
||||||
@@ -179,10 +187,12 @@ static const AVOption adynamicequalizer_options[] = {
|
|||||||
{ "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 30, FLAGS },
|
{ "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 30, FLAGS },
|
||||||
{ "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS },
|
{ "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS },
|
||||||
{ "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 200, FLAGS },
|
{ "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 200, FLAGS },
|
||||||
{ "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" },
|
{ "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, LISTEN,NB_MODES-1,FLAGS, "mode" },
|
||||||
{ "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" },
|
{ "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=LISTEN}, 0, 0, FLAGS, "mode" },
|
||||||
{ "cut", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" },
|
{ "cutbelow", 0, 0, AV_OPT_TYPE_CONST, {.i64=CUT_BELOW},0, 0, FLAGS, "mode" },
|
||||||
{ "boost", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "mode" },
|
{ "cutabove", 0, 0, AV_OPT_TYPE_CONST, {.i64=CUT_ABOVE},0, 0, FLAGS, "mode" },
|
||||||
|
{ "boostbelow", 0, 0, AV_OPT_TYPE_CONST, {.i64=BOOST_BELOW},0, 0, FLAGS, "mode" },
|
||||||
|
{ "boostabove", 0, 0, AV_OPT_TYPE_CONST, {.i64=BOOST_ABOVE},0, 0, FLAGS, "mode" },
|
||||||
{ "dftype", "set detection filter type",OFFSET(dftype), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "dftype" },
|
{ "dftype", "set detection filter type",OFFSET(dftype), AV_OPT_TYPE_INT, {.i64=0}, 0, 3, FLAGS, "dftype" },
|
||||||
{ "bandpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "dftype" },
|
{ "bandpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "dftype" },
|
||||||
{ "lowpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "dftype" },
|
{ "lowpass", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "dftype" },
|
||||||
@@ -192,9 +202,6 @@ static const AVOption adynamicequalizer_options[] = {
|
|||||||
{ "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "tftype" },
|
{ "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "tftype" },
|
||||||
{ "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "tftype" },
|
{ "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "tftype" },
|
||||||
{ "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "tftype" },
|
{ "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "tftype" },
|
||||||
{ "direction", "set direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "direction" },
|
|
||||||
{ "downward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "direction" },
|
|
||||||
{ "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" },
|
|
||||||
{ "auto", "set auto threshold", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "auto" },
|
{ "auto", "set auto threshold", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "auto" },
|
||||||
{ "disabled", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "auto" },
|
{ "disabled", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "auto" },
|
||||||
{ "off", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "auto" },
|
{ "off", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "auto" },
|
||||||
|
Reference in New Issue
Block a user