FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/adynamicequalizer_template.c
Date: 2026-09-25 02:02:46
Exec Total Coverage
Lines: 0 233 0.0%
Functions: 0 8 0.0%
Branches: 0 43 0.0%

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 = ff_slice_pos(in->ch_layout.nb_channels, jobnr, nb_jobs);
273 ✗ const int end = ff_slice_pos(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