FFmpeg
af_firequalizer.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Muhammad Faiz <mfcc64@gmail.com>
3  *
4  * This file is part of FFmpeg.
5  *
6  * FFmpeg is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * FFmpeg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with FFmpeg; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
21 #include "libavutil/opt.h"
22 #include "libavutil/eval.h"
23 #include "libavutil/avassert.h"
24 #include "libavcodec/avfft.h"
25 #include "avfilter.h"
26 #include "internal.h"
27 #include "audio.h"
28 
29 #define RDFT_BITS_MIN 4
30 #define RDFT_BITS_MAX 16
31 
32 enum WindowFunc {
44 };
45 
46 enum Scale {
52 };
53 
54 #define NB_GAIN_ENTRY_MAX 4096
55 typedef struct GainEntry {
56  double freq;
57  double gain;
58 } GainEntry;
59 
60 typedef struct OverlapIndex {
61  int buf_idx;
63 } OverlapIndex;
64 
65 typedef struct FIREqualizerContext {
66  const AVClass *class;
67 
76  int rdft_len;
78 
79  float *analysis_buf;
80  float *dump_buf;
82  float *kernel_buf;
83  float *cepstrum_buf;
84  float *conv_buf;
86  int fir_len;
88  int64_t next_pts;
90  int remaining;
91 
92  char *gain_cmd;
94  const char *gain;
95  const char *gain_entry;
96  double delay;
97  double accuracy;
98  int wfunc;
99  int fixed;
100  int multi;
102  int scale;
103  char *dumpfile;
105  int fft2;
107 
110  GainEntry gain_entry_tbl[NB_GAIN_ENTRY_MAX];
112 
113 #define OFFSET(x) offsetof(FIREqualizerContext, x)
114 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
115 
116 static const AVOption firequalizer_options[] = {
117  { "gain", "set gain curve", OFFSET(gain), AV_OPT_TYPE_STRING, { .str = "gain_interpolate(f)" }, 0, 0, FLAGS },
118  { "gain_entry", "set gain entry", OFFSET(gain_entry), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
119  { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, { .dbl = 0.01 }, 0.0, 1e10, FLAGS },
120  { "accuracy", "set accuracy", OFFSET(accuracy), AV_OPT_TYPE_DOUBLE, { .dbl = 5.0 }, 0.0, 1e10, FLAGS },
121  { "wfunc", "set window function", OFFSET(wfunc), AV_OPT_TYPE_INT, { .i64 = WFUNC_HANN }, 0, NB_WFUNC-1, FLAGS, "wfunc" },
122  { "rectangular", "rectangular window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_RECTANGULAR }, 0, 0, FLAGS, "wfunc" },
123  { "hann", "hann window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HANN }, 0, 0, FLAGS, "wfunc" },
124  { "hamming", "hamming window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HAMMING }, 0, 0, FLAGS, "wfunc" },
125  { "blackman", "blackman window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BLACKMAN }, 0, 0, FLAGS, "wfunc" },
126  { "nuttall3", "3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL3 }, 0, 0, FLAGS, "wfunc" },
127  { "mnuttall3", "minimum 3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_MNUTTALL3 }, 0, 0, FLAGS, "wfunc" },
128  { "nuttall", "nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL }, 0, 0, FLAGS, "wfunc" },
129  { "bnuttall", "blackman-nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BNUTTALL }, 0, 0, FLAGS, "wfunc" },
130  { "bharris", "blackman-harris window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BHARRIS }, 0, 0, FLAGS, "wfunc" },
131  { "tukey", "tukey window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_TUKEY }, 0, 0, FLAGS, "wfunc" },
132  { "fixed", "set fixed frame samples", OFFSET(fixed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
133  { "multi", "set multi channels mode", OFFSET(multi), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
134  { "zero_phase", "set zero phase mode", OFFSET(zero_phase), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
135  { "scale", "set gain scale", OFFSET(scale), AV_OPT_TYPE_INT, { .i64 = SCALE_LINLOG }, 0, NB_SCALE-1, FLAGS, "scale" },
136  { "linlin", "linear-freq linear-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LINLIN }, 0, 0, FLAGS, "scale" },
137  { "linlog", "linear-freq logarithmic-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LINLOG }, 0, 0, FLAGS, "scale" },
138  { "loglin", "logarithmic-freq linear-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LOGLIN }, 0, 0, FLAGS, "scale" },
139  { "loglog", "logarithmic-freq logarithmic-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LOGLOG }, 0, 0, FLAGS, "scale" },
140  { "dumpfile", "set dump file", OFFSET(dumpfile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
141  { "dumpscale", "set dump scale", OFFSET(dumpscale), AV_OPT_TYPE_INT, { .i64 = SCALE_LINLOG }, 0, NB_SCALE-1, FLAGS, "scale" },
142  { "fft2", "set 2-channels fft", OFFSET(fft2), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
143  { "min_phase", "set minimum phase mode", OFFSET(min_phase), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
144  { NULL }
145 };
146 
147 AVFILTER_DEFINE_CLASS(firequalizer);
148 
150 {
153  av_rdft_end(s->rdft);
154  av_rdft_end(s->irdft);
155  av_fft_end(s->fft_ctx);
158  s->analysis_rdft = s->analysis_irdft = s->rdft = s->irdft = NULL;
159  s->fft_ctx = NULL;
160  s->cepstrum_rdft = NULL;
161  s->cepstrum_irdft = NULL;
162 
163  av_freep(&s->analysis_buf);
164  av_freep(&s->dump_buf);
166  av_freep(&s->kernel_buf);
167  av_freep(&s->cepstrum_buf);
168  av_freep(&s->conv_buf);
169  av_freep(&s->conv_idx);
170 }
171 
173 {
174  FIREqualizerContext *s = ctx->priv;
175 
176  common_uninit(s);
177  av_freep(&s->gain_cmd);
179 }
180 
182 {
185  static const enum AVSampleFormat sample_fmts[] = {
188  };
189  int ret;
190 
191  layouts = ff_all_channel_counts();
192  if (!layouts)
193  return AVERROR(ENOMEM);
194  ret = ff_set_common_channel_layouts(ctx, layouts);
195  if (ret < 0)
196  return ret;
197 
198  formats = ff_make_format_list(sample_fmts);
199  if (!formats)
200  return AVERROR(ENOMEM);
201  ret = ff_set_common_formats(ctx, formats);
202  if (ret < 0)
203  return ret;
204 
205  formats = ff_all_samplerates();
206  if (!formats)
207  return AVERROR(ENOMEM);
208  return ff_set_common_samplerates(ctx, formats);
209 }
210 
211 static void fast_convolute(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf,
212  OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
213 {
214  if (nsamples <= s->nsamples_max) {
215  float *buf = conv_buf + idx->buf_idx * s->rdft_len;
216  float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
217  int center = s->fir_len/2;
218  int k;
219 
220  memset(buf, 0, center * sizeof(*data));
221  memcpy(buf + center, data, nsamples * sizeof(*data));
222  memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) * sizeof(*data));
223  av_rdft_calc(s->rdft, buf);
224 
225  buf[0] *= kernel_buf[0];
226  buf[1] *= kernel_buf[s->rdft_len/2];
227  for (k = 1; k < s->rdft_len/2; k++) {
228  buf[2*k] *= kernel_buf[k];
229  buf[2*k+1] *= kernel_buf[k];
230  }
231 
232  av_rdft_calc(s->irdft, buf);
233  for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
234  buf[k] += obuf[k];
235  memcpy(data, buf, nsamples * sizeof(*data));
236  idx->buf_idx = !idx->buf_idx;
237  idx->overlap_idx = nsamples;
238  } else {
239  while (nsamples > s->nsamples_max * 2) {
240  fast_convolute(s, kernel_buf, conv_buf, idx, data, s->nsamples_max);
241  data += s->nsamples_max;
242  nsamples -= s->nsamples_max;
243  }
244  fast_convolute(s, kernel_buf, conv_buf, idx, data, nsamples/2);
245  fast_convolute(s, kernel_buf, conv_buf, idx, data + nsamples/2, nsamples - nsamples/2);
246  }
247 }
248 
249 static void fast_convolute_nonlinear(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf,
250  float *av_restrict conv_buf, OverlapIndex *av_restrict idx,
251  float *av_restrict data, int nsamples)
252 {
253  if (nsamples <= s->nsamples_max) {
254  float *buf = conv_buf + idx->buf_idx * s->rdft_len;
255  float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
256  int k;
257 
258  memcpy(buf, data, nsamples * sizeof(*data));
259  memset(buf + nsamples, 0, (s->rdft_len - nsamples) * sizeof(*data));
260  av_rdft_calc(s->rdft, buf);
261 
262  buf[0] *= kernel_buf[0];
263  buf[1] *= kernel_buf[1];
264  for (k = 2; k < s->rdft_len; k += 2) {
265  float re, im;
266  re = buf[k] * kernel_buf[k] - buf[k+1] * kernel_buf[k+1];
267  im = buf[k] * kernel_buf[k+1] + buf[k+1] * kernel_buf[k];
268  buf[k] = re;
269  buf[k+1] = im;
270  }
271 
272  av_rdft_calc(s->irdft, buf);
273  for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
274  buf[k] += obuf[k];
275  memcpy(data, buf, nsamples * sizeof(*data));
276  idx->buf_idx = !idx->buf_idx;
277  idx->overlap_idx = nsamples;
278  } else {
279  while (nsamples > s->nsamples_max * 2) {
280  fast_convolute_nonlinear(s, kernel_buf, conv_buf, idx, data, s->nsamples_max);
281  data += s->nsamples_max;
282  nsamples -= s->nsamples_max;
283  }
284  fast_convolute_nonlinear(s, kernel_buf, conv_buf, idx, data, nsamples/2);
285  fast_convolute_nonlinear(s, kernel_buf, conv_buf, idx, data + nsamples/2, nsamples - nsamples/2);
286  }
287 }
288 
289 static void fast_convolute2(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, FFTComplex *av_restrict conv_buf,
290  OverlapIndex *av_restrict idx, float *av_restrict data0, float *av_restrict data1, int nsamples)
291 {
292  if (nsamples <= s->nsamples_max) {
293  FFTComplex *buf = conv_buf + idx->buf_idx * s->rdft_len;
294  FFTComplex *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
295  int center = s->fir_len/2;
296  int k;
297  float tmp;
298 
299  memset(buf, 0, center * sizeof(*buf));
300  for (k = 0; k < nsamples; k++) {
301  buf[center+k].re = data0[k];
302  buf[center+k].im = data1[k];
303  }
304  memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) * sizeof(*buf));
305  av_fft_permute(s->fft_ctx, buf);
306  av_fft_calc(s->fft_ctx, buf);
307 
308  /* swap re <-> im, do backward fft using forward fft_ctx */
309  /* normalize with 0.5f */
310  tmp = buf[0].re;
311  buf[0].re = 0.5f * kernel_buf[0] * buf[0].im;
312  buf[0].im = 0.5f * kernel_buf[0] * tmp;
313  for (k = 1; k < s->rdft_len/2; k++) {
314  int m = s->rdft_len - k;
315  tmp = buf[k].re;
316  buf[k].re = 0.5f * kernel_buf[k] * buf[k].im;
317  buf[k].im = 0.5f * kernel_buf[k] * tmp;
318  tmp = buf[m].re;
319  buf[m].re = 0.5f * kernel_buf[k] * buf[m].im;
320  buf[m].im = 0.5f * kernel_buf[k] * tmp;
321  }
322  tmp = buf[k].re;
323  buf[k].re = 0.5f * kernel_buf[k] * buf[k].im;
324  buf[k].im = 0.5f * kernel_buf[k] * tmp;
325 
326  av_fft_permute(s->fft_ctx, buf);
327  av_fft_calc(s->fft_ctx, buf);
328 
329  for (k = 0; k < s->rdft_len - idx->overlap_idx; k++) {
330  buf[k].re += obuf[k].re;
331  buf[k].im += obuf[k].im;
332  }
333 
334  /* swapped re <-> im */
335  for (k = 0; k < nsamples; k++) {
336  data0[k] = buf[k].im;
337  data1[k] = buf[k].re;
338  }
339  idx->buf_idx = !idx->buf_idx;
340  idx->overlap_idx = nsamples;
341  } else {
342  while (nsamples > s->nsamples_max * 2) {
343  fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, s->nsamples_max);
344  data0 += s->nsamples_max;
345  data1 += s->nsamples_max;
346  nsamples -= s->nsamples_max;
347  }
348  fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, nsamples/2);
349  fast_convolute2(s, kernel_buf, conv_buf, idx, data0 + nsamples/2, data1 + nsamples/2, nsamples - nsamples/2);
350  }
351 }
352 
353 static void dump_fir(AVFilterContext *ctx, FILE *fp, int ch)
354 {
355  FIREqualizerContext *s = ctx->priv;
356  int rate = ctx->inputs[0]->sample_rate;
357  int xlog = s->dumpscale == SCALE_LOGLIN || s->dumpscale == SCALE_LOGLOG;
358  int ylog = s->dumpscale == SCALE_LINLOG || s->dumpscale == SCALE_LOGLOG;
359  int x;
360  int center = s->fir_len / 2;
361  double delay = s->zero_phase ? 0.0 : (double) center / rate;
362  double vx, ya, yb;
363 
364  if (!s->min_phase) {
365  s->analysis_buf[0] *= s->rdft_len/2;
366  for (x = 1; x <= center; x++) {
367  s->analysis_buf[x] *= s->rdft_len/2;
368  s->analysis_buf[s->analysis_rdft_len - x] *= s->rdft_len/2;
369  }
370  } else {
371  for (x = 0; x < s->fir_len; x++)
372  s->analysis_buf[x] *= s->rdft_len/2;
373  }
374 
375  if (ch)
376  fprintf(fp, "\n\n");
377 
378  fprintf(fp, "# time[%d] (time amplitude)\n", ch);
379 
380  if (!s->min_phase) {
381  for (x = center; x > 0; x--)
382  fprintf(fp, "%15.10f %15.10f\n", delay - (double) x / rate, (double) s->analysis_buf[s->analysis_rdft_len - x]);
383 
384  for (x = 0; x <= center; x++)
385  fprintf(fp, "%15.10f %15.10f\n", delay + (double)x / rate , (double) s->analysis_buf[x]);
386  } else {
387  for (x = 0; x < s->fir_len; x++)
388  fprintf(fp, "%15.10f %15.10f\n", (double)x / rate, (double) s->analysis_buf[x]);
389  }
390 
392 
393  fprintf(fp, "\n\n# freq[%d] (frequency desired_gain actual_gain)\n", ch);
394 
395  for (x = 0; x <= s->analysis_rdft_len/2; x++) {
396  int i = (x == s->analysis_rdft_len/2) ? 1 : 2 * x;
397  vx = (double)x * rate / s->analysis_rdft_len;
398  if (xlog)
399  vx = log2(0.05*vx);
400  ya = s->dump_buf[i];
401  yb = s->min_phase && (i > 1) ? hypotf(s->analysis_buf[i], s->analysis_buf[i+1]) : s->analysis_buf[i];
402  if (s->min_phase)
403  yb = fabs(yb);
404  if (ylog) {
405  ya = 20.0 * log10(fabs(ya));
406  yb = 20.0 * log10(fabs(yb));
407  }
408  fprintf(fp, "%17.10f %17.10f %17.10f\n", vx, ya, yb);
409  }
410 }
411 
412 static double entry_func(void *p, double freq, double gain)
413 {
414  AVFilterContext *ctx = p;
415  FIREqualizerContext *s = ctx->priv;
416 
417  if (s->nb_gain_entry >= NB_GAIN_ENTRY_MAX) {
418  av_log(ctx, AV_LOG_ERROR, "entry table overflow.\n");
419  s->gain_entry_err = AVERROR(EINVAL);
420  return 0;
421  }
422 
423  if (isnan(freq)) {
424  av_log(ctx, AV_LOG_ERROR, "nan frequency (%g, %g).\n", freq, gain);
425  s->gain_entry_err = AVERROR(EINVAL);
426  return 0;
427  }
428 
429  if (s->nb_gain_entry > 0 && freq <= s->gain_entry_tbl[s->nb_gain_entry - 1].freq) {
430  av_log(ctx, AV_LOG_ERROR, "unsorted frequency (%g, %g).\n", freq, gain);
431  s->gain_entry_err = AVERROR(EINVAL);
432  return 0;
433  }
434 
437  s->nb_gain_entry++;
438  return 0;
439 }
440 
441 static int gain_entry_compare(const void *key, const void *memb)
442 {
443  const double *freq = key;
444  const GainEntry *entry = memb;
445 
446  if (*freq < entry[0].freq)
447  return -1;
448  if (*freq > entry[1].freq)
449  return 1;
450  return 0;
451 }
452 
453 static double gain_interpolate_func(void *p, double freq)
454 {
455  AVFilterContext *ctx = p;
456  FIREqualizerContext *s = ctx->priv;
457  GainEntry *res;
458  double d0, d1, d;
459 
460  if (isnan(freq))
461  return freq;
462 
463  if (!s->nb_gain_entry)
464  return 0;
465 
466  if (freq <= s->gain_entry_tbl[0].freq)
467  return s->gain_entry_tbl[0].gain;
468 
469  if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
470  return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
471 
472  res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
473  av_assert0(res);
474 
475  d = res[1].freq - res[0].freq;
476  d0 = freq - res[0].freq;
477  d1 = res[1].freq - freq;
478 
479  if (d0 && d1)
480  return (d0 * res[1].gain + d1 * res[0].gain) / d;
481 
482  if (d0)
483  return res[1].gain;
484 
485  return res[0].gain;
486 }
487 
488 static double cubic_interpolate_func(void *p, double freq)
489 {
490  AVFilterContext *ctx = p;
491  FIREqualizerContext *s = ctx->priv;
492  GainEntry *res;
493  double x, x2, x3;
494  double a, b, c, d;
495  double m0, m1, m2, msum, unit;
496 
497  if (!s->nb_gain_entry)
498  return 0;
499 
500  if (freq <= s->gain_entry_tbl[0].freq)
501  return s->gain_entry_tbl[0].gain;
502 
503  if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
504  return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
505 
506  res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
507  av_assert0(res);
508 
509  unit = res[1].freq - res[0].freq;
510  m0 = res != s->gain_entry_tbl ?
511  unit * (res[0].gain - res[-1].gain) / (res[0].freq - res[-1].freq) : 0;
512  m1 = res[1].gain - res[0].gain;
513  m2 = res != s->gain_entry_tbl + s->nb_gain_entry - 2 ?
514  unit * (res[2].gain - res[1].gain) / (res[2].freq - res[1].freq) : 0;
515 
516  msum = fabs(m0) + fabs(m1);
517  m0 = msum > 0 ? (fabs(m0) * m1 + fabs(m1) * m0) / msum : 0;
518  msum = fabs(m1) + fabs(m2);
519  m1 = msum > 0 ? (fabs(m1) * m2 + fabs(m2) * m1) / msum : 0;
520 
521  d = res[0].gain;
522  c = m0;
523  b = 3 * res[1].gain - m1 - 2 * c - 3 * d;
524  a = res[1].gain - b - c - d;
525 
526  x = (freq - res[0].freq) / unit;
527  x2 = x * x;
528  x3 = x2 * x;
529 
530  return a * x3 + b * x2 + c * x + d;
531 }
532 
533 static const char *const var_names[] = {
534  "f",
535  "sr",
536  "ch",
537  "chid",
538  "chs",
539  "chlayout",
540  NULL
541 };
542 
543 enum VarOffset {
551 };
552 
553 static void generate_min_phase_kernel(FIREqualizerContext *s, float *rdft_buf)
554 {
555  int k, cepstrum_len = s->cepstrum_len, rdft_len = s->rdft_len;
556  double norm = 2.0 / cepstrum_len;
557  double minval = 1e-7 / rdft_len;
558 
559  memset(s->cepstrum_buf, 0, cepstrum_len * sizeof(*s->cepstrum_buf));
560  memcpy(s->cepstrum_buf, rdft_buf, rdft_len/2 * sizeof(*rdft_buf));
561  memcpy(s->cepstrum_buf + cepstrum_len - rdft_len/2, rdft_buf + rdft_len/2, rdft_len/2 * sizeof(*rdft_buf));
562 
564 
565  s->cepstrum_buf[0] = log(FFMAX(s->cepstrum_buf[0], minval));
566  s->cepstrum_buf[1] = log(FFMAX(s->cepstrum_buf[1], minval));
567 
568  for (k = 2; k < cepstrum_len; k += 2) {
569  s->cepstrum_buf[k] = log(FFMAX(s->cepstrum_buf[k], minval));
570  s->cepstrum_buf[k+1] = 0;
571  }
572 
574 
575  memset(s->cepstrum_buf + cepstrum_len/2 + 1, 0, (cepstrum_len/2 - 1) * sizeof(*s->cepstrum_buf));
576  for (k = 1; k < cepstrum_len/2; k++)
577  s->cepstrum_buf[k] *= 2;
578 
580 
581  s->cepstrum_buf[0] = exp(s->cepstrum_buf[0] * norm) * norm;
582  s->cepstrum_buf[1] = exp(s->cepstrum_buf[1] * norm) * norm;
583  for (k = 2; k < cepstrum_len; k += 2) {
584  double mag = exp(s->cepstrum_buf[k] * norm) * norm;
585  double ph = s->cepstrum_buf[k+1] * norm;
586  s->cepstrum_buf[k] = mag * cos(ph);
587  s->cepstrum_buf[k+1] = mag * sin(ph);
588  }
589 
591  memset(rdft_buf, 0, s->rdft_len * sizeof(*rdft_buf));
592  memcpy(rdft_buf, s->cepstrum_buf, s->fir_len * sizeof(*rdft_buf));
593 
594  if (s->dumpfile) {
595  memset(s->analysis_buf, 0, s->analysis_rdft_len * sizeof(*s->analysis_buf));
596  memcpy(s->analysis_buf, s->cepstrum_buf, s->fir_len * sizeof(*s->analysis_buf));
597  }
598 
599 }
600 
601 static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
602 {
603  FIREqualizerContext *s = ctx->priv;
604  AVFilterLink *inlink = ctx->inputs[0];
605  const char *gain_entry_func_names[] = { "entry", NULL };
606  const char *gain_func_names[] = { "gain_interpolate", "cubic_interpolate", NULL };
607  double (*gain_entry_funcs[])(void *, double, double) = { entry_func, NULL };
608  double (*gain_funcs[])(void *, double) = { gain_interpolate_func, cubic_interpolate_func, NULL };
609  double vars[VAR_NB];
610  AVExpr *gain_expr;
611  int ret, k, center, ch;
612  int xlog = s->scale == SCALE_LOGLIN || s->scale == SCALE_LOGLOG;
613  int ylog = s->scale == SCALE_LINLOG || s->scale == SCALE_LOGLOG;
614  FILE *dump_fp = NULL;
615 
616  s->nb_gain_entry = 0;
617  s->gain_entry_err = 0;
618  if (gain_entry) {
619  double result = 0.0;
620  ret = av_expr_parse_and_eval(&result, gain_entry, NULL, NULL, NULL, NULL,
621  gain_entry_func_names, gain_entry_funcs, ctx, 0, ctx);
622  if (ret < 0)
623  return ret;
624  if (s->gain_entry_err < 0)
625  return s->gain_entry_err;
626  }
627 
628  av_log(ctx, AV_LOG_DEBUG, "nb_gain_entry = %d.\n", s->nb_gain_entry);
629 
630  ret = av_expr_parse(&gain_expr, gain, var_names,
631  gain_func_names, gain_funcs, NULL, NULL, 0, ctx);
632  if (ret < 0)
633  return ret;
634 
635  if (s->dumpfile && (!s->dump_buf || !s->analysis_rdft || !(dump_fp = fopen(s->dumpfile, "w"))))
636  av_log(ctx, AV_LOG_WARNING, "dumping failed.\n");
637 
638  vars[VAR_CHS] = inlink->channels;
639  vars[VAR_CHLAYOUT] = inlink->channel_layout;
640  vars[VAR_SR] = inlink->sample_rate;
641  for (ch = 0; ch < inlink->channels; ch++) {
642  float *rdft_buf = s->kernel_tmp_buf + ch * s->rdft_len;
643  double result;
644  vars[VAR_CH] = ch;
646  vars[VAR_F] = 0.0;
647  if (xlog)
648  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
649  result = av_expr_eval(gain_expr, vars, ctx);
650  s->analysis_buf[0] = ylog ? pow(10.0, 0.05 * result) : result;
651 
652  vars[VAR_F] = 0.5 * inlink->sample_rate;
653  if (xlog)
654  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
655  result = av_expr_eval(gain_expr, vars, ctx);
656  s->analysis_buf[1] = ylog ? pow(10.0, 0.05 * result) : result;
657 
658  for (k = 1; k < s->analysis_rdft_len/2; k++) {
659  vars[VAR_F] = k * ((double)inlink->sample_rate /(double)s->analysis_rdft_len);
660  if (xlog)
661  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
662  result = av_expr_eval(gain_expr, vars, ctx);
663  s->analysis_buf[2*k] = ylog ? pow(10.0, 0.05 * result) : s->min_phase ? fabs(result) : result;
664  s->analysis_buf[2*k+1] = 0.0;
665  }
666 
667  if (s->dump_buf)
668  memcpy(s->dump_buf, s->analysis_buf, s->analysis_rdft_len * sizeof(*s->analysis_buf));
669 
671  center = s->fir_len / 2;
672 
673  for (k = 0; k <= center; k++) {
674  double u = k * (M_PI/center);
675  double win;
676  switch (s->wfunc) {
677  case WFUNC_RECTANGULAR:
678  win = 1.0;
679  break;
680  case WFUNC_HANN:
681  win = 0.5 + 0.5 * cos(u);
682  break;
683  case WFUNC_HAMMING:
684  win = 0.53836 + 0.46164 * cos(u);
685  break;
686  case WFUNC_BLACKMAN:
687  win = 0.42 + 0.5 * cos(u) + 0.08 * cos(2*u);
688  break;
689  case WFUNC_NUTTALL3:
690  win = 0.40897 + 0.5 * cos(u) + 0.09103 * cos(2*u);
691  break;
692  case WFUNC_MNUTTALL3:
693  win = 0.4243801 + 0.4973406 * cos(u) + 0.0782793 * cos(2*u);
694  break;
695  case WFUNC_NUTTALL:
696  win = 0.355768 + 0.487396 * cos(u) + 0.144232 * cos(2*u) + 0.012604 * cos(3*u);
697  break;
698  case WFUNC_BNUTTALL:
699  win = 0.3635819 + 0.4891775 * cos(u) + 0.1365995 * cos(2*u) + 0.0106411 * cos(3*u);
700  break;
701  case WFUNC_BHARRIS:
702  win = 0.35875 + 0.48829 * cos(u) + 0.14128 * cos(2*u) + 0.01168 * cos(3*u);
703  break;
704  case WFUNC_TUKEY:
705  win = (u <= 0.5 * M_PI) ? 1.0 : (0.5 + 0.5 * cos(2*u - M_PI));
706  break;
707  default:
708  av_assert0(0);
709  }
710  s->analysis_buf[k] *= (2.0/s->analysis_rdft_len) * (2.0/s->rdft_len) * win;
711  if (k)
712  s->analysis_buf[s->analysis_rdft_len - k] = s->analysis_buf[k];
713  }
714 
715  memset(s->analysis_buf + center + 1, 0, (s->analysis_rdft_len - s->fir_len) * sizeof(*s->analysis_buf));
716  memcpy(rdft_buf, s->analysis_buf, s->rdft_len/2 * sizeof(*s->analysis_buf));
717  memcpy(rdft_buf + s->rdft_len/2, s->analysis_buf + s->analysis_rdft_len - s->rdft_len/2, s->rdft_len/2 * sizeof(*s->analysis_buf));
718  if (s->min_phase)
719  generate_min_phase_kernel(s, rdft_buf);
720  av_rdft_calc(s->rdft, rdft_buf);
721 
722  for (k = 0; k < s->rdft_len; k++) {
723  if (isnan(rdft_buf[k]) || isinf(rdft_buf[k])) {
724  av_log(ctx, AV_LOG_ERROR, "filter kernel contains nan or infinity.\n");
725  av_expr_free(gain_expr);
726  if (dump_fp)
727  fclose(dump_fp);
728  return AVERROR(EINVAL);
729  }
730  }
731 
732  if (!s->min_phase) {
733  rdft_buf[s->rdft_len-1] = rdft_buf[1];
734  for (k = 0; k < s->rdft_len/2; k++)
735  rdft_buf[k] = rdft_buf[2*k];
736  rdft_buf[s->rdft_len/2] = rdft_buf[s->rdft_len-1];
737  }
738 
739  if (dump_fp)
740  dump_fir(ctx, dump_fp, ch);
741 
742  if (!s->multi)
743  break;
744  }
745 
746  memcpy(s->kernel_buf, s->kernel_tmp_buf, (s->multi ? inlink->channels : 1) * s->rdft_len * sizeof(*s->kernel_buf));
747  av_expr_free(gain_expr);
748  if (dump_fp)
749  fclose(dump_fp);
750  return 0;
751 }
752 
753 #define SELECT_GAIN(s) (s->gain_cmd ? s->gain_cmd : s->gain)
754 #define SELECT_GAIN_ENTRY(s) (s->gain_entry_cmd ? s->gain_entry_cmd : s->gain_entry)
755 
757 {
758  AVFilterContext *ctx = inlink->dst;
759  FIREqualizerContext *s = ctx->priv;
760  int rdft_bits;
761 
762  common_uninit(s);
763 
764  s->next_pts = 0;
765  s->frame_nsamples_max = 0;
766 
767  s->fir_len = FFMAX(2 * (int)(inlink->sample_rate * s->delay) + 1, 3);
768  s->remaining = s->fir_len - 1;
769 
770  for (rdft_bits = RDFT_BITS_MIN; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
771  s->rdft_len = 1 << rdft_bits;
772  s->nsamples_max = s->rdft_len - s->fir_len + 1;
773  if (s->nsamples_max * 2 >= s->fir_len)
774  break;
775  }
776 
777  if (rdft_bits > RDFT_BITS_MAX) {
778  av_log(ctx, AV_LOG_ERROR, "too large delay, please decrease it.\n");
779  return AVERROR(EINVAL);
780  }
781 
782  if (!(s->rdft = av_rdft_init(rdft_bits, DFT_R2C)) || !(s->irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
783  return AVERROR(ENOMEM);
784 
785  if (s->fft2 && !s->multi && inlink->channels > 1 && !(s->fft_ctx = av_fft_init(rdft_bits, 0)))
786  return AVERROR(ENOMEM);
787 
788  if (s->min_phase) {
789  int cepstrum_bits = rdft_bits + 2;
790  if (cepstrum_bits > RDFT_BITS_MAX) {
791  av_log(ctx, AV_LOG_ERROR, "too large delay, please decrease it.\n");
792  return AVERROR(EINVAL);
793  }
794 
795  cepstrum_bits = FFMIN(RDFT_BITS_MAX, cepstrum_bits + 1);
796  s->cepstrum_rdft = av_rdft_init(cepstrum_bits, DFT_R2C);
797  s->cepstrum_irdft = av_rdft_init(cepstrum_bits, IDFT_C2R);
798  if (!s->cepstrum_rdft || !s->cepstrum_irdft)
799  return AVERROR(ENOMEM);
800 
801  s->cepstrum_len = 1 << cepstrum_bits;
803  if (!s->cepstrum_buf)
804  return AVERROR(ENOMEM);
805  }
806 
807  for ( ; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
808  s->analysis_rdft_len = 1 << rdft_bits;
809  if (inlink->sample_rate <= s->accuracy * s->analysis_rdft_len)
810  break;
811  }
812 
813  if (rdft_bits > RDFT_BITS_MAX) {
814  av_log(ctx, AV_LOG_ERROR, "too small accuracy, please increase it.\n");
815  return AVERROR(EINVAL);
816  }
817 
818  if (!(s->analysis_irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
819  return AVERROR(ENOMEM);
820 
821  if (s->dumpfile) {
822  s->analysis_rdft = av_rdft_init(rdft_bits, DFT_R2C);
823  s->dump_buf = av_malloc_array(s->analysis_rdft_len, sizeof(*s->dump_buf));
824  }
825 
827  s->kernel_tmp_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_tmp_buf));
828  s->kernel_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_buf));
829  s->conv_buf = av_calloc(2 * s->rdft_len * inlink->channels, sizeof(*s->conv_buf));
830  s->conv_idx = av_calloc(inlink->channels, sizeof(*s->conv_idx));
831  if (!s->analysis_buf || !s->kernel_tmp_buf || !s->kernel_buf || !s->conv_buf || !s->conv_idx)
832  return AVERROR(ENOMEM);
833 
834  av_log(ctx, AV_LOG_DEBUG, "sample_rate = %d, channels = %d, analysis_rdft_len = %d, rdft_len = %d, fir_len = %d, nsamples_max = %d.\n",
835  inlink->sample_rate, inlink->channels, s->analysis_rdft_len, s->rdft_len, s->fir_len, s->nsamples_max);
836 
837  if (s->fixed)
838  inlink->min_samples = inlink->max_samples = inlink->partial_buf_size = s->nsamples_max;
839 
840  return generate_kernel(ctx, SELECT_GAIN(s), SELECT_GAIN_ENTRY(s));
841 }
842 
844 {
845  AVFilterContext *ctx = inlink->dst;
846  FIREqualizerContext *s = ctx->priv;
847  int ch;
848 
849  if (!s->min_phase) {
850  for (ch = 0; ch + 1 < inlink->channels && s->fft_ctx; ch += 2) {
851  fast_convolute2(s, s->kernel_buf, (FFTComplex *)(s->conv_buf + 2 * ch * s->rdft_len),
852  s->conv_idx + ch, (float *) frame->extended_data[ch],
853  (float *) frame->extended_data[ch+1], frame->nb_samples);
854  }
855 
856  for ( ; ch < inlink->channels; ch++) {
857  fast_convolute(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0),
858  s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch,
859  (float *) frame->extended_data[ch], frame->nb_samples);
860  }
861  } else {
862  for (ch = 0; ch < inlink->channels; ch++) {
863  fast_convolute_nonlinear(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0),
864  s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch,
865  (float *) frame->extended_data[ch], frame->nb_samples);
866  }
867  }
868 
870  if (frame->pts != AV_NOPTS_VALUE) {
871  s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, av_make_q(1, inlink->sample_rate), inlink->time_base);
872  if (s->zero_phase && !s->min_phase)
873  frame->pts -= av_rescale_q(s->fir_len/2, av_make_q(1, inlink->sample_rate), inlink->time_base);
874  }
876  return ff_filter_frame(ctx->outputs[0], frame);
877 }
878 
879 static int request_frame(AVFilterLink *outlink)
880 {
881  AVFilterContext *ctx = outlink->src;
882  FIREqualizerContext *s= ctx->priv;
883  int ret;
884 
885  ret = ff_request_frame(ctx->inputs[0]);
886  if (ret == AVERROR_EOF && s->remaining > 0 && s->frame_nsamples_max > 0) {
888 
889  if (!frame)
890  return AVERROR(ENOMEM);
891 
892  av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, outlink->channels, frame->format);
893  frame->pts = s->next_pts;
894  s->remaining -= frame->nb_samples;
895  ret = filter_frame(ctx->inputs[0], frame);
896  }
897 
898  return ret;
899 }
900 
901 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
902  char *res, int res_len, int flags)
903 {
904  FIREqualizerContext *s = ctx->priv;
905  int ret = AVERROR(ENOSYS);
906 
907  if (!strcmp(cmd, "gain")) {
908  char *gain_cmd;
909 
910  if (SELECT_GAIN(s) && !strcmp(SELECT_GAIN(s), args)) {
911  av_log(ctx, AV_LOG_DEBUG, "equal gain, do not rebuild.\n");
912  return 0;
913  }
914 
915  gain_cmd = av_strdup(args);
916  if (!gain_cmd)
917  return AVERROR(ENOMEM);
918 
919  ret = generate_kernel(ctx, gain_cmd, SELECT_GAIN_ENTRY(s));
920  if (ret >= 0) {
921  av_freep(&s->gain_cmd);
922  s->gain_cmd = gain_cmd;
923  } else {
924  av_freep(&gain_cmd);
925  }
926  } else if (!strcmp(cmd, "gain_entry")) {
927  char *gain_entry_cmd;
928 
929  if (SELECT_GAIN_ENTRY(s) && !strcmp(SELECT_GAIN_ENTRY(s), args)) {
930  av_log(ctx, AV_LOG_DEBUG, "equal gain_entry, do not rebuild.\n");
931  return 0;
932  }
933 
934  gain_entry_cmd = av_strdup(args);
935  if (!gain_entry_cmd)
936  return AVERROR(ENOMEM);
937 
938  ret = generate_kernel(ctx, SELECT_GAIN(s), gain_entry_cmd);
939  if (ret >= 0) {
941  s->gain_entry_cmd = gain_entry_cmd;
942  } else {
943  av_freep(&gain_entry_cmd);
944  }
945  }
946 
947  return ret;
948 }
949 
951  {
952  .name = "default",
953  .config_props = config_input,
954  .filter_frame = filter_frame,
955  .type = AVMEDIA_TYPE_AUDIO,
956  .needs_writable = 1,
957  },
958  { NULL }
959 };
960 
962  {
963  .name = "default",
964  .request_frame = request_frame,
965  .type = AVMEDIA_TYPE_AUDIO,
966  },
967  { NULL }
968 };
969 
971  .name = "firequalizer",
972  .description = NULL_IF_CONFIG_SMALL("Finite Impulse Response Equalizer."),
973  .uninit = uninit,
974  .query_formats = query_formats,
975  .process_command = process_command,
976  .priv_size = sizeof(FIREqualizerContext),
977  .inputs = firequalizer_inputs,
978  .outputs = firequalizer_outputs,
979  .priv_class = &firequalizer_class,
980 };
float, planar
Definition: samplefmt.h:69
#define NULL
Definition: coverity.c:32
int ff_set_common_channel_layouts(AVFilterContext *ctx, AVFilterChannelLayouts *layouts)
A helper for query_formats() which sets all links to the same list of channel layouts/sample rates...
Definition: formats.c:550
#define isinf(x)
Definition: libm.h:317
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
float re
Definition: fft.c:82
#define fixed(width, name, value)
Definition: cbs_av1.c:566
RDFTContext * rdft
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
static void common_uninit(FIREqualizerContext *s)
Main libavfilter public API header.
static float win(SuperEqualizerContext *s, float n, int N)
static void generate_min_phase_kernel(FIREqualizerContext *s, float *rdft_buf)
static double gain_interpolate_func(void *p, double freq)
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:36
FFTSample re
Definition: avfft.h:38
static int request_frame(AVFilterLink *outlink)
#define SELECT_GAIN(s)
void av_fft_permute(FFTContext *s, FFTComplex *z)
Do the permutation needed BEFORE calling ff_fft_calc().
Definition: avfft.c:38
static int config_input(AVFilterLink *inlink)
const char * key
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:683
#define SELECT_GAIN_ENTRY(s)
#define log2(x)
Definition: libm.h:404
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
#define NB_GAIN_ENTRY_MAX
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
#define RDFT_BITS_MIN
static const AVFilterPad firequalizer_outputs[]
const char * name
Pad name.
Definition: internal.h:60
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
VarOffset
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1093
RDFTContext * irdft
#define av_cold
Definition: attributes.h:82
AVOptions.
static double cubic_interpolate_func(void *p, double freq)
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
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
#define RDFT_BITS_MAX
Definition: eval.c:157
#define u(width, name, range_min, range_max)
Definition: cbs_h2645.c:252
static const char *const var_names[]
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
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
int av_expr_parse_and_eval(double *d, const char *s, const char *const *const_names, const double *const_values, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), void *opaque, int log_offset, void *log_ctx)
Parse and evaluate an expression.
Definition: eval.c:748
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:569
int av_samples_set_silence(uint8_t **audio_data, int offset, int nb_samples, int nb_channels, enum AVSampleFormat sample_fmt)
Fill an audio buffer with silence.
Definition: samplefmt.c:237
AVFrame * ff_get_audio_buffer(AVFilterLink *link, int nb_samples)
Request an audio samples buffer with a specific set of permissions.
Definition: audio.c:86
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
AVFILTER_DEFINE_CLASS(firequalizer)
RDFTContext * cepstrum_rdft
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
simple assert() macros that are a bit more flexible than ISO C assert().
Definition: avfft.h:73
FFTContext * av_fft_init(int nbits, int inverse)
Set up a complex FFT.
Definition: avfft.c:28
RDFTContext * cepstrum_irdft
#define FFMAX(a, b)
Definition: common.h:94
RDFTContext * analysis_irdft
int8_t exp
Definition: eval.c:72
static av_cold void uninit(AVFilterContext *ctx)
static const AVOption firequalizer_options[]
void av_rdft_calc(RDFTContext *s, FFTSample *data)
#define b
Definition: input.c:41
Definition: fft.h:88
static const AVFilterPad firequalizer_inputs[]
WindowFunc
static void fast_convolute2(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, FFTComplex *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data0, float *av_restrict data1, int nsamples)
#define FFMIN(a, b)
Definition: common.h:96
static void fast_convolute_nonlinear(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
AVFormatContext * ctx
Definition: movenc.c:48
#define FLAGS
const char * gain_entry
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
Definition: avfft.h:72
void av_rdft_end(RDFTContext *s)
RDFTContext * av_rdft_init(int nbits, enum RDFTransformType trans)
Set up a real FFT.
OverlapIndex * conv_idx
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
A list of supported channel layouts.
Definition: formats.h:85
static double entry_func(void *p, double freq, double gain)
if(ret)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
static const uint8_t vars[2][12]
Definition: camellia.c:179
#define OFFSET(x)
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
AVSampleFormat
Audio sample formats.
Definition: samplefmt.h:58
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
AVFilter ff_af_firequalizer
static AVRational av_make_q(int num, int den)
Create an AVRational.
Definition: rational.h:71
FFT functions.
Scale
#define fp
Definition: regdef.h:44
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
static void fast_convolute(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf, OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
void * buf
Definition: avisynth_c.h:766
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
#define isnan(x)
Definition: libm.h:340
float im
Definition: fft.c:82
GainEntry gain_entry_tbl[NB_GAIN_ENTRY_MAX]
const char * name
Filter name.
Definition: avfilter.h:148
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(const uint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(const int16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(const int16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(const int32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(const int32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(const int64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0f/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(const int64_t *) pi *(1.0/(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(const float *) pi *(UINT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(const double *) pi *(UINT64_C(1)<< 63)))#define FMT_PAIR_FUNC(out, in) static conv_func_type *const fmt_pair_to_conv_functions[AV_SAMPLE_FMT_NB *AV_SAMPLE_FMT_NB]={FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_U8), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S16), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S32), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_FLT), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_DBL), FMT_PAIR_FUNC(AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_FLT, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_DBL, AV_SAMPLE_FMT_S64), FMT_PAIR_FUNC(AV_SAMPLE_FMT_S64, AV_SAMPLE_FMT_S64),};static void cpy1(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, len);}static void cpy2(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 2 *len);}static void cpy4(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 4 *len);}static void cpy8(uint8_t **dst, const uint8_t **src, int len){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, const int *ch_map, int flags){AudioConvert *ctx;conv_func_type *f=fmt_pair_to_conv_functions[av_get_packed_sample_fmt(out_fmt)+AV_SAMPLE_FMT_NB *av_get_packed_sample_fmt(in_fmt)];if(!f) return NULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) return NULL;if(channels==1){in_fmt=av_get_planar_sample_fmt(in_fmt);out_fmt=av_get_planar_sample_fmt(out_fmt);}ctx->channels=channels;ctx->conv_f=f;ctx->ch_map=ch_map;if(in_fmt==AV_SAMPLE_FMT_U8||in_fmt==AV_SAMPLE_FMT_U8P) memset(ctx->silence, 0x80, sizeof(ctx->silence));if(out_fmt==in_fmt &&!ch_map){switch(av_get_bytes_per_sample(in_fmt)){case 1:ctx->simd_f=cpy1;break;case 2:ctx->simd_f=cpy2;break;case 4:ctx->simd_f=cpy4;break;case 8:ctx->simd_f=cpy8;break;}}if(HAVE_X86ASM &&1) swri_audio_convert_init_x86(ctx, out_fmt, in_fmt, channels);if(ARCH_ARM) swri_audio_convert_init_arm(ctx, out_fmt, in_fmt, channels);if(ARCH_AARCH64) swri_audio_convert_init_aarch64(ctx, out_fmt, in_fmt, channels);return ctx;}void swri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}int swri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, int len){int ch;int off=0;const int os=(out->planar?1:out->ch_count)*out->bps;unsigned misaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){int planes=in->planar?in->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) in->ch[ch];misaligned|=m &ctx->in_simd_align_mask;}if(ctx->out_simd_align_mask){int planes=out->planar?out->ch_count:1;unsigned m=0;for(ch=0;ch< planes;ch++) m|=(intptr_t) out->ch[ch];misaligned|=m &ctx->out_simd_align_mask;}if(ctx->simd_f &&!ctx->ch_map &&!misaligned){off=len &~15;av_assert1(off >=0);av_assert1(off<=len);av_assert2(ctx->channels==SWR_CH_MAX||!in->ch[ctx->channels]);if(off >0){if(out->planar==in->planar){int planes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:394
static void dump_fir(AVFilterContext *ctx, FILE *fp, int ch)
#define flags(name, subs,...)
Definition: cbs_av1.c:561
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
FFTSample im
Definition: avfft.h:38
RDFTContext * analysis_rdft
uint64_t av_channel_layout_extract_channel(uint64_t channel_layout, int index)
Get the channel with the given index in channel_layout.
static int query_formats(AVFilterContext *ctx)
static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:738
A list of supported formats for one end of a filter link.
Definition: formats.h:64
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
An instance of a filter.
Definition: avfilter.h:338
and forward the result(frame or status change) to the corresponding input.If nothing is possible
static enum AVSampleFormat sample_fmts[]
Definition: adpcmenc.c:701
FFTContext * fft_ctx
#define av_freep(p)
#define M_PI
Definition: mathematics.h:52
#define av_malloc_array(a, b)
static int gain_entry_compare(const void *key, const void *memb)
int ff_request_frame(AVFilterLink *link)
Request an input frame from the filter at the other end of the link.
Definition: avfilter.c:407
formats
Definition: signature.h:48
internal API functions
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
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition...
Definition: formats.c:409
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:342
void av_fft_calc(FFTContext *s, FFTComplex *z)
Do a complex FFT with the parameters defined in av_fft_init().
Definition: avfft.c:43
int nb_samples
number of audio samples (per channel) described by this frame
Definition: frame.h:361
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:557
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
simple arithmetic expression evaluator
static uint8_t tmp[11]
Definition: aes_ctr.c:26