Showing the changes to libavfilter (1 of 2 files). Show all
Unified · Split
| @@ -34,13 +34,12 @@ typedef struct AudioDynamicEqualizerContext { · 33 unmodified lines | |||
| 34 | double ratio; | 34 | double ratio; |
| 35 | double range; | 35 | double range; |
| 36 | double makeup; | 36 | double makeup; |
| 37 | double knee; | ||
| 38 | double slew; | ||
| 39 | double attack; | 37 | double attack; |
| 40 | double release; | 38 | double release; |
| 41 | double attack_coef; | 39 | double attack_coef; |
| 42 | double release_coef; | 40 | double release_coef; |
| 43 | int mode; | 41 | int mode; |
| 42 | int direction; | ||
| 44 | int type; | 43 | int type; |
| 45 | 44 | ||
| 46 | AVFrame *state; | 45 | AVFrame *state; |
| @@ -55,6 +54,12 @@ static int config_input(AVFilterLink *inlink) · 8 unmodified lines | |||
| 55 | if (!s->state) | 54 | if (!s->state) |
| 56 | return AVERROR(ENOMEM); | 55 | return AVERROR(ENOMEM); |
| 57 | 56 | ||
| 57 | for (int ch = 0; ch < inlink->ch_layout.nb_channels; ch++) { | ||
| 58 | double *state = (double *)s->state->extended_data[ch]; | ||
| 59 | |||
| 60 | state[4] = 1.; | ||
| 61 | } | ||
| 62 | |||
| 58 | return 0; | 63 | return 0; |
| 59 | } | 64 | } |
| 60 | 65 | ||
| @@ -71,69 +76,6 @@ static double get_svf(double in, double *m, double *a, double *b) · 10 unmodified lines | |||
| 71 | return m[0] * v0 + m[1] * v1 + m[2] * v2; | 76 | return m[0] * v0 + m[1] * v1 + m[2] * v2; |
| 72 | } | 77 | } |
| 73 | 78 | ||
| 74 | static inline double from_dB(double x) | ||
| 75 | { | ||
| 76 | return exp(0.05 * x * M_LN10); | ||
| 77 | } | ||
| 78 | |||
| 79 | static inline double to_dB(double x) | ||
| 80 | { | ||
| 81 | return 20. * log10(x); | ||
| 82 | } | ||
| 83 | |||
| 84 | static inline double sqr(double x) | ||
| 85 | { | ||
| 86 | return x * x; | ||
| 87 | } | ||
| 88 | |||
| 89 | static double get_gain(double in, double srate, double makeup, | ||
| 90 | double aattack, double iratio, double knee, double range, | ||
| 91 | double thresdb, double slewfactor, double *state, | ||
| 92 | double attack_coeff, double release_coeff, double nc) | ||
| 93 | { | ||
| 94 | double width = (6. * knee) + 0.01; | ||
| 95 | double cdb = 0.; | ||
| 96 | double Lgain = 1.; | ||
| 97 | double Lxg, Lxl, Lyg, Lyl, Ly1; | ||
| 98 | double checkwidth = 0.; | ||
| 99 | double slewwidth = 1.8; | ||
| 100 | int attslew = 0; | ||
| 101 | |||
| 102 | Lyg = 0.; | ||
| 103 | Lxg = to_dB(fabs(in) + DBL_EPSILON); | ||
| 104 | |||
| 105 | Lyg = Lxg + (iratio - 1.) * sqr(Lxg - thresdb + width * .5) / (2. * width); | ||
| 106 | |||
| 107 | checkwidth = 2. * fabs(Lxg - thresdb); | ||
| 108 | if (2. * (Lxg - thresdb) < -width) { | ||
| 109 | Lyg = Lxg; | ||
| 110 | } else if (checkwidth <= width) { | ||
| 111 | Lyg = thresdb + (Lxg - thresdb) * iratio; | ||
| 112 | if (checkwidth <= slewwidth) { | ||
| 113 | if (Lyg >= state[2]) | ||
| 114 | attslew = 1; | ||
| 115 | } | ||
| 116 | } else if (2. * (Lxg - thresdb) > width) { | ||
| 117 | Lyg = thresdb + (Lxg - thresdb) * iratio; | ||
| 118 | } | ||
| 119 | |||
| 120 | attack_coeff = attslew ? aattack : attack_coeff; | ||
| 121 | |||
| 122 | Lxl = Lxg - Lyg; | ||
| 123 | |||
| 124 | Ly1 = fmax(Lxl, release_coeff * state[1] +(1. - release_coeff) * Lxl); | ||
| 125 | Lyl = attack_coeff * state[0] + (1. - attack_coeff) * Ly1; | ||
| 126 | |||
| 127 | cdb = -Lyl; | ||
| 128 | Lgain = from_dB(nc * fmin(cdb - makeup, range)); | ||
| 129 | |||
| 130 | state[0] = Lyl; | ||
| 131 | state[1] = Ly1; | ||
| 132 | state[2] = Lyg; | ||
| 133 | |||
| 134 | return Lgain; | ||
| 135 | } | ||
| 136 | |||
| 137 | typedef struct ThreadData { | 79 | typedef struct ThreadData { |
| 138 | AVFrame *in, *out; | 80 | AVFrame *in, *out; |
| 139 | } ThreadData; | 81 | } ThreadData; |
| @@ -146,25 +88,24 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 6 unmodified lines | |||
| 146 | AVFrame *out = td->out; | 88 | AVFrame *out = td->out; |
| 147 | const double sample_rate = in->sample_rate; | 89 | const double sample_rate = in->sample_rate; |
| 148 | const double makeup = s->makeup; | 90 | const double makeup = s->makeup; |
| 149 | const double iratio = 1. / s->ratio; | 91 | const double ratio = s->ratio; |
| 150 | const double range = s->range; | 92 | const double range = s->range; |
| 151 | const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); | 93 | const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); |
| 152 | const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); | 94 | const double tfrequency = fmin(s->tfrequency, sample_rate * 0.5); |
| 153 | const double threshold = to_dB(s->threshold + DBL_EPSILON); | 95 | const double threshold = s->threshold; |
| 154 | const double release = s->release_coef; | 96 | const double release = s->release_coef; |
| 97 | const double irelease = 1. - release; | ||
| 155 | const double attack = s->attack_coef; | 98 | const double attack = s->attack_coef; |
| 99 | const double iattack = 1. - attack; | ||
| 156 | const double dqfactor = s->dqfactor; | 100 | const double dqfactor = s->dqfactor; |
| 157 | const double tqfactor = s->tqfactor; | 101 | const double tqfactor = s->tqfactor; |
| 158 | const double fg = tan(M_PI * tfrequency / sample_rate); | 102 | const double fg = tan(M_PI * tfrequency / sample_rate); |
| 159 | const double dg = tan(M_PI * dfrequency / sample_rate); | 103 | const double dg = tan(M_PI * dfrequency / sample_rate); |
| 160 | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; | 104 | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; |
| 161 | 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 direction = s->direction; | ||
| 162 | const int mode = s->mode; | 107 | const int mode = s->mode; |
| 163 | const int type = s->type; | 108 | const int type = s->type; |
| 164 | const double knee = s->knee; | ||
| 165 | const double slew = s->slew; | ||
| 166 | const double aattack = exp(-1000. / ((s->attack + 2.0 * (slew - 1.)) * sample_rate)); | ||
| 167 | const double nc = mode == 0 ? 1. : -1.; | ||
| 168 | double da[3], dm[3]; | 109 | double da[3], dm[3]; |
| 169 | 110 | ||
| 170 | { | 111 | { |
| @@ -175,7 +116,7 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 4 unmodified lines | |||
| 175 | da[2] = dg * da[1]; | 116 | da[2] = dg * da[1]; |
| 176 | 117 | ||
| 177 | dm[0] = 0.; | 118 | dm[0] = 0.; |
| 178 | dm[1] = 1.; | 119 | dm[1] = k; |
| 179 | dm[2] = 0.; | 120 | dm[2] = 0.; |
| 180 | } | 121 | } |
| 181 | 122 | ||
| @@ -192,46 +133,63 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 10 unmodified lines | |||
| 192 | detect = listen = get_svf(src[n], dm, da, state); | 133 | detect = listen = get_svf(src[n], dm, da, state); |
| 193 | detect = fabs(detect); | 134 | detect = fabs(detect); |
| 194 | 135 | ||
| 195 | gain = get_gain(detect, sample_rate, makeup, | 136 | if (direction == 0 && mode == 0 && detect < threshold) |
| 196 | aattack, iratio, knee, range, threshold, slew, | 137 | detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); |
| 197 | &state[4], attack, release, nc); | 138 | else if (direction == 0 && mode == 1 && detect < threshold) |
| 198 | 139 | detect = av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); | |
| 199 | switch (type) { | 140 | else if (direction == 1 && mode == 0 && detect > threshold) |
| 200 | case 0: | 141 | detect = 1. / av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); |
| 201 | k = 1. / (tqfactor * gain); | 142 | else if (direction == 1 && mode == 1 && detect > threshold) |
| 202 | 143 | detect = av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); | |
| 203 | fa[0] = 1. / (1. + fg * (fg + k)); | 144 | else |
| 204 | fa[1] = fg * fa[0]; | 145 | detect = 1.; |
| 205 | fa[2] = fg * fa[1]; | 146 | |
| 206 | 147 | if (detect < state[4]) { | |
| 207 | fm[0] = 1.; | 148 | detect = iattack * detect + attack * state[4]; |
| 208 | fm[1] = k * (gain * gain - 1.); | 149 | } else { |
| 209 | fm[2] = 0.; | 150 | detect = irelease * detect + release * state[4]; |
| 210 | break; | 151 | } |
| 211 | case 1: | 152 | |
| 212 | k = 1. / tqfactor; | 153 | if (state[4] != detect || n == 0) { |
| 213 | g = fg / sqrt(gain); | 154 | state[4] = gain = detect; |
| 214 | 155 | ||
| 215 | fa[0] = 1. / (1. + g * (g + k)); | 156 | switch (type) { |
| 216 | fa[1] = g * fa[0]; | 157 | case 0: |
| 217 | fa[2] = g * fa[1]; | 158 | k = 1. / (tqfactor * gain); |
| 218 | 159 | ||
| 219 | fm[0] = 1.; | 160 | fa[0] = 1. / (1. + fg * (fg + k)); |
| 220 | fm[1] = k * (gain - 1.); | 161 | fa[1] = fg * fa[0]; |
| 221 | fm[2] = gain * gain - 1.; | 162 | fa[2] = fg * fa[1]; |
| 222 | break; | 163 | |
| 223 | case 2: | 164 | fm[0] = 1.; |
| 224 | k = 1. / tqfactor; | 165 | fm[1] = k * (gain * gain - 1.); |
| 225 | g = fg / sqrt(gain); | 166 | fm[2] = 0.; |
| 226 | 167 | break; | |
| 227 | fa[0] = 1. / (1. + g * (g + k)); | 168 | case 1: |
| 228 | fa[1] = g * fa[0]; | 169 | k = 1. / tqfactor; |
| 229 | fa[2] = g * fa[1]; | 170 | g = fg / sqrt(gain); |
| 230 | 171 | ||
| 231 | fm[0] = gain * gain; | 172 | fa[0] = 1. / (1. + g * (g + k)); |
| 232 | fm[1] = k * (1. - gain) * gain; | 173 | fa[1] = g * fa[0]; |
| 233 | fm[2] = 1. - gain * gain; | 174 | fa[2] = g * fa[1]; |
| 234 | break; | 175 | |
| 176 | fm[0] = 1.; | ||
| 177 | fm[1] = k * (gain - 1.); | ||
| 178 | fm[2] = gain * gain - 1.; | ||
| 179 | break; | ||
| 180 | case 2: | ||
| 181 | k = 1. / tqfactor; | ||
| 182 | g = fg / sqrt(gain); | ||
| 183 | |||
| 184 | fa[0] = 1. / (1. + g * (g + k)); | ||
| 185 | fa[1] = g * fa[0]; | ||
| 186 | fa[2] = g * fa[1]; | ||
| 187 | |||
| 188 | fm[0] = gain * gain; | ||
| 189 | fm[1] = k * (1. - gain) * gain; | ||
| 190 | fm[2] = 1. - gain * gain; | ||
| 191 | break; | ||
| 192 | } | ||
| 235 | } | 193 | } |
| 236 | 194 | ||
| 237 | v = get_svf(src[n], fm, fa, &state[2]); | 195 | v = get_svf(src[n], fm, fa, &state[2]); |
| @@ -298,11 +256,9 @@ static const AVOption adynamicequalizer_options[] = { · 60 unmodified lines | |||
| 298 | { "tqfactor", "set target Q factor", OFFSET(tqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, | 256 | { "tqfactor", "set target Q factor", OFFSET(tqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, |
| 299 | { "attack", "set attack duration", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 2000, FLAGS }, | 257 | { "attack", "set attack duration", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 2000, FLAGS }, |
| 300 | { "release", "set release duration", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=200}, 1, 2000, FLAGS }, | 258 | { "release", "set release duration", OFFSET(release), AV_OPT_TYPE_DOUBLE, {.dbl=200}, 1, 2000, FLAGS }, |
| 301 | { "knee", "set knee factor", OFFSET(knee), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 8, FLAGS }, | 259 | { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 30, FLAGS }, |
| 302 | { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 20, FLAGS }, | 260 | { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS }, |
| 303 | { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 30, FLAGS }, | 261 | { "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 200, FLAGS }, |
| 304 | { "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 200, FLAGS }, | ||
| 305 | { "slew", "set slew factor", OFFSET(slew), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 200, FLAGS }, | ||
| 306 | { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" }, | 262 | { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" }, |
| 307 | { "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" }, | 263 | { "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" }, |
| 308 | { "cut", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, | 264 | { "cut", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "mode" }, |
| @@ -311,6 +267,9 @@ static const AVOption adynamicequalizer_options[] = { · 2 unmodified lines | |||
| 311 | { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, | 267 | { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, |
| 312 | { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, | 268 | { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, |
| 313 | { "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "type" }, | 269 | { "highshelf",0, 0, AV_OPT_TYPE_CONST, {.i64=2}, 0, 0, FLAGS, "type" }, |
| 270 | { "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" }, | ||
| 272 | { "upward", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "direction" }, | ||
| 314 | { NULL } | 273 | { NULL } |
| 315 | }; | 274 | }; |
| 316 | 275 | ||