| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /* | ||
| 2 | * This file is part of FFmpeg. | ||
| 3 | * | ||
| 4 | * FFmpeg is free software; you can redistribute it and/or | ||
| 5 | * modify it under the terms of the GNU Lesser General Public | ||
| 6 | * License as published by the Free Software Foundation; either | ||
| 7 | * version 2.1 of the License, or (at your option) any later version. | ||
| 8 | * | ||
| 9 | * FFmpeg is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * Lesser General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU Lesser General Public | ||
| 15 | * License along with FFmpeg; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 17 | */ | ||
| 18 | |||
| 19 | #undef ftype | ||
| 20 | #undef SQRT | ||
| 21 | #undef TAN | ||
| 22 | #undef ONE | ||
| 23 | #undef TWO | ||
| 24 | #undef ZERO | ||
| 25 | #undef FMAX | ||
| 26 | #undef FMIN | ||
| 27 | #undef CLIP | ||
| 28 | #undef SAMPLE_FORMAT | ||
| 29 | #undef FABS | ||
| 30 | #undef FLOG | ||
| 31 | #undef FEXP | ||
| 32 | #undef FLOG2 | ||
| 33 | #undef FLOG10 | ||
| 34 | #undef FEXP2 | ||
| 35 | #undef FEXP10 | ||
| 36 | #undef EPSILON | ||
| 37 | #if DEPTH == 32 | ||
| 38 | #define SAMPLE_FORMAT float | ||
| 39 | #define SQRT sqrtf | ||
| 40 | #define TAN tanf | ||
| 41 | #define ONE 1.f | ||
| 42 | #define TWO 2.f | ||
| 43 | #define ZERO 0.f | ||
| 44 | #define FMIN fminf | ||
| 45 | #define FMAX fmaxf | ||
| 46 | #define CLIP av_clipf | ||
| 47 | #define FABS fabsf | ||
| 48 | #define FLOG logf | ||
| 49 | #define FEXP expf | ||
| 50 | #define FLOG2 log2f | ||
| 51 | #define FLOG10 log10f | ||
| 52 | #define FEXP2 exp2f | ||
| 53 | #define FEXP10 ff_exp10f | ||
| 54 | #define EPSILON (1.f / (1 << 23)) | ||
| 55 | #define ftype float | ||
| 56 | #else | ||
| 57 | #define SAMPLE_FORMAT double | ||
| 58 | #define SQRT sqrt | ||
| 59 | #define TAN tan | ||
| 60 | #define ONE 1.0 | ||
| 61 | #define TWO 2.0 | ||
| 62 | #define ZERO 0.0 | ||
| 63 | #define FMIN fmin | ||
| 64 | #define FMAX fmax | ||
| 65 | #define CLIP av_clipd | ||
| 66 | #define FABS fabs | ||
| 67 | #define FLOG log | ||
| 68 | #define FEXP exp | ||
| 69 | #define FLOG2 log2 | ||
| 70 | #define FLOG10 log10 | ||
| 71 | #define FEXP2 exp2 | ||
| 72 | #define FEXP10 ff_exp10 | ||
| 73 | #define EPSILON (1.0 / (1LL << 53)) | ||
| 74 | #define ftype double | ||
| 75 | #endif | ||
| 76 | |||
| 77 | #define LIN2LOG(x) (20.0 * FLOG10(x)) | ||
| 78 | #define LOG2LIN(x) (FEXP10(x / 20.0)) | ||
| 79 | |||
| 80 | #define fn3(a,b) a##_##b | ||
| 81 | #define fn2(a,b) fn3(a,b) | ||
| 82 | #define fn(a) fn2(a, SAMPLE_FORMAT) | ||
| 83 | |||
| 84 | ✗ | static ftype fn(get_svf)(ftype in, const ftype *m, const ftype *a, ftype *b) | |
| 85 | { | ||
| 86 | ✗ | const ftype v0 = in; | |
| 87 | ✗ | const ftype v3 = v0 - b[1]; | |
| 88 | ✗ | const ftype v1 = a[0] * b[0] + a[1] * v3; | |
| 89 | ✗ | const ftype v2 = b[1] + a[1] * b[0] + a[2] * v3; | |
| 90 | |||
| 91 | ✗ | b[0] = TWO * v1 - b[0]; | |
| 92 | ✗ | b[1] = TWO * v2 - b[1]; | |
| 93 | |||
| 94 | ✗ | return m[0] * v0 + m[1] * v1 + m[2] * v2; | |
| 95 | } | ||
| 96 | |||
| 97 | ✗ | static int fn(filter_prepare)(AVFilterContext *ctx) | |
| 98 | { | ||
| 99 | ✗ | AudioDynamicEqualizerContext *s = ctx->priv; | |
| 100 | ✗ | const ftype sample_rate = ctx->inputs[0]->sample_rate; | |
| 101 | ✗ | const ftype dfrequency = FMIN(s->dfrequency, sample_rate * 0.5); | |
| 102 | ✗ | const ftype dg = TAN(M_PI * dfrequency / sample_rate); | |
| 103 | ✗ | const ftype dqfactor = s->dqfactor; | |
| 104 | ✗ | const int dftype = s->dftype; | |
| 105 | ✗ | ftype *da = fn(s->da); | |
| 106 | ✗ | ftype *dm = fn(s->dm); | |
| 107 | ftype k; | ||
| 108 | |||
| 109 | ✗ | s->threshold_log = LIN2LOG(s->threshold); | |
| 110 | ✗ | s->dattack_coef = get_coef(s->dattack, sample_rate); | |
| 111 | ✗ | s->drelease_coef = get_coef(s->drelease, sample_rate); | |
| 112 | ✗ | s->gattack_coef = s->dattack_coef * 0.25; | |
| 113 | ✗ | s->grelease_coef = s->drelease_coef * 0.25; | |
| 114 | |||
| 115 | ✗ | switch (dftype) { | |
| 116 | ✗ | case 0: | |
| 117 | ✗ | k = ONE / dqfactor; | |
| 118 | |||
| 119 | ✗ | da[0] = ONE / (ONE + dg * (dg + k)); | |
| 120 | ✗ | da[1] = dg * da[0]; | |
| 121 | ✗ | da[2] = dg * da[1]; | |
| 122 | |||
| 123 | ✗ | dm[0] = ZERO; | |
| 124 | ✗ | dm[1] = k; | |
| 125 | ✗ | dm[2] = ZERO; | |
| 126 | ✗ | break; | |
| 127 | ✗ | case 1: | |
| 128 | ✗ | k = ONE / dqfactor; | |
| 129 | |||
| 130 | ✗ | da[0] = ONE / (ONE + dg * (dg + k)); | |
| 131 | ✗ | da[1] = dg * da[0]; | |
| 132 | ✗ | da[2] = dg * da[1]; | |
| 133 | |||
| 134 | ✗ | dm[0] = ZERO; | |
| 135 | ✗ | dm[1] = ZERO; | |
| 136 | ✗ | dm[2] = ONE; | |
| 137 | ✗ | break; | |
| 138 | ✗ | case 2: | |
| 139 | ✗ | k = ONE / dqfactor; | |
| 140 | |||
| 141 | ✗ | da[0] = ONE / (ONE + dg * (dg + k)); | |
| 142 | ✗ | da[1] = dg * da[0]; | |
| 143 | ✗ | da[2] = dg * da[1]; | |
| 144 | |||
| 145 | ✗ | dm[0] = ZERO; | |
| 146 | ✗ | dm[1] = -k; | |
| 147 | ✗ | dm[2] = -ONE; | |
| 148 | ✗ | break; | |
| 149 | ✗ | case 3: | |
| 150 | ✗ | k = ONE / dqfactor; | |
| 151 | |||
| 152 | ✗ | da[0] = ONE / (ONE + dg * (dg + k)); | |
| 153 | ✗ | da[1] = dg * da[0]; | |
| 154 | ✗ | da[2] = dg * da[1]; | |
| 155 | |||
| 156 | ✗ | dm[0] = ONE; | |
| 157 | ✗ | dm[1] = -k; | |
| 158 | ✗ | dm[2] = -TWO; | |
| 159 | ✗ | break; | |
| 160 | } | ||
| 161 | |||
| 162 | ✗ | return 0; | |
| 163 | } | ||
| 164 | |||
| 165 | #define PEAKS(empty_value,op,sample, psample)\ | ||
| 166 | if (!empty && psample == ss[front]) { \ | ||
| 167 | ss[front] = empty_value; \ | ||
| 168 | if (back != front) { \ | ||
| 169 | front--; \ | ||
| 170 | if (front < 0) \ | ||
| 171 | front = n - 1; \ | ||
| 172 | } \ | ||
| 173 | empty = front == back; \ | ||
| 174 | } \ | ||
| 175 | \ | ||
| 176 | if (!empty && sample op ss[front]) { \ | ||
| 177 | while (1) { \ | ||
| 178 | ss[front] = empty_value; \ | ||
| 179 | if (back == front) { \ | ||
| 180 | empty = 1; \ | ||
| 181 | break; \ | ||
| 182 | } \ | ||
| 183 | front--; \ | ||
| 184 | if (front < 0) \ | ||
| 185 | front = n - 1; \ | ||
| 186 | } \ | ||
| 187 | } \ | ||
| 188 | \ | ||
| 189 | while (!empty && sample op ss[back]) { \ | ||
| 190 | ss[back] = empty_value; \ | ||
| 191 | if (back == front) { \ | ||
| 192 | empty = 1; \ | ||
| 193 | break; \ | ||
| 194 | } \ | ||
| 195 | back++; \ | ||
| 196 | if (back >= n) \ | ||
| 197 | back = 0; \ | ||
| 198 | } \ | ||
| 199 | \ | ||
| 200 | if (!empty) { \ | ||
| 201 | back--; \ | ||
| 202 | if (back < 0) \ | ||
| 203 | back = n - 1; \ | ||
| 204 | } | ||
| 205 | |||
| 206 | ✗ | static void fn(queue_sample)(ChannelContext *cc, | |
| 207 | const ftype x, | ||
| 208 | const int nb_samples) | ||
| 209 | { | ||
| 210 | ✗ | ftype *ss = cc->dqueue; | |
| 211 | ✗ | ftype *qq = cc->queue; | |
| 212 | ✗ | int front = cc->front; | |
| 213 | ✗ | int back = cc->back; | |
| 214 | ✗ | int empty, n, pos = cc->position; | |
| 215 | ✗ | ftype px = qq[pos]; | |
| 216 | |||
| 217 | ✗ | fn(cc->sum) += x; | |
| 218 | ✗ | fn(cc->log_sum) += FLOG2(x); | |
| 219 | ✗ | if (cc->size >= nb_samples) { | |
| 220 | ✗ | fn(cc->sum) -= px; | |
| 221 | ✗ | fn(cc->log_sum) -= FLOG2(px); | |
| 222 | } | ||
| 223 | |||
| 224 | ✗ | qq[pos] = x; | |
| 225 | ✗ | pos++; | |
| 226 | ✗ | if (pos >= nb_samples) | |
| 227 | ✗ | pos = 0; | |
| 228 | ✗ | cc->position = pos; | |
| 229 | |||
| 230 | ✗ | if (cc->size < nb_samples) | |
| 231 | ✗ | cc->size++; | |
| 232 | ✗ | n = cc->size; | |
| 233 | |||
| 234 | ✗ | empty = (front == back) && (ss[front] == ZERO); | |
| 235 | ✗ | PEAKS(ZERO, >, x, px) | |
| 236 | |||
| 237 | ✗ | ss[back] = x; | |
| 238 | |||
| 239 | ✗ | cc->front = front; | |
| 240 | ✗ | cc->back = back; | |
| 241 | ✗ | } | |
| 242 | |||
| 243 | ✗ | static ftype fn(get_peak)(ChannelContext *cc, ftype *score) | |
| 244 | { | ||
| 245 | ✗ | ftype s, *ss = cc->dqueue; | |
| 246 | ✗ | s = FEXP2(fn(cc->log_sum) / cc->size) / (fn(cc->sum) / cc->size); | |
| 247 | ✗ | *score = LIN2LOG(s); | |
| 248 | ✗ | return ss[cc->front]; | |
| 249 | } | ||
| 250 | |||
| 251 | ✗ | static int fn(filter_channels)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) | |
| 252 | { | ||
| 253 | ✗ | AudioDynamicEqualizerContext *s = ctx->priv; | |
| 254 | ✗ | ThreadData *td = arg; | |
| 255 | ✗ | AVFrame *in = td->in; | |
| 256 | ✗ | AVFrame *out = td->out; | |
| 257 | ✗ | const ftype sample_rate = in->sample_rate; | |
| 258 | ✗ | const int isample_rate = in->sample_rate; | |
| 259 | ✗ | const ftype makeup = s->makeup; | |
| 260 | ✗ | const ftype ratio = s->ratio; | |
| 261 | ✗ | const ftype range = s->range; | |
| 262 | ✗ | const ftype tfrequency = FMIN(s->tfrequency, sample_rate * 0.5); | |
| 263 | ✗ | const int mode = s->mode; | |
| 264 | ✗ | const ftype power = (mode == CUT_BELOW || mode == CUT_ABOVE) ? -ONE : ONE; | |
| 265 | ✗ | const ftype grelease = s->grelease_coef; | |
| 266 | ✗ | const ftype gattack = s->gattack_coef; | |
| 267 | ✗ | const ftype drelease = s->drelease_coef; | |
| 268 | ✗ | const ftype dattack = s->dattack_coef; | |
| 269 | ✗ | const ftype tqfactor = s->tqfactor; | |
| 270 | ✗ | const ftype itqfactor = ONE / tqfactor; | |
| 271 | ✗ | const ftype fg = TAN(M_PI * tfrequency / sample_rate); | |
| 272 | ✗ | const int start = (in->ch_layout.nb_channels * jobnr) / nb_jobs; | |
| 273 | ✗ | const int end = (in->ch_layout.nb_channels * (jobnr+1)) / nb_jobs; | |
| 274 | ✗ | const int is_disabled = ctx->is_disabled; | |
| 275 | ✗ | const int detection = s->detection; | |
| 276 | ✗ | const int tftype = s->tftype; | |
| 277 | ✗ | const ftype *da = fn(s->da); | |
| 278 | ✗ | const ftype *dm = fn(s->dm); | |
| 279 | |||
| 280 | ✗ | if (detection == DET_ON) { | |
| 281 | ✗ | for (int ch = start; ch < end; ch++) { | |
| 282 | ✗ | const ftype *src = (const ftype *)in->extended_data[ch]; | |
| 283 | ✗ | ChannelContext *cc = &s->cc[ch]; | |
| 284 | ✗ | ftype *tstate = fn(cc->tstate); | |
| 285 | ✗ | ftype new_threshold = ZERO; | |
| 286 | |||
| 287 | ✗ | if (cc->detection != detection) { | |
| 288 | ✗ | cc->detection = detection; | |
| 289 | ✗ | fn(cc->new_threshold_log) = LIN2LOG(EPSILON); | |
| 290 | } | ||
| 291 | |||
| 292 | ✗ | for (int n = 0; n < in->nb_samples; n++) { | |
| 293 | ✗ | ftype detect = FABS(fn(get_svf)(src[n], dm, da, tstate)); | |
| 294 | ✗ | new_threshold = FMAX(new_threshold, detect); | |
| 295 | } | ||
| 296 | |||
| 297 | ✗ | fn(cc->new_threshold_log) = FMAX(fn(cc->new_threshold_log), LIN2LOG(new_threshold)); | |
| 298 | } | ||
| 299 | ✗ | } else if (detection == DET_ADAPTIVE) { | |
| 300 | ✗ | for (int ch = start; ch < end; ch++) { | |
| 301 | ✗ | const ftype *src = (const ftype *)in->extended_data[ch]; | |
| 302 | ✗ | ChannelContext *cc = &s->cc[ch]; | |
| 303 | ✗ | ftype *tstate = fn(cc->tstate); | |
| 304 | ftype score, peak; | ||
| 305 | |||
| 306 | ✗ | for (int n = 0; n < in->nb_samples; n++) { | |
| 307 | ✗ | ftype detect = FMAX(FABS(fn(get_svf)(src[n], dm, da, tstate)), EPSILON); | |
| 308 | ✗ | fn(queue_sample)(cc, detect, isample_rate); | |
| 309 | } | ||
| 310 | |||
| 311 | ✗ | peak = fn(get_peak)(cc, &score); | |
| 312 | |||
| 313 | ✗ | if (score >= -3.5) { | |
| 314 | ✗ | fn(cc->threshold_log) = LIN2LOG(peak); | |
| 315 | ✗ | } else if (cc->detection == DET_UNSET) { | |
| 316 | ✗ | fn(cc->threshold_log) = s->threshold_log; | |
| 317 | } | ||
| 318 | ✗ | cc->detection = detection; | |
| 319 | } | ||
| 320 | ✗ | } else if (detection == DET_DISABLED) { | |
| 321 | ✗ | for (int ch = start; ch < end; ch++) { | |
| 322 | ✗ | ChannelContext *cc = &s->cc[ch]; | |
| 323 | ✗ | fn(cc->threshold_log) = s->threshold_log; | |
| 324 | ✗ | cc->detection = detection; | |
| 325 | } | ||
| 326 | ✗ | } else if (detection == DET_OFF) { | |
| 327 | ✗ | for (int ch = start; ch < end; ch++) { | |
| 328 | ✗ | ChannelContext *cc = &s->cc[ch]; | |
| 329 | ✗ | if (cc->detection == DET_ON) | |
| 330 | ✗ | fn(cc->threshold_log) = fn(cc->new_threshold_log); | |
| 331 | ✗ | else if (cc->detection == DET_UNSET) | |
| 332 | ✗ | fn(cc->threshold_log) = s->threshold_log; | |
| 333 | ✗ | cc->detection = detection; | |
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | ✗ | for (int ch = start; ch < end; ch++) { | |
| 338 | ✗ | const ftype *src = (const ftype *)in->extended_data[ch]; | |
| 339 | ✗ | ftype *dst = (ftype *)out->extended_data[ch]; | |
| 340 | ✗ | ChannelContext *cc = &s->cc[ch]; | |
| 341 | ✗ | const ftype threshold_log = fn(cc->threshold_log); | |
| 342 | ✗ | ftype *fa = fn(cc->fa), *fm = fn(cc->fm); | |
| 343 | ✗ | ftype *fstate = fn(cc->fstate); | |
| 344 | ✗ | ftype *dstate = fn(cc->dstate); | |
| 345 | ✗ | ftype detect = fn(cc->detect); | |
| 346 | ✗ | ftype lin_gain = fn(cc->lin_gain); | |
| 347 | ✗ | int init = cc->init; | |
| 348 | |||
| 349 | ✗ | for (int n = 0; n < out->nb_samples; n++) { | |
| 350 | ✗ | ftype new_detect, new_lin_gain = ONE; | |
| 351 | ftype f, v, listen, k, g, ld; | ||
| 352 | |||
| 353 | ✗ | listen = fn(get_svf)(src[n], dm, da, dstate); | |
| 354 | ✗ | if (mode > LISTEN) { | |
| 355 | ✗ | new_detect = FABS(listen); | |
| 356 | ✗ | f = (new_detect > detect) * dattack + (new_detect <= detect) * drelease; | |
| 357 | ✗ | detect = f * new_detect + (ONE - f) * detect; | |
| 358 | } | ||
| 359 | |||
| 360 | ✗ | switch (mode) { | |
| 361 | ✗ | case LISTEN: | |
| 362 | ✗ | break; | |
| 363 | ✗ | case CUT_BELOW: | |
| 364 | case BOOST_BELOW: | ||
| 365 | ✗ | ld = LIN2LOG(detect); | |
| 366 | ✗ | if (ld < threshold_log) { | |
| 367 | ✗ | ftype new_log_gain = CLIP(makeup + (threshold_log - ld) * ratio, ZERO, range) * power; | |
| 368 | ✗ | new_lin_gain = LOG2LIN(new_log_gain); | |
| 369 | } | ||
| 370 | ✗ | break; | |
| 371 | ✗ | case CUT_ABOVE: | |
| 372 | case BOOST_ABOVE: | ||
| 373 | ✗ | ld = LIN2LOG(detect); | |
| 374 | ✗ | if (ld > threshold_log) { | |
| 375 | ✗ | ftype new_log_gain = CLIP(makeup + (ld - threshold_log) * ratio, ZERO, range) * power; | |
| 376 | ✗ | new_lin_gain = LOG2LIN(new_log_gain); | |
| 377 | } | ||
| 378 | ✗ | break; | |
| 379 | } | ||
| 380 | |||
| 381 | ✗ | f = (new_lin_gain > lin_gain) * gattack + (new_lin_gain <= lin_gain) * grelease; | |
| 382 | ✗ | new_lin_gain = f * new_lin_gain + (ONE - f) * lin_gain; | |
| 383 | |||
| 384 | ✗ | if (lin_gain != new_lin_gain || !init) { | |
| 385 | ✗ | init = 1; | |
| 386 | ✗ | lin_gain = new_lin_gain; | |
| 387 | |||
| 388 | ✗ | switch (tftype) { | |
| 389 | ✗ | case 0: | |
| 390 | ✗ | k = itqfactor / lin_gain; | |
| 391 | |||
| 392 | ✗ | fa[0] = ONE / (ONE + fg * (fg + k)); | |
| 393 | ✗ | fa[1] = fg * fa[0]; | |
| 394 | ✗ | fa[2] = fg * fa[1]; | |
| 395 | |||
| 396 | ✗ | fm[0] = ONE; | |
| 397 | ✗ | fm[1] = k * (lin_gain * lin_gain - ONE); | |
| 398 | ✗ | fm[2] = ZERO; | |
| 399 | ✗ | break; | |
| 400 | ✗ | case 1: | |
| 401 | ✗ | k = itqfactor; | |
| 402 | ✗ | g = fg / SQRT(lin_gain); | |
| 403 | |||
| 404 | ✗ | fa[0] = ONE / (ONE + g * (g + k)); | |
| 405 | ✗ | fa[1] = g * fa[0]; | |
| 406 | ✗ | fa[2] = g * fa[1]; | |
| 407 | |||
| 408 | ✗ | fm[0] = ONE; | |
| 409 | ✗ | fm[1] = k * (lin_gain - ONE); | |
| 410 | ✗ | fm[2] = lin_gain * lin_gain - ONE; | |
| 411 | ✗ | break; | |
| 412 | ✗ | case 2: | |
| 413 | ✗ | k = itqfactor; | |
| 414 | ✗ | g = fg * SQRT(lin_gain); | |
| 415 | |||
| 416 | ✗ | fa[0] = ONE / (ONE + g * (g + k)); | |
| 417 | ✗ | fa[1] = g * fa[0]; | |
| 418 | ✗ | fa[2] = g * fa[1]; | |
| 419 | |||
| 420 | ✗ | fm[0] = lin_gain * lin_gain; | |
| 421 | ✗ | fm[1] = k * (ONE - lin_gain) * lin_gain; | |
| 422 | ✗ | fm[2] = ONE - lin_gain * lin_gain; | |
| 423 | ✗ | break; | |
| 424 | } | ||
| 425 | } | ||
| 426 | |||
| 427 | ✗ | v = fn(get_svf)(src[n], fm, fa, fstate); | |
| 428 | ✗ | v = mode == LISTEN ? listen : v; | |
| 429 | ✗ | dst[n] = is_disabled ? src[n] : v; | |
| 430 | } | ||
| 431 | |||
| 432 | ✗ | fn(cc->detect) = detect; | |
| 433 | ✗ | fn(cc->lin_gain) = lin_gain; | |
| 434 | ✗ | cc->init = 1; | |
| 435 | } | ||
| 436 | |||
| 437 | ✗ | return 0; | |
| 438 | } | ||
| 439 |