FFmpeg
af_anequalizer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2001-2010 Krzysztof Foltman, Markus Schmidt, Thor Harald Johansen and others
3  * Copyright (c) 2015 Paul B Mahol
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/intreadwrite.h"
23 #include "libavutil/avstring.h"
24 #include "libavutil/ffmath.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavutil/parseutils.h"
28 #include "avfilter.h"
29 #include "filters.h"
30 #include "formats.h"
31 #include "audio.h"
32 #include "video.h"
33 
34 #define FILTER_ORDER 4
35 
36 enum FilterType {
41 };
42 
43 typedef struct FoSection {
44  double a0, a1, a2, a3, a4;
45  double b0, b1, b2, b3, b4;
46 
47  double num[4];
48  double denum[4];
49 } FoSection;
50 
51 typedef struct EqualizatorFilter {
52  int ignore;
53  int channel;
54  int type;
55 
56  double freq;
57  double gain;
58  double width;
59 
62 
63 typedef struct AudioNEqualizerContext {
64  const AVClass *class;
65  char *args;
66  char *colors;
68  int w, h;
69 
70  double mag;
71  int fscale;
77 
78 #define OFFSET(x) offsetof(AudioNEqualizerContext, x)
79 #define A AV_OPT_FLAG_AUDIO_PARAM
80 #define V AV_OPT_FLAG_VIDEO_PARAM
81 #define F AV_OPT_FLAG_FILTERING_PARAM
82 
83 static const AVOption anequalizer_options[] = {
84  { "params", NULL, OFFSET(args), AV_OPT_TYPE_STRING, {.str=""}, 0, 0, A|F },
85  { "curves", "draw frequency response curves", OFFSET(draw_curves), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, V|F },
86  { "size", "set video size", OFFSET(w), AV_OPT_TYPE_IMAGE_SIZE, {.str = "hd720"}, 0, 0, V|F },
87  { "mgain", "set max gain", OFFSET(mag), AV_OPT_TYPE_DOUBLE, {.dbl=60}, -900, 900, V|F },
88  { "fscale", "set frequency scale", OFFSET(fscale), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, V|F, .unit = "fscale" },
89  { "lin", "linear", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, V|F, .unit = "fscale" },
90  { "log", "logarithmic", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, V|F, .unit = "fscale" },
91  { "colors", "set channels curves colors", OFFSET(colors), AV_OPT_TYPE_STRING, {.str = "red|green|blue|yellow|orange|lime|pink|magenta|brown" }, 0, 0, V|F },
92  { NULL }
93 };
94 
95 AVFILTER_DEFINE_CLASS(anequalizer);
96 
98 {
99  AudioNEqualizerContext *s = ctx->priv;
100  char *colors, *color, *saveptr = NULL;
101  int ch, i, n;
102 
103  colors = av_strdup(s->colors);
104  if (!colors)
105  return;
106 
107  memset(out->data[0], 0, s->h * out->linesize[0]);
108 
109  for (ch = 0; ch < inlink->ch_layout.nb_channels; ch++) {
110  uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };
111  int prev_v = -1;
112  double f;
113 
114  color = av_strtok(ch == 0 ? colors : NULL, " |", &saveptr);
115  if (color)
116  av_parse_color(fg, color, -1, ctx);
117 
118  for (f = 0; f < s->w; f++) {
119  double zr, zi, zr2, zi2;
120  double Hr, Hi;
121  double Hmag = 1;
122  double w;
123  int v, y, x;
124 
125  w = M_PI * (s->fscale ? pow(s->w - 1, f / s->w) : f) / (s->w - 1);
126  zr = cos(w);
127  zr2 = zr * zr;
128  zi = -sin(w);
129  zi2 = zi * zi;
130 
131  for (n = 0; n < s->nb_filters; n++) {
132  if (s->filters[n].channel != ch ||
133  s->filters[n].ignore)
134  continue;
135 
136  for (i = 0; i < FILTER_ORDER / 2; i++) {
137  FoSection *S = &s->filters[n].section[i];
138 
139  /* H *= (((((S->b4 * z + S->b3) * z + S->b2) * z + S->b1) * z + S->b0) /
140  ((((S->a4 * z + S->a3) * z + S->a2) * z + S->a1) * z + S->a0)); */
141 
142  Hr = S->b4*(1-8*zr2*zi2) + S->b2*(zr2-zi2) + zr*(S->b1+S->b3*(zr2-3*zi2))+ S->b0;
143  Hi = zi*(S->b3*(3*zr2-zi2) + S->b1 + 2*zr*(2*S->b4*(zr2-zi2) + S->b2));
144  Hmag *= hypot(Hr, Hi);
145  Hr = S->a4*(1-8*zr2*zi2) + S->a2*(zr2-zi2) + zr*(S->a1+S->a3*(zr2-3*zi2))+ S->a0;
146  Hi = zi*(S->a3*(3*zr2-zi2) + S->a1 + 2*zr*(2*S->a4*(zr2-zi2) + S->a2));
147  Hmag /= hypot(Hr, Hi);
148  }
149  }
150 
151  v = av_clip((1. + -20 * log10(Hmag) / s->mag) * s->h / 2, 0, s->h - 1);
152  x = lrint(f);
153  if (prev_v == -1)
154  prev_v = v;
155  if (v <= prev_v) {
156  for (y = v; y <= prev_v; y++)
157  AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg));
158  } else {
159  for (y = prev_v; y <= v; y++)
160  AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg));
161  }
162 
163  prev_v = v;
164  }
165  }
166 
167  av_free(colors);
168 }
169 
170 static int config_video(AVFilterLink *outlink)
171 {
172  AVFilterContext *ctx = outlink->src;
173  AudioNEqualizerContext *s = ctx->priv;
174  AVFilterLink *inlink = ctx->inputs[0];
175  AVFrame *out;
176 
177  outlink->w = s->w;
178  outlink->h = s->h;
179 
180  av_frame_free(&s->video);
181  s->video = out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
182  if (!out)
183  return AVERROR(ENOMEM);
184  outlink->sample_aspect_ratio = (AVRational){1,1};
185 
187 
188  return 0;
189 }
190 
192 {
193  AudioNEqualizerContext *s = ctx->priv;
194  AVFilterPad pad, vpad;
195  int ret;
196 
197  pad = (AVFilterPad){
198  .name = "out0",
199  .type = AVMEDIA_TYPE_AUDIO,
200  };
201 
202  ret = ff_append_outpad(ctx, &pad);
203  if (ret < 0)
204  return ret;
205 
206  if (s->draw_curves) {
207  vpad = (AVFilterPad){
208  .name = "out1",
209  .type = AVMEDIA_TYPE_VIDEO,
210  .config_props = config_video,
211  };
212  ret = ff_append_outpad(ctx, &vpad);
213  if (ret < 0)
214  return ret;
215  }
216 
217  return 0;
218 }
219 
221  AVFilterFormatsConfig **cfg_in,
222  AVFilterFormatsConfig **cfg_out)
223 {
224  const AudioNEqualizerContext *s = ctx->priv;
225  static const enum AVPixelFormat pix_fmts[] = { AV_PIX_FMT_RGBA, AV_PIX_FMT_NONE };
226  static const enum AVSampleFormat sample_fmts[] = {
229  };
230  int ret;
231 
232  if (s->draw_curves) {
233  ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, pix_fmts);
234  if (ret < 0)
235  return ret;
236  }
237 
239  if (ret < 0)
240  return ret;
241 
242  return 0;
243 }
244 
246 {
247  AudioNEqualizerContext *s = ctx->priv;
248 
249  av_frame_free(&s->video);
250  av_freep(&s->filters);
251  s->nb_filters = 0;
252  s->nb_allocated = 0;
253 }
254 
255 static void butterworth_fo_section(FoSection *S, double beta,
256  double si, double g, double g0,
257  double D, double c0)
258 {
259  if (c0 == 1 || c0 == -1) {
260  S->b0 = (g*g*beta*beta + 2*g*g0*si*beta + g0*g0)/D;
261  S->b1 = 2*c0*(g*g*beta*beta - g0*g0)/D;
262  S->b2 = (g*g*beta*beta - 2*g0*g*beta*si + g0*g0)/D;
263  S->b3 = 0;
264  S->b4 = 0;
265 
266  S->a0 = 1;
267  S->a1 = 2*c0*(beta*beta - 1)/D;
268  S->a2 = (beta*beta - 2*beta*si + 1)/D;
269  S->a3 = 0;
270  S->a4 = 0;
271  } else {
272  S->b0 = (g*g*beta*beta + 2*g*g0*si*beta + g0*g0)/D;
273  S->b1 = -4*c0*(g0*g0 + g*g0*si*beta)/D;
274  S->b2 = 2*(g0*g0*(1 + 2*c0*c0) - g*g*beta*beta)/D;
275  S->b3 = -4*c0*(g0*g0 - g*g0*si*beta)/D;
276  S->b4 = (g*g*beta*beta - 2*g*g0*si*beta + g0*g0)/D;
277 
278  S->a0 = 1;
279  S->a1 = -4*c0*(1 + si*beta)/D;
280  S->a2 = 2*(1 + 2*c0*c0 - beta*beta)/D;
281  S->a3 = -4*c0*(1 - si*beta)/D;
282  S->a4 = (beta*beta - 2*si*beta + 1)/D;
283  }
284 }
285 
287  int N, double w0, double wb,
288  double G, double Gb, double G0)
289 {
290  double g, c0, g0, beta;
291  double epsilon;
292  int r = N % 2;
293  int L = (N - r) / 2;
294  int i;
295 
296  if (G == 0 && G0 == 0) {
297  f->section[0].a0 = 1;
298  f->section[0].b0 = 1;
299  f->section[1].a0 = 1;
300  f->section[1].b0 = 1;
301  return;
302  }
303 
304  G = ff_exp10(G/20);
305  Gb = ff_exp10(Gb/20);
306  G0 = ff_exp10(G0/20);
307 
308  epsilon = sqrt((G * G - Gb * Gb) / (Gb * Gb - G0 * G0));
309  g = pow(G, 1.0 / N);
310  g0 = pow(G0, 1.0 / N);
311  beta = pow(epsilon, -1.0 / N) * tan(wb/2);
312  c0 = cos(w0);
313 
314  for (i = 1; i <= L; i++) {
315  double ui = (2.0 * i - 1) / N;
316  double si = sin(M_PI * ui / 2.0);
317  double Di = beta * beta + 2 * si * beta + 1;
318 
319  butterworth_fo_section(&f->section[i - 1], beta, si, g, g0, Di, c0);
320  }
321 }
322 
323 static void chebyshev1_fo_section(FoSection *S, double a,
324  double c, double tetta_b,
325  double g0, double si, double b,
326  double D, double c0)
327 {
328  if (c0 == 1 || c0 == -1) {
329  S->b0 = (tetta_b*tetta_b*(b*b+g0*g0*c*c) + 2*g0*b*si*tetta_b*tetta_b + g0*g0)/D;
330  S->b1 = 2*c0*(tetta_b*tetta_b*(b*b+g0*g0*c*c) - g0*g0)/D;
331  S->b2 = (tetta_b*tetta_b*(b*b+g0*g0*c*c) - 2*g0*b*si*tetta_b + g0*g0)/D;
332  S->b3 = 0;
333  S->b4 = 0;
334 
335  S->a0 = 1;
336  S->a1 = 2*c0*(tetta_b*tetta_b*(a*a+c*c) - 1)/D;
337  S->a2 = (tetta_b*tetta_b*(a*a+c*c) - 2*a*si*tetta_b + 1)/D;
338  S->a3 = 0;
339  S->a4 = 0;
340  } else {
341  S->b0 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b + 2*g0*b*si*tetta_b + g0*g0)/D;
342  S->b1 = -4*c0*(g0*g0 + g0*b*si*tetta_b)/D;
343  S->b2 = 2*(g0*g0*(1 + 2*c0*c0) - (b*b + g0*g0*c*c)*tetta_b*tetta_b)/D;
344  S->b3 = -4*c0*(g0*g0 - g0*b*si*tetta_b)/D;
345  S->b4 = ((b*b + g0*g0*c*c)*tetta_b*tetta_b - 2*g0*b*si*tetta_b + g0*g0)/D;
346 
347  S->a0 = 1;
348  S->a1 = -4*c0*(1 + a*si*tetta_b)/D;
349  S->a2 = 2*(1 + 2*c0*c0 - (a*a + c*c)*tetta_b*tetta_b)/D;
350  S->a3 = -4*c0*(1 - a*si*tetta_b)/D;
351  S->a4 = ((a*a + c*c)*tetta_b*tetta_b - 2*a*si*tetta_b + 1)/D;
352  }
353 }
354 
356  int N, double w0, double wb,
357  double G, double Gb, double G0)
358 {
359  double a, b, c0, g0, alfa, beta, tetta_b;
360  double epsilon;
361  int r = N % 2;
362  int L = (N - r) / 2;
363  int i;
364 
365  if (G == 0 && G0 == 0) {
366  f->section[0].a0 = 1;
367  f->section[0].b0 = 1;
368  f->section[1].a0 = 1;
369  f->section[1].b0 = 1;
370  return;
371  }
372 
373  G = ff_exp10(G/20);
374  Gb = ff_exp10(Gb/20);
375  G0 = ff_exp10(G0/20);
376 
377  epsilon = sqrt((G*G - Gb*Gb) / (Gb*Gb - G0*G0));
378  g0 = pow(G0,1.0/N);
379  alfa = pow(1.0/epsilon + sqrt(1 + 1/(epsilon*epsilon)), 1.0/N);
380  beta = pow(G/epsilon + Gb * sqrt(1 + 1/(epsilon*epsilon)), 1.0/N);
381  a = 0.5 * (alfa - 1.0/alfa);
382  b = 0.5 * (beta - g0*g0*(1/beta));
383  tetta_b = tan(wb/2);
384  c0 = cos(w0);
385 
386  for (i = 1; i <= L; i++) {
387  double ui = (2.0*i-1.0)/N;
388  double ci = cos(M_PI*ui/2.0);
389  double si = sin(M_PI*ui/2.0);
390  double Di = (a*a + ci*ci)*tetta_b*tetta_b + 2.0*a*si*tetta_b + 1;
391 
392  chebyshev1_fo_section(&f->section[i - 1], a, ci, tetta_b, g0, si, b, Di, c0);
393  }
394 }
395 
396 static void chebyshev2_fo_section(FoSection *S, double a,
397  double c, double tetta_b,
398  double g, double si, double b,
399  double D, double c0)
400 {
401  if (c0 == 1 || c0 == -1) {
402  S->b0 = (g*g*tetta_b*tetta_b + 2*tetta_b*g*b*si + b*b + g*g*c*c)/D;
403  S->b1 = 2*c0*(g*g*tetta_b*tetta_b - b*b - g*g*c*c)/D;
404  S->b2 = (g*g*tetta_b*tetta_b - 2*tetta_b*g*b*si + b*b + g*g*c*c)/D;
405  S->b3 = 0;
406  S->b4 = 0;
407 
408  S->a0 = 1;
409  S->a1 = 2*c0*(tetta_b*tetta_b - a*a - c*c)/D;
410  S->a2 = (tetta_b*tetta_b - 2*tetta_b*a*si + a*a + c*c)/D;
411  S->a3 = 0;
412  S->a4 = 0;
413  } else {
414  S->b0 = (g*g*tetta_b*tetta_b + 2*g*b*si*tetta_b + b*b + g*g*c*c)/D;
415  S->b1 = -4*c0*(b*b + g*g*c*c + g*b*si*tetta_b)/D;
416  S->b2 = 2*((b*b + g*g*c*c)*(1 + 2*c0*c0) - g*g*tetta_b*tetta_b)/D;
417  S->b3 = -4*c0*(b*b + g*g*c*c - g*b*si*tetta_b)/D;
418  S->b4 = (g*g*tetta_b*tetta_b - 2*g*b*si*tetta_b + b*b + g*g*c*c)/D;
419 
420  S->a0 = 1;
421  S->a1 = -4*c0*(a*a + c*c + a*si*tetta_b)/D;
422  S->a2 = 2*((a*a + c*c)*(1 + 2*c0*c0) - tetta_b*tetta_b)/D;
423  S->a3 = -4*c0*(a*a + c*c - a*si*tetta_b)/D;
424  S->a4 = (tetta_b*tetta_b - 2*a*si*tetta_b + a*a + c*c)/D;
425  }
426 }
427 
429  int N, double w0, double wb,
430  double G, double Gb, double G0)
431 {
432  double a, b, c0, tetta_b;
433  double epsilon, g, eu, ew;
434  int r = N % 2;
435  int L = (N - r) / 2;
436  int i;
437 
438  if (G == 0 && G0 == 0) {
439  f->section[0].a0 = 1;
440  f->section[0].b0 = 1;
441  f->section[1].a0 = 1;
442  f->section[1].b0 = 1;
443  return;
444  }
445 
446  G = ff_exp10(G/20);
447  Gb = ff_exp10(Gb/20);
448  G0 = ff_exp10(G0/20);
449 
450  epsilon = sqrt((G*G - Gb*Gb) / (Gb*Gb - G0*G0));
451  g = pow(G, 1.0 / N);
452  eu = pow(epsilon + sqrt(1 + epsilon*epsilon), 1.0/N);
453  ew = pow(G0*epsilon + Gb*sqrt(1 + epsilon*epsilon), 1.0/N);
454  a = (eu - 1.0/eu)/2.0;
455  b = (ew - g*g/ew)/2.0;
456  tetta_b = tan(wb/2);
457  c0 = cos(w0);
458 
459  for (i = 1; i <= L; i++) {
460  double ui = (2.0 * i - 1.0)/N;
461  double ci = cos(M_PI * ui / 2.0);
462  double si = sin(M_PI * ui / 2.0);
463  double Di = tetta_b*tetta_b + 2*a*si*tetta_b + a*a + ci*ci;
464 
465  chebyshev2_fo_section(&f->section[i - 1], a, ci, tetta_b, g, si, b, Di, c0);
466  }
467 }
468 
469 static double butterworth_compute_bw_gain_db(double gain)
470 {
471  double bw_gain = 0;
472 
473  if (gain <= -6)
474  bw_gain = gain + 3;
475  else if(gain > -6 && gain < 6)
476  bw_gain = gain * 0.5;
477  else if(gain >= 6)
478  bw_gain = gain - 3;
479 
480  return bw_gain;
481 }
482 
483 static double chebyshev1_compute_bw_gain_db(double gain)
484 {
485  double bw_gain = 0;
486 
487  if (gain <= -6)
488  bw_gain = gain + 1;
489  else if(gain > -6 && gain < 6)
490  bw_gain = gain * 0.9;
491  else if(gain >= 6)
492  bw_gain = gain - 1;
493 
494  return bw_gain;
495 }
496 
497 static double chebyshev2_compute_bw_gain_db(double gain)
498 {
499  double bw_gain = 0;
500 
501  if (gain <= -6)
502  bw_gain = -3;
503  else if(gain > -6 && gain < 6)
504  bw_gain = gain * 0.3;
505  else if(gain >= 6)
506  bw_gain = 3;
507 
508  return bw_gain;
509 }
510 
511 static inline double hz_2_rad(double x, double fs)
512 {
513  return 2 * M_PI * x / fs;
514 }
515 
516 static void equalizer(EqualizatorFilter *f, double sample_rate)
517 {
518  double w0 = hz_2_rad(f->freq, sample_rate);
519  double wb = hz_2_rad(f->width, sample_rate);
520  double bw_gain;
521 
522  switch (f->type) {
523  case BUTTERWORTH:
524  bw_gain = butterworth_compute_bw_gain_db(f->gain);
525  butterworth_bp_filter(f, FILTER_ORDER, w0, wb, f->gain, bw_gain, 0);
526  break;
527  case CHEBYSHEV1:
528  bw_gain = chebyshev1_compute_bw_gain_db(f->gain);
529  chebyshev1_bp_filter(f, FILTER_ORDER, w0, wb, f->gain, bw_gain, 0);
530  break;
531  case CHEBYSHEV2:
532  bw_gain = chebyshev2_compute_bw_gain_db(f->gain);
533  chebyshev2_bp_filter(f, FILTER_ORDER, w0, wb, f->gain, bw_gain, 0);
534  break;
535  }
536 
537 }
538 
540 {
541  equalizer(&s->filters[s->nb_filters], inlink->sample_rate);
542  if (s->nb_filters >= s->nb_allocated - 1) {
544 
545  filters = av_calloc(s->nb_allocated, 2 * sizeof(*s->filters));
546  if (!filters)
547  return AVERROR(ENOMEM);
548  memcpy(filters, s->filters, sizeof(*s->filters) * s->nb_allocated);
549  av_free(s->filters);
550  s->filters = filters;
551  s->nb_allocated *= 2;
552  }
553  s->nb_filters++;
554 
555  return 0;
556 }
557 
559 {
560  AVFilterContext *ctx = inlink->dst;
561  AudioNEqualizerContext *s = ctx->priv;
562  char *args = av_strdup(s->args);
563  char *saveptr = NULL;
564  int ret = 0;
565 
566  if (!args)
567  return AVERROR(ENOMEM);
568 
569  s->nb_allocated = 32 * inlink->ch_layout.nb_channels;
570  s->filters = av_calloc(inlink->ch_layout.nb_channels, 32 * sizeof(*s->filters));
571  if (!s->filters) {
572  s->nb_allocated = 0;
573  av_free(args);
574  return AVERROR(ENOMEM);
575  }
576 
577  while (1) {
578  char *arg = av_strtok(s->nb_filters == 0 ? args : NULL, "|", &saveptr);
579 
580  if (!arg)
581  break;
582 
583  s->filters[s->nb_filters].type = 0;
584  if (sscanf(arg, "c%d f=%lf w=%lf g=%lf t=%d", &s->filters[s->nb_filters].channel,
585  &s->filters[s->nb_filters].freq,
586  &s->filters[s->nb_filters].width,
587  &s->filters[s->nb_filters].gain,
588  &s->filters[s->nb_filters].type) != 5 &&
589  sscanf(arg, "c%d f=%lf w=%lf g=%lf", &s->filters[s->nb_filters].channel,
590  &s->filters[s->nb_filters].freq,
591  &s->filters[s->nb_filters].width,
592  &s->filters[s->nb_filters].gain) != 4 ) {
593  av_free(args);
594  return AVERROR(EINVAL);
595  }
596 
597  if (s->filters[s->nb_filters].freq < 0 ||
598  s->filters[s->nb_filters].freq > inlink->sample_rate / 2.0)
599  s->filters[s->nb_filters].ignore = 1;
600 
601  if (s->filters[s->nb_filters].channel < 0 ||
602  s->filters[s->nb_filters].channel >= inlink->ch_layout.nb_channels)
603  s->filters[s->nb_filters].ignore = 1;
604 
605  s->filters[s->nb_filters].type = av_clip(s->filters[s->nb_filters].type, 0, NB_TYPES - 1);
606  ret = add_filter(s, inlink);
607  if (ret < 0)
608  break;
609  }
610 
611  av_free(args);
612 
613  return ret;
614 }
615 
616 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
617  char *res, int res_len, int flags)
618 {
619  AudioNEqualizerContext *s = ctx->priv;
620  AVFilterLink *inlink = ctx->inputs[0];
621  int ret = AVERROR(ENOSYS);
622 
623  if (!strcmp(cmd, "change")) {
624  double freq, width, gain;
625  int filter;
626 
627  if (sscanf(args, "%d|f=%lf|w=%lf|g=%lf", &filter, &freq, &width, &gain) != 4)
628  return AVERROR(EINVAL);
629 
630  if (filter < 0 || filter >= s->nb_filters)
631  return AVERROR(EINVAL);
632 
633  if (freq < 0 || freq > inlink->sample_rate / 2.0)
634  return AVERROR(EINVAL);
635 
636  s->filters[filter].freq = freq;
637  s->filters[filter].width = width;
638  s->filters[filter].gain = gain;
639  equalizer(&s->filters[filter], inlink->sample_rate);
640  if (s->draw_curves)
641  draw_curves(ctx, inlink, s->video);
642 
643  ret = 0;
644  }
645 
646  return ret;
647 }
648 
649 static inline double section_process(FoSection *S, double in)
650 {
651  double out;
652 
653  out = S->b0 * in;
654  out+= S->b1 * S->num[0] - S->denum[0] * S->a1;
655  out+= S->b2 * S->num[1] - S->denum[1] * S->a2;
656  out+= S->b3 * S->num[2] - S->denum[2] * S->a3;
657  out+= S->b4 * S->num[3] - S->denum[3] * S->a4;
658 
659  S->num[3] = S->num[2];
660  S->num[2] = S->num[1];
661  S->num[1] = S->num[0];
662  S->num[0] = in;
663 
664  S->denum[3] = S->denum[2];
665  S->denum[2] = S->denum[1];
666  S->denum[1] = S->denum[0];
667  S->denum[0] = out;
668 
669  return out;
670 }
671 
672 static double process_sample(FoSection *s1, double in)
673 {
674  double p0 = in, p1;
675  int i;
676 
677  for (i = 0; i < FILTER_ORDER / 2; i++) {
678  p1 = section_process(&s1[i], p0);
679  p0 = p1;
680  }
681 
682  return p1;
683 }
684 
686  int jobnr, int nb_jobs)
687 {
688  AudioNEqualizerContext *s = ctx->priv;
689  AVFrame *buf = arg;
690  const int start = (buf->ch_layout.nb_channels * jobnr) / nb_jobs;
691  const int end = (buf->ch_layout.nb_channels * (jobnr+1)) / nb_jobs;
692 
693  for (int i = 0; i < s->nb_filters; i++) {
694  EqualizatorFilter *f = &s->filters[i];
695  double *bptr;
696 
697  if (f->gain == 0. || f->ignore)
698  continue;
699  if (f->channel < start ||
700  f->channel >= end)
701  continue;
702 
703  bptr = (double *)buf->extended_data[f->channel];
704  for (int n = 0; n < buf->nb_samples; n++) {
705  double sample = bptr[n];
706 
707  sample = process_sample(f->section, sample);
708  bptr[n] = sample;
709  }
710  }
711 
712  return 0;
713 }
714 
716 {
717  AVFilterContext *ctx = inlink->dst;
718  AudioNEqualizerContext *s = ctx->priv;
719  AVFilterLink *outlink = ctx->outputs[0];
720 
721  if (!ctx->is_disabled)
723  FFMIN(inlink->ch_layout.nb_channels, ff_filter_get_nb_threads(ctx)));
724 
725  if (s->draw_curves) {
726  AVFrame *clone;
727 
728  const int64_t pts = buf->pts +
729  av_rescale_q(buf->nb_samples, (AVRational){ 1, inlink->sample_rate },
730  outlink->time_base);
731  int ret;
732 
733  s->video->pts = pts;
734  clone = av_frame_clone(s->video);
735  if (!clone)
736  return AVERROR(ENOMEM);
737  ret = ff_filter_frame(ctx->outputs[1], clone);
738  if (ret < 0)
739  return ret;
740  }
741 
742  return ff_filter_frame(outlink, buf);
743 }
744 
745 static const AVFilterPad inputs[] = {
746  {
747  .name = "default",
748  .type = AVMEDIA_TYPE_AUDIO,
750  .config_props = config_input,
751  .filter_frame = filter_frame,
752  },
753 };
754 
756  .name = "anequalizer",
757  .description = NULL_IF_CONFIG_SMALL("Apply high-order audio parametric multi band equalizer."),
758  .priv_size = sizeof(AudioNEqualizerContext),
759  .priv_class = &anequalizer_class,
760  .init = init,
761  .uninit = uninit,
763  .outputs = NULL,
765  .process_command = process_command,
769 };
config_video
static int config_video(AVFilterLink *outlink)
Definition: af_anequalizer.c:170
ff_get_video_buffer
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:116
AudioNEqualizerContext::args
char * args
Definition: af_anequalizer.c:65
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:71
ff_exp10
static av_always_inline double ff_exp10(double x)
Compute 10^x for floating point values.
Definition: ffmath.h:42
av_clip
#define av_clip
Definition: common.h:100
r
const char * r
Definition: vf_curves.c:127
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
opt.h
butterworth_fo_section
static void butterworth_fo_section(FoSection *S, double beta, double si, double g, double g0, double D, double c0)
Definition: af_anequalizer.c:255
AV_WL32
#define AV_WL32(p, v)
Definition: intreadwrite.h:422
out
FILE * out
Definition: movenc.c:55
F
#define F
Definition: af_anequalizer.c:81
color
Definition: vf_paletteuse.c:513
ff_filter_frame
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1061
sample_fmts
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:948
av_parse_color
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition: parseutils.c:359
int64_t
long long int64_t
Definition: coverity.c:34
inlink
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Definition: filter_design.txt:212
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:162
FILTER_INPUTS
#define FILTER_INPUTS(array)
Definition: filters.h:262
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:389
AVFrame::pts
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:501
EqualizatorFilter
Definition: af_anequalizer.c:51
w
uint8_t w
Definition: llviddspenc.c:38
AVOption
AVOption.
Definition: opt.h:429
b
#define b
Definition: input.c:41
filter_channels
static int filter_channels(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition: af_anequalizer.c:685
CHEBYSHEV2
@ CHEBYSHEV2
Definition: af_anequalizer.c:39
EqualizatorFilter::width
double width
Definition: af_anequalizer.c:58
chebyshev1_bp_filter
static void chebyshev1_bp_filter(EqualizatorFilter *f, int N, double w0, double wb, double G, double Gb, double G0)
Definition: af_anequalizer.c:355
filter
void(* filter)(uint8_t *src, int stride, int qscale)
Definition: h263dsp.c:29
EqualizatorFilter::gain
double gain
Definition: af_anequalizer.c:57
AVFilter::name
const char * name
Filter name.
Definition: avfilter.h:205
AVChannelLayout::nb_channels
int nb_channels
Number of channels in this layout.
Definition: channel_layout.h:327
video.h
chebyshev2_bp_filter
static void chebyshev2_bp_filter(EqualizatorFilter *f, int N, double w0, double wb, double G, double Gb, double G0)
Definition: af_anequalizer.c:428
anequalizer_options
static const AVOption anequalizer_options[]
Definition: af_anequalizer.c:83
AudioNEqualizerContext::mag
double mag
Definition: af_anequalizer.c:70
D
D(D(float, sse)
Definition: rematrix_init.c:30
AudioNEqualizerContext::nb_filters
int nb_filters
Definition: af_anequalizer.c:72
FILTER_ORDER
#define FILTER_ORDER
Definition: af_anequalizer.c:34
formats.h
S
#define S(s, c, i)
Definition: flacdsp_template.c:46
filter_frame
static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
Definition: af_anequalizer.c:715
FoSection::b1
double b1
Definition: af_anequalizer.c:45
AudioNEqualizerContext::h
int h
Definition: af_anequalizer.c:68
AudioNEqualizerContext::fscale
int fscale
Definition: af_anequalizer.c:71
AVFrame::ch_layout
AVChannelLayout ch_layout
Channel layout of the audio data.
Definition: frame.h:790
CHEBYSHEV1
@ CHEBYSHEV1
Definition: af_anequalizer.c:38
config_input
static int config_input(AVFilterLink *inlink)
Definition: af_anequalizer.c:558
pts
static int64_t pts
Definition: transcode_aac.c:644
AVFILTER_DEFINE_CLASS
AVFILTER_DEFINE_CLASS(anequalizer)
BUTTERWORTH
@ BUTTERWORTH
Definition: af_anequalizer.c:37
AVFilterPad
A filter pad used for either input or output.
Definition: filters.h:38
FoSection::denum
double denum[4]
Definition: af_anequalizer.c:48
FilterType
FilterType
Definition: af_adenorm.c:26
query_formats
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition: af_anequalizer.c:220
lrint
#define lrint
Definition: tablegen.h:53
FoSection::a2
double a2
Definition: af_anequalizer.c:44
av_cold
#define av_cold
Definition: attributes.h:90
equalizer
static void equalizer(EqualizatorFilter *f, double sample_rate)
Definition: af_anequalizer.c:516
chebyshev2_fo_section
static void chebyshev2_fo_section(FoSection *S, double a, double c, double tetta_b, double g, double si, double b, double D, double c0)
Definition: af_anequalizer.c:396
FoSection::num
double num[4]
Definition: af_anequalizer.c:47
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:198
FoSection::a0
double a0
Definition: af_anequalizer.c:44
g
const char * g
Definition: vf_curves.c:128
AV_OPT_TYPE_DOUBLE
@ AV_OPT_TYPE_DOUBLE
Underlying C type is double.
Definition: opt.h:267
AVMEDIA_TYPE_AUDIO
@ AVMEDIA_TYPE_AUDIO
Definition: avutil.h:202
av_strtok
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok().
Definition: avstring.c:178
chebyshev1_fo_section
static void chebyshev1_fo_section(FoSection *S, double a, double c, double tetta_b, double g0, double si, double b, double D, double c0)
Definition: af_anequalizer.c:323
filters
#define filters(fmt, type, inverse, clp, inverset, clip, one, clip_fn, packed)
Definition: af_crystalizer.c:55
filters.h
pix_fmts
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:304
ctx
AVFormatContext * ctx
Definition: movenc.c:49
av_frame_clone
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition: frame.c:609
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
A
#define A
Definition: af_anequalizer.c:79
hz_2_rad
static double hz_2_rad(double x, double fs)
Definition: af_anequalizer.c:511
AV_PIX_FMT_RGBA
@ AV_PIX_FMT_RGBA
packed RGBA 8:8:8:8, 32bpp, RGBARGBA...
Definition: pixfmt.h:100
arg
const char * arg
Definition: jacosubdec.c:67
uninit
static av_cold void uninit(AVFilterContext *ctx)
Definition: af_anequalizer.c:245
AudioNEqualizerContext
Definition: af_anequalizer.c:63
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:75
NULL
#define NULL
Definition: coverity.c:32
fs
#define fs(width, name, subs,...)
Definition: cbs_vp9.c:200
inputs
static const AVFilterPad inputs[]
Definition: af_anequalizer.c:745
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_OPT_TYPE_IMAGE_SIZE
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
Definition: opt.h:303
FoSection::b3
double b3
Definition: af_anequalizer.c:45
parseutils.h
process_command
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
Definition: af_anequalizer.c:616
AudioNEqualizerContext::video
AVFrame * video
Definition: af_anequalizer.c:75
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
AVFilterFormatsConfig
Lists of formats / etc.
Definition: avfilter.h:111
AVFILTER_FLAG_DYNAMIC_OUTPUTS
#define AVFILTER_FLAG_DYNAMIC_OUTPUTS
The number of the filter outputs is not determined just by AVFilter.outputs.
Definition: avfilter.h:147
AVFILTERPAD_FLAG_NEEDS_WRITABLE
#define AVFILTERPAD_FLAG_NEEDS_WRITABLE
The filter expects writable frames from its input link, duplicating data buffers if needed.
Definition: filters.h:57
f
f
Definition: af_crystalizer.c:122
draw_curves
static void draw_curves(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *out)
Definition: af_anequalizer.c:97
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:94
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
AV_SAMPLE_FMT_NONE
@ AV_SAMPLE_FMT_NONE
Definition: samplefmt.h:56
sample
#define sample
Definition: flacdsp_template.c:44
hypot
static av_const double hypot(double x, double y)
Definition: libm.h:366
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:94
section
Definition: ffprobe.c:241
FoSection::b4
double b4
Definition: af_anequalizer.c:45
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
FoSection
Definition: af_anequalizer.c:43
N
#define N
Definition: af_mcompand.c:54
add_filter
static int add_filter(AudioNEqualizerContext *s, AVFilterLink *inlink)
Definition: af_anequalizer.c:539
M_PI
#define M_PI
Definition: mathematics.h:67
EqualizatorFilter::channel
int channel
Definition: af_anequalizer.c:53
AVFrame::nb_samples
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:469
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
FoSection::b2
double b2
Definition: af_anequalizer.c:45
AVFrame::extended_data
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:450
ff_filter_get_nb_threads
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition: avfilter.c:840
FoSection::b0
double b0
Definition: af_anequalizer.c:45
AVSampleFormat
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:55
section_process
static double section_process(FoSection *S, double in)
Definition: af_anequalizer.c:649
FILTER_QUERY_FUNC2
#define FILTER_QUERY_FUNC2(func)
Definition: filters.h:239
NB_TYPES
@ NB_TYPES
Definition: af_anequalizer.c:40
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
chebyshev1_compute_bw_gain_db
static double chebyshev1_compute_bw_gain_db(double gain)
Definition: af_anequalizer.c:483
AVFilterPad::name
const char * name
Pad name.
Definition: filters.h:44
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:264
chebyshev2_compute_bw_gain_db
static double chebyshev2_compute_bw_gain_db(double gain)
Definition: af_anequalizer.c:497
V
#define V
Definition: af_anequalizer.c:80
OFFSET
#define OFFSET(x)
Definition: af_anequalizer.c:78
AVFilter
Filter definition.
Definition: avfilter.h:201
FoSection::a3
double a3
Definition: af_anequalizer.c:44
ret
ret
Definition: filter_design.txt:187
FoSection::a1
double a1
Definition: af_anequalizer.c:44
AV_RL32
uint64_t_TMPL AV_WL64 unsigned int_TMPL AV_RL32
Definition: bytestream.h:92
ff_set_common_formats_from_list2
int ff_set_common_formats_from_list2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, const int *fmts)
Definition: formats.c:1016
ff_filter_execute
int ff_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition: avfilter.c:1666
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:72
butterworth_bp_filter
static void butterworth_bp_filter(EqualizatorFilter *f, int N, double w0, double wb, double G, double Gb, double G0)
Definition: af_anequalizer.c:286
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition: opt.h:259
avfilter.h
EqualizatorFilter::type
int type
Definition: af_anequalizer.c:54
AV_SAMPLE_FMT_DBLP
@ AV_SAMPLE_FMT_DBLP
double, planar
Definition: samplefmt.h:67
EqualizatorFilter::freq
double freq
Definition: af_anequalizer.c:56
L
#define L(x)
Definition: vpx_arith.h:36
ffmath.h
G
#define G
Definition: huffyuv.h:43
AVFilterContext
An instance of a filter.
Definition: avfilter.h:457
AVFILTER_FLAG_SLICE_THREADS
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition: avfilter.h:152
av_strdup
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:272
AVMEDIA_TYPE_VIDEO
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
mem.h
audio.h
AudioNEqualizerContext::w
int w
Definition: af_anequalizer.c:68
ff_append_outpad
int ff_append_outpad(AVFilterContext *f, AVFilterPad *p)
Definition: avfilter.c:138
process_sample
static double process_sample(FoSection *s1, double in)
Definition: af_anequalizer.c:672
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Underlying C type is int.
Definition: opt.h:327
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
ff_af_anequalizer
const AVFilter ff_af_anequalizer
Definition: af_anequalizer.c:755
AudioNEqualizerContext::filters
EqualizatorFilter * filters
Definition: af_anequalizer.c:74
AudioNEqualizerContext::nb_allocated
int nb_allocated
Definition: af_anequalizer.c:73
AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition: avfilter.h:190
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:482
AudioNEqualizerContext::colors
char * colors
Definition: af_anequalizer.c:66
EqualizatorFilter::ignore
int ignore
Definition: af_anequalizer.c:52
AudioNEqualizerContext::draw_curves
int draw_curves
Definition: af_anequalizer.c:67
avstring.h
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition: opt.h:276
width
#define width
Definition: dsp.h:85
init
static av_cold int init(AVFilterContext *ctx)
Definition: af_anequalizer.c:191
AV_OPT_TYPE_CONST
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition: opt.h:299
FoSection::a4
double a4
Definition: af_anequalizer.c:44
ui
#define ui(width, name)
Definition: cbs_mpeg2.c:113
butterworth_compute_bw_gain_db
static double butterworth_compute_bw_gain_db(double gain)
Definition: af_anequalizer.c:469