| @@ -40,6 +40,7 @@ typedef struct AudioDynamicEqualizerContext { · 39 unmodified lines |
| 40 | double release_coef; | 40 | double release_coef; |
| 41 | int mode; | 41 | int mode; |
| 42 | int direction; | 42 | int direction; |
| | 43 | int detection; |
| 43 | int type; | 44 | int type; |
| 44 | | 45 | |
| 45 | AVFrame *state; | 46 | AVFrame *state; |
| @@ -92,7 +93,6 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 46 unmodified lines |
| 92 | const double range = s->range; | 93 | const double range = s->range; |
| 93 | const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); | 94 | const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); |
| 94 | const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); | 95 | const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); |
| 95 | const double threshold = s->threshold; | | |
| 96 | const double release = s->release_coef; | 96 | const double release = s->release_coef; |
| 97 | const double irelease = 1. - release; | 97 | const double irelease = 1. - release; |
| 98 | const double attack = s->attack_coef; | 98 | const double attack = s->attack_coef; |
| @@ -103,6 +103,7 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 4 unmodified lines |
| 103 | const double dg = tan(M_PI * dfrequency / sample_rate); | 103 | const double dg = tan(M_PI * dfrequency / sample_rate); |
| 104 | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; | 104 | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; |
| 105 | const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; | 105 | const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; |
| | 106 | const int detection = s->detection; |
| 106 | const int direction = s->direction; | 107 | const int direction = s->direction; |
| 107 | const int mode = s->mode; | 108 | const int mode = s->mode; |
| 108 | const int type = s->type; | 109 | const int type = s->type; |
| @@ -124,6 +125,10 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 15 unmodified lines |
| 124 | const double *src = (const double *)in->extended_data[ch]; | 125 | const double *src = (const double *)in->extended_data[ch]; |
| 125 | double *dst = (double *)out->extended_data[ch]; | 126 | double *dst = (double *)out->extended_data[ch]; |
| 126 | double *state = (double *)s->state->extended_data[ch]; | 127 | double *state = (double *)s->state->extended_data[ch]; |
| | 128 | const double threshold = detection == 0 ? state[5] : s->threshold; |
| | 129 | |
| | 130 | if (detection < 0) |
| | 131 | state[5] = threshold; |
| 127 | | 132 | |
| 128 | for (int n = 0; n < out->nb_samples; n++) { | 133 | for (int n = 0; n < out->nb_samples; n++) { |
| 129 | double detect, gain, v, listen; | 134 | double detect, gain, v, listen; |
| @@ -133,6 +138,9 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 3 unmodified lines |
| 133 | detect = listen = get_svf(src[n], dm, da, state); | 138 | detect = listen = get_svf(src[n], dm, da, state); |
| 134 | detect = fabs(detect); | 139 | detect = fabs(detect); |
| 135 | | 140 | |
| | 141 | if (detection > 0) |
| | 142 | state[5] = fmax(state[5], detect); |
| | 143 | |
| 136 | if (direction == 0 && mode == 0 && detect < threshold) | 144 | if (direction == 0 && mode == 0 && detect < threshold) |
| 137 | detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); | 145 | detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); |
| 138 | else if (direction == 0 && mode == 1 && detect < threshold) | 146 | else if (direction == 0 && mode == 1 && detect < threshold) |
| @@ -144,10 +152,18 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 5 unmodified lines |
| 144 | else | 152 | else |
| 145 | detect = 1.; | 153 | detect = 1.; |
| 146 | | 154 | |
| 147 | if (detect < state[4]) { | 155 | if (direction == 0) { |
| 148 | detect = iattack * detect + attack * state[4]; | 156 | if (detect > state[4]) { |
| | 157 | detect = iattack * detect + attack * state[4]; |
| | 158 | } else { |
| | 159 | detect = irelease * detect + release * state[4]; |
| | 160 | } |
| 149 | } else { | 161 | } else { |
| 150 | detect = irelease * detect + release * state[4]; | 162 | if (detect < state[4]) { |
| | 163 | detect = iattack * detect + attack * state[4]; |
| | 164 | } else { |
| | 165 | detect = irelease * detect + release * state[4]; |
| | 166 | } |
| 151 | } | 167 | } |
| 152 | | 168 | |
| 153 | if (state[4] != detect || n == 0) { | 169 | if (state[4] != detect || n == 0) { |
| @@ -270,6 +286,10 @@ static const AVOption adynamicequalizer_options[] = { · 116 unmodified lines |
| 270 | { "direction", "set direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "direction" }, | 286 | { "direction", "set direction", OFFSET(direction), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, "direction" }, |
| 271 | { "downward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "direction" }, | 287 | { "downward", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "direction" }, |
| 272 | { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" }, | 288 | { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" }, |
| | 289 | { "auto", "set auto threshold", OFFSET(detection), AV_OPT_TYPE_INT, {.i64=-1}, -1, 1, FLAGS, "auto" }, |
| | 290 | { "disabled", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "auto" }, |
| | 291 | { "off", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "auto" }, |
| | 292 | { "on", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "auto" }, |
| 273 | { NULL } | 293 | { NULL } |
| 274 | }; | 294 | }; |
| 275 | | 295 | |