FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavfilter/adynamicequalizer_template.c
Date: 2024-05-08 16:03:45
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 = (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