Showing the changes to libavfilter (1 of 2 files). Show all
Unified · Split
| @@ -34,13 +34,12 @@ typedef struct AudioDynamicEqualizerContext { · 33 unmodified lines | ||
| 34 | 34 | double ratio; |
| 35 | 35 | double range; |
| 36 | 36 | double makeup; |
| 37 | − double knee; | |
| 38 | − double slew; | |
| 39 | 37 | double attack; |
| 40 | 38 | double release; |
| 41 | 39 | double attack_coef; |
| 42 | 40 | double release_coef; |
| 43 | 41 | int mode; |
| 42 | + int direction; | |
| 44 | 43 | int type; |
| 45 | 44 | |
| 46 | 45 | AVFrame *state; |
| @@ -55,6 +54,12 @@ static int config_input(AVFilterLink *inlink) · 8 unmodified lines | ||
| 55 | 54 | if (!s->state) |
| 56 | 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 | 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 | 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 | 79 | typedef struct ThreadData { |
| 138 | 80 | AVFrame *in, *out; |
| 139 | 81 | } ThreadData; |
| @@ -146,25 +88,24 @@ static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jo · 6 unmodified lines | ||
| 146 | 88 | AVFrame *out = td->out; |
| 147 | 89 | const double sample_rate = in->sample_rate; |
| 148 | 90 | const double makeup = s->makeup; |
| 149 | − const double iratio = 1. / s->ratio; | |
| 91 | + const double ratio = s->ratio; | |
| 150 | 92 | const double range = s->range; |
| 151 | 93 | const double dfrequency = fmin(s->dfrequency, sample_rate * 0.5); |
| 152 | 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 | 96 | const double release = s->release_coef; |
| 97 | + const double irelease = 1. - release; | |
| 155 | 98 | const double attack = s->attack_coef; |
| 99 | + const double iattack = 1. - attack; | |
| 156 | 100 | const double dqfactor = s->dqfactor; |
| 157 | 101 | const double tqfactor = s->tqfactor; |
| 158 | 102 | const double fg = tan(M_PI * tfrequency / sample_rate); |
| 159 | 103 | const double dg = tan(M_PI * dfrequency / sample_rate); |
| 160 | 104 | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; |
| 161 | 105 | const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; |
| 106 | + const int direction = s->direction; | |
| 162 | 107 | const int mode = s->mode; |
| 163 | 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 | 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 | 116 | da[2] = dg * da[1]; |
| 176 | 117 | |
| 177 | 118 | dm[0] = 0.; |
| 178 | − dm[1] = 1.; | |
| 119 | + dm[1] = k; | |
| 179 | 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 | 133 | detect = listen = get_svf(src[n], dm, da, state); |
| 193 | 134 | detect = fabs(detect); |
| 194 | 135 | |
| 195 | − gain = get_gain(detect, sample_rate, makeup, | |
| 196 | − aattack, iratio, knee, range, threshold, slew, | |
| 197 | − &state[4], attack, release, nc); | |
| 198 | − | |
| 199 | − switch (type) { | |
| 200 | − case 0: | |
| 201 | − k = 1. / (tqfactor * gain); | |
| 202 | − | |
| 203 | − fa[0] = 1. / (1. + fg * (fg + k)); | |
| 204 | − fa[1] = fg * fa[0]; | |
| 205 | − fa[2] = fg * fa[1]; | |
| 206 | − | |
| 207 | − fm[0] = 1.; | |
| 208 | − fm[1] = k * (gain * gain - 1.); | |
| 209 | − fm[2] = 0.; | |
| 210 | − break; | |
| 211 | − case 1: | |
| 212 | − k = 1. / tqfactor; | |
| 213 | − g = fg / sqrt(gain); | |
| 214 | − | |
| 215 | − fa[0] = 1. / (1. + g * (g + k)); | |
| 216 | − fa[1] = g * fa[0]; | |
| 217 | − fa[2] = g * fa[1]; | |
| 218 | − | |
| 219 | − fm[0] = 1.; | |
| 220 | − fm[1] = k * (gain - 1.); | |
| 221 | − fm[2] = gain * gain - 1.; | |
| 222 | − break; | |
| 223 | − case 2: | |
| 224 | − k = 1. / tqfactor; | |
| 225 | − g = fg / sqrt(gain); | |
| 226 | − | |
| 227 | − fa[0] = 1. / (1. + g * (g + k)); | |
| 228 | − fa[1] = g * fa[0]; | |
| 229 | − fa[2] = g * fa[1]; | |
| 230 | − | |
| 231 | − fm[0] = gain * gain; | |
| 232 | − fm[1] = k * (1. - gain) * gain; | |
| 233 | − fm[2] = 1. - gain * gain; | |
| 234 | − break; | |
| 136 | + if (direction == 0 && mode == 0 && detect < threshold) | |
| 137 | + detect = 1. / av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); | |
| 138 | + else if (direction == 0 && mode == 1 && detect < threshold) | |
| 139 | + detect = av_clipd(1. + makeup + (threshold - detect) * ratio, 1., range); | |
| 140 | + else if (direction == 1 && mode == 0 && detect > threshold) | |
| 141 | + detect = 1. / av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); | |
| 142 | + else if (direction == 1 && mode == 1 && detect > threshold) | |
| 143 | + detect = av_clipd(1. + makeup + (detect - threshold) * ratio, 1., range); | |
| 144 | + else | |
| 145 | + detect = 1.; | |
| 146 | + | |
| 147 | + if (detect < state[4]) { | |
| 148 | + detect = iattack * detect + attack * state[4]; | |
| 149 | + } else { | |
| 150 | + detect = irelease * detect + release * state[4]; | |
| 151 | + } | |
| 152 | + | |
| 153 | + if (state[4] != detect || n == 0) { | |
| 154 | + state[4] = gain = detect; | |
| 155 | + | |
| 156 | + switch (type) { | |
| 157 | + case 0: | |
| 158 | + k = 1. / (tqfactor * gain); | |
| 159 | + | |
| 160 | + fa[0] = 1. / (1. + fg * (fg + k)); | |
| 161 | + fa[1] = fg * fa[0]; | |
| 162 | + fa[2] = fg * fa[1]; | |
| 163 | + | |
| 164 | + fm[0] = 1.; | |
| 165 | + fm[1] = k * (gain * gain - 1.); | |
| 166 | + fm[2] = 0.; | |
| 167 | + break; | |
| 168 | + case 1: | |
| 169 | + k = 1. / tqfactor; | |
| 170 | + g = fg / sqrt(gain); | |
| 171 | + | |
| 172 | + fa[0] = 1. / (1. + g * (g + k)); | |
| 173 | + fa[1] = g * fa[0]; | |
| 174 | + fa[2] = g * fa[1]; | |
| 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 | 195 | v = get_svf(src[n], fm, fa, &state[2]); |
| @@ -298,11 +256,9 @@ static const AVOption adynamicequalizer_options[] = { · 60 unmodified lines | ||
| 298 | 256 | { "tqfactor", "set target Q factor", OFFSET(tqfactor), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0.001, 1000, FLAGS }, |
| 299 | 257 | { "attack", "set attack duration", OFFSET(attack), AV_OPT_TYPE_DOUBLE, {.dbl=20}, 1, 2000, FLAGS }, |
| 300 | 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 }, | |
| 302 | − { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 1, 20, FLAGS }, | |
| 303 | − { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 30, 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 }, | |
| 259 | + { "ratio", "set ratio factor", OFFSET(ratio), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 30, FLAGS }, | |
| 260 | + { "makeup", "set makeup gain", OFFSET(makeup), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 100, FLAGS }, | |
| 261 | + { "range", "set max gain", OFFSET(range), AV_OPT_TYPE_DOUBLE, {.dbl=50}, 1, 200, FLAGS }, | |
| 306 | 262 | { "mode", "set mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=0}, -1, 1, FLAGS, "mode" }, |
| 307 | 263 | { "listen", 0, 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, "mode" }, |
| 308 | 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 | 267 | { "bell", 0, 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, FLAGS, "type" }, |
| 312 | 268 | { "lowshelf", 0, 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, FLAGS, "type" }, |
| 313 | 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 | 273 | { NULL } |
| 315 | 274 | }; |
| 316 | 275 | |