FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 {
56  double freq;
57  double gain;
58 } GainEntry;
59 
60 typedef struct {
61  int buf_idx;
63 } OverlapIndex;
64 
65 typedef struct {
66  const AVClass *class;
67 
74  int rdft_len;
75 
76  float *analysis_buf;
77  float *dump_buf;
79  float *kernel_buf;
80  float *conv_buf;
82  int fir_len;
84  int64_t next_pts;
86  int remaining;
87 
88  char *gain_cmd;
90  const char *gain;
91  const char *gain_entry;
92  double delay;
93  double accuracy;
94  int wfunc;
95  int fixed;
96  int multi;
98  int scale;
99  char *dumpfile;
101  int fft2;
102 
105  GainEntry gain_entry_tbl[NB_GAIN_ENTRY_MAX];
107 
108 #define OFFSET(x) offsetof(FIREqualizerContext, x)
109 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
110 
111 static const AVOption firequalizer_options[] = {
112  { "gain", "set gain curve", OFFSET(gain), AV_OPT_TYPE_STRING, { .str = "gain_interpolate(f)" }, 0, 0, FLAGS },
113  { "gain_entry", "set gain entry", OFFSET(gain_entry), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
114  { "delay", "set delay", OFFSET(delay), AV_OPT_TYPE_DOUBLE, { .dbl = 0.01 }, 0.0, 1e10, FLAGS },
115  { "accuracy", "set accuracy", OFFSET(accuracy), AV_OPT_TYPE_DOUBLE, { .dbl = 5.0 }, 0.0, 1e10, FLAGS },
116  { "wfunc", "set window function", OFFSET(wfunc), AV_OPT_TYPE_INT, { .i64 = WFUNC_HANN }, 0, NB_WFUNC-1, FLAGS, "wfunc" },
117  { "rectangular", "rectangular window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_RECTANGULAR }, 0, 0, FLAGS, "wfunc" },
118  { "hann", "hann window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HANN }, 0, 0, FLAGS, "wfunc" },
119  { "hamming", "hamming window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_HAMMING }, 0, 0, FLAGS, "wfunc" },
120  { "blackman", "blackman window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BLACKMAN }, 0, 0, FLAGS, "wfunc" },
121  { "nuttall3", "3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL3 }, 0, 0, FLAGS, "wfunc" },
122  { "mnuttall3", "minimum 3-term nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_MNUTTALL3 }, 0, 0, FLAGS, "wfunc" },
123  { "nuttall", "nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_NUTTALL }, 0, 0, FLAGS, "wfunc" },
124  { "bnuttall", "blackman-nuttall window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BNUTTALL }, 0, 0, FLAGS, "wfunc" },
125  { "bharris", "blackman-harris window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_BHARRIS }, 0, 0, FLAGS, "wfunc" },
126  { "tukey", "tukey window", 0, AV_OPT_TYPE_CONST, { .i64 = WFUNC_TUKEY }, 0, 0, FLAGS, "wfunc" },
127  { "fixed", "set fixed frame samples", OFFSET(fixed), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
128  { "multi", "set multi channels mode", OFFSET(multi), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
129  { "zero_phase", "set zero phase mode", OFFSET(zero_phase), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
130  { "scale", "set gain scale", OFFSET(scale), AV_OPT_TYPE_INT, { .i64 = SCALE_LINLOG }, 0, NB_SCALE-1, FLAGS, "scale" },
131  { "linlin", "linear-freq linear-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LINLIN }, 0, 0, FLAGS, "scale" },
132  { "linlog", "linear-freq logarithmic-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LINLOG }, 0, 0, FLAGS, "scale" },
133  { "loglin", "logarithmic-freq linear-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LOGLIN }, 0, 0, FLAGS, "scale" },
134  { "loglog", "logarithmic-freq logarithmic-gain", 0, AV_OPT_TYPE_CONST, { .i64 = SCALE_LOGLOG }, 0, 0, FLAGS, "scale" },
135  { "dumpfile", "set dump file", OFFSET(dumpfile), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
136  { "dumpscale", "set dump scale", OFFSET(dumpscale), AV_OPT_TYPE_INT, { .i64 = SCALE_LINLOG }, 0, NB_SCALE-1, FLAGS, "scale" },
137  { "fft2", "set 2-channels fft", OFFSET(fft2), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
138  { NULL }
139 };
140 
141 AVFILTER_DEFINE_CLASS(firequalizer);
142 
144 {
147  av_rdft_end(s->rdft);
148  av_rdft_end(s->irdft);
149  av_fft_end(s->fft_ctx);
150  s->analysis_rdft = s->analysis_irdft = s->rdft = s->irdft = NULL;
151  s->fft_ctx = NULL;
152 
153  av_freep(&s->analysis_buf);
154  av_freep(&s->dump_buf);
156  av_freep(&s->kernel_buf);
157  av_freep(&s->conv_buf);
158  av_freep(&s->conv_idx);
159 }
160 
162 {
163  FIREqualizerContext *s = ctx->priv;
164 
165  common_uninit(s);
166  av_freep(&s->gain_cmd);
168 }
169 
171 {
174  static const enum AVSampleFormat sample_fmts[] = {
177  };
178  int ret;
179 
180  layouts = ff_all_channel_counts();
181  if (!layouts)
182  return AVERROR(ENOMEM);
183  ret = ff_set_common_channel_layouts(ctx, layouts);
184  if (ret < 0)
185  return ret;
186 
187  formats = ff_make_format_list(sample_fmts);
188  if (!formats)
189  return AVERROR(ENOMEM);
190  ret = ff_set_common_formats(ctx, formats);
191  if (ret < 0)
192  return ret;
193 
194  formats = ff_all_samplerates();
195  if (!formats)
196  return AVERROR(ENOMEM);
197  return ff_set_common_samplerates(ctx, formats);
198 }
199 
200 static void fast_convolute(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, float *av_restrict conv_buf,
201  OverlapIndex *av_restrict idx, float *av_restrict data, int nsamples)
202 {
203  if (nsamples <= s->nsamples_max) {
204  float *buf = conv_buf + idx->buf_idx * s->rdft_len;
205  float *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
206  int center = s->fir_len/2;
207  int k;
208 
209  memset(buf, 0, center * sizeof(*data));
210  memcpy(buf + center, data, nsamples * sizeof(*data));
211  memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) * sizeof(*data));
212  av_rdft_calc(s->rdft, buf);
213 
214  buf[0] *= kernel_buf[0];
215  buf[1] *= kernel_buf[s->rdft_len/2];
216  for (k = 1; k < s->rdft_len/2; k++) {
217  buf[2*k] *= kernel_buf[k];
218  buf[2*k+1] *= kernel_buf[k];
219  }
220 
221  av_rdft_calc(s->irdft, buf);
222  for (k = 0; k < s->rdft_len - idx->overlap_idx; k++)
223  buf[k] += obuf[k];
224  memcpy(data, buf, nsamples * sizeof(*data));
225  idx->buf_idx = !idx->buf_idx;
226  idx->overlap_idx = nsamples;
227  } else {
228  while (nsamples > s->nsamples_max * 2) {
229  fast_convolute(s, kernel_buf, conv_buf, idx, data, s->nsamples_max);
230  data += s->nsamples_max;
231  nsamples -= s->nsamples_max;
232  }
233  fast_convolute(s, kernel_buf, conv_buf, idx, data, nsamples/2);
234  fast_convolute(s, kernel_buf, conv_buf, idx, data + nsamples/2, nsamples - nsamples/2);
235  }
236 }
237 
238 static void fast_convolute2(FIREqualizerContext *av_restrict s, const float *av_restrict kernel_buf, FFTComplex *av_restrict conv_buf,
239  OverlapIndex *av_restrict idx, float *av_restrict data0, float *av_restrict data1, int nsamples)
240 {
241  if (nsamples <= s->nsamples_max) {
242  FFTComplex *buf = conv_buf + idx->buf_idx * s->rdft_len;
243  FFTComplex *obuf = conv_buf + !idx->buf_idx * s->rdft_len + idx->overlap_idx;
244  int center = s->fir_len/2;
245  int k;
246  float tmp;
247 
248  memset(buf, 0, center * sizeof(*buf));
249  for (k = 0; k < nsamples; k++) {
250  buf[center+k].re = data0[k];
251  buf[center+k].im = data1[k];
252  }
253  memset(buf + center + nsamples, 0, (s->rdft_len - nsamples - center) * sizeof(*buf));
254  av_fft_permute(s->fft_ctx, buf);
255  av_fft_calc(s->fft_ctx, buf);
256 
257  /* swap re <-> im, do backward fft using forward fft_ctx */
258  /* normalize with 0.5f */
259  tmp = buf[0].re;
260  buf[0].re = 0.5f * kernel_buf[0] * buf[0].im;
261  buf[0].im = 0.5f * kernel_buf[0] * tmp;
262  for (k = 1; k < s->rdft_len/2; k++) {
263  int m = s->rdft_len - k;
264  tmp = buf[k].re;
265  buf[k].re = 0.5f * kernel_buf[k] * buf[k].im;
266  buf[k].im = 0.5f * kernel_buf[k] * tmp;
267  tmp = buf[m].re;
268  buf[m].re = 0.5f * kernel_buf[k] * buf[m].im;
269  buf[m].im = 0.5f * kernel_buf[k] * tmp;
270  }
271  tmp = buf[k].re;
272  buf[k].re = 0.5f * kernel_buf[k] * buf[k].im;
273  buf[k].im = 0.5f * kernel_buf[k] * tmp;
274 
275  av_fft_permute(s->fft_ctx, buf);
276  av_fft_calc(s->fft_ctx, buf);
277 
278  for (k = 0; k < s->rdft_len - idx->overlap_idx; k++) {
279  buf[k].re += obuf[k].re;
280  buf[k].im += obuf[k].im;
281  }
282 
283  /* swapped re <-> im */
284  for (k = 0; k < nsamples; k++) {
285  data0[k] = buf[k].im;
286  data1[k] = buf[k].re;
287  }
288  idx->buf_idx = !idx->buf_idx;
289  idx->overlap_idx = nsamples;
290  } else {
291  while (nsamples > s->nsamples_max * 2) {
292  fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, s->nsamples_max);
293  data0 += s->nsamples_max;
294  data1 += s->nsamples_max;
295  nsamples -= s->nsamples_max;
296  }
297  fast_convolute2(s, kernel_buf, conv_buf, idx, data0, data1, nsamples/2);
298  fast_convolute2(s, kernel_buf, conv_buf, idx, data0 + nsamples/2, data1 + nsamples/2, nsamples - nsamples/2);
299  }
300 }
301 
302 static void dump_fir(AVFilterContext *ctx, FILE *fp, int ch)
303 {
304  FIREqualizerContext *s = ctx->priv;
305  int rate = ctx->inputs[0]->sample_rate;
306  int xlog = s->dumpscale == SCALE_LOGLIN || s->dumpscale == SCALE_LOGLOG;
307  int ylog = s->dumpscale == SCALE_LINLOG || s->dumpscale == SCALE_LOGLOG;
308  int x;
309  int center = s->fir_len / 2;
310  double delay = s->zero_phase ? 0.0 : (double) center / rate;
311  double vx, ya, yb;
312 
313  s->analysis_buf[0] *= s->rdft_len/2;
314  for (x = 1; x <= center; x++) {
315  s->analysis_buf[x] *= s->rdft_len/2;
316  s->analysis_buf[s->analysis_rdft_len - x] *= s->rdft_len/2;
317  }
318 
319  if (ch)
320  fprintf(fp, "\n\n");
321 
322  fprintf(fp, "# time[%d] (time amplitude)\n", ch);
323 
324  for (x = center; x > 0; x--)
325  fprintf(fp, "%15.10f %15.10f\n", delay - (double) x / rate, (double) s->analysis_buf[s->analysis_rdft_len - x]);
326 
327  for (x = 0; x <= center; x++)
328  fprintf(fp, "%15.10f %15.10f\n", delay + (double)x / rate , (double) s->analysis_buf[x]);
329 
331 
332  fprintf(fp, "\n\n# freq[%d] (frequency desired_gain actual_gain)\n", ch);
333 
334  for (x = 0; x <= s->analysis_rdft_len/2; x++) {
335  int i = (x == s->analysis_rdft_len/2) ? 1 : 2 * x;
336  vx = (double)x * rate / s->analysis_rdft_len;
337  if (xlog)
338  vx = log2(0.05*vx);
339  ya = s->dump_buf[i];
340  yb = s->analysis_buf[i];
341  if (ylog) {
342  ya = 20.0 * log10(fabs(ya));
343  yb = 20.0 * log10(fabs(yb));
344  }
345  fprintf(fp, "%17.10f %17.10f %17.10f\n", vx, ya, yb);
346  }
347 }
348 
349 static double entry_func(void *p, double freq, double gain)
350 {
351  AVFilterContext *ctx = p;
352  FIREqualizerContext *s = ctx->priv;
353 
354  if (s->nb_gain_entry >= NB_GAIN_ENTRY_MAX) {
355  av_log(ctx, AV_LOG_ERROR, "entry table overflow.\n");
356  s->gain_entry_err = AVERROR(EINVAL);
357  return 0;
358  }
359 
360  if (isnan(freq)) {
361  av_log(ctx, AV_LOG_ERROR, "nan frequency (%g, %g).\n", freq, gain);
362  s->gain_entry_err = AVERROR(EINVAL);
363  return 0;
364  }
365 
366  if (s->nb_gain_entry > 0 && freq <= s->gain_entry_tbl[s->nb_gain_entry - 1].freq) {
367  av_log(ctx, AV_LOG_ERROR, "unsorted frequency (%g, %g).\n", freq, gain);
368  s->gain_entry_err = AVERROR(EINVAL);
369  return 0;
370  }
371 
372  s->gain_entry_tbl[s->nb_gain_entry].freq = freq;
373  s->gain_entry_tbl[s->nb_gain_entry].gain = gain;
374  s->nb_gain_entry++;
375  return 0;
376 }
377 
378 static int gain_entry_compare(const void *key, const void *memb)
379 {
380  const double *freq = key;
381  const GainEntry *entry = memb;
382 
383  if (*freq < entry[0].freq)
384  return -1;
385  if (*freq > entry[1].freq)
386  return 1;
387  return 0;
388 }
389 
390 static double gain_interpolate_func(void *p, double freq)
391 {
392  AVFilterContext *ctx = p;
393  FIREqualizerContext *s = ctx->priv;
394  GainEntry *res;
395  double d0, d1, d;
396 
397  if (isnan(freq))
398  return freq;
399 
400  if (!s->nb_gain_entry)
401  return 0;
402 
403  if (freq <= s->gain_entry_tbl[0].freq)
404  return s->gain_entry_tbl[0].gain;
405 
406  if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
407  return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
408 
409  res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
410  av_assert0(res);
411 
412  d = res[1].freq - res[0].freq;
413  d0 = freq - res[0].freq;
414  d1 = res[1].freq - freq;
415 
416  if (d0 && d1)
417  return (d0 * res[1].gain + d1 * res[0].gain) / d;
418 
419  if (d0)
420  return res[1].gain;
421 
422  return res[0].gain;
423 }
424 
425 static double cubic_interpolate_func(void *p, double freq)
426 {
427  AVFilterContext *ctx = p;
428  FIREqualizerContext *s = ctx->priv;
429  GainEntry *res;
430  double x, x2, x3;
431  double a, b, c, d;
432  double m0, m1, m2, msum, unit;
433 
434  if (!s->nb_gain_entry)
435  return 0;
436 
437  if (freq <= s->gain_entry_tbl[0].freq)
438  return s->gain_entry_tbl[0].gain;
439 
440  if (freq >= s->gain_entry_tbl[s->nb_gain_entry-1].freq)
441  return s->gain_entry_tbl[s->nb_gain_entry-1].gain;
442 
443  res = bsearch(&freq, &s->gain_entry_tbl, s->nb_gain_entry - 1, sizeof(*res), gain_entry_compare);
444  av_assert0(res);
445 
446  unit = res[1].freq - res[0].freq;
447  m0 = res != s->gain_entry_tbl ?
448  unit * (res[0].gain - res[-1].gain) / (res[0].freq - res[-1].freq) : 0;
449  m1 = res[1].gain - res[0].gain;
450  m2 = res != s->gain_entry_tbl + s->nb_gain_entry - 2 ?
451  unit * (res[2].gain - res[1].gain) / (res[2].freq - res[1].freq) : 0;
452 
453  msum = fabs(m0) + fabs(m1);
454  m0 = msum > 0 ? (fabs(m0) * m1 + fabs(m1) * m0) / msum : 0;
455  msum = fabs(m1) + fabs(m2);
456  m1 = msum > 0 ? (fabs(m1) * m2 + fabs(m2) * m1) / msum : 0;
457 
458  d = res[0].gain;
459  c = m0;
460  b = 3 * res[1].gain - m1 - 2 * c - 3 * d;
461  a = res[1].gain - b - c - d;
462 
463  x = (freq - res[0].freq) / unit;
464  x2 = x * x;
465  x3 = x2 * x;
466 
467  return a * x3 + b * x2 + c * x + d;
468 }
469 
470 static const char *const var_names[] = {
471  "f",
472  "sr",
473  "ch",
474  "chid",
475  "chs",
476  "chlayout",
477  NULL
478 };
479 
480 enum VarOffset {
488 };
489 
490 static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
491 {
492  FIREqualizerContext *s = ctx->priv;
493  AVFilterLink *inlink = ctx->inputs[0];
494  const char *gain_entry_func_names[] = { "entry", NULL };
495  const char *gain_func_names[] = { "gain_interpolate", "cubic_interpolate", NULL };
496  double (*gain_entry_funcs[])(void *, double, double) = { entry_func, NULL };
497  double (*gain_funcs[])(void *, double) = { gain_interpolate_func, cubic_interpolate_func, NULL };
498  double vars[VAR_NB];
499  AVExpr *gain_expr;
500  int ret, k, center, ch;
501  int xlog = s->scale == SCALE_LOGLIN || s->scale == SCALE_LOGLOG;
502  int ylog = s->scale == SCALE_LINLOG || s->scale == SCALE_LOGLOG;
503  FILE *dump_fp = NULL;
504 
505  s->nb_gain_entry = 0;
506  s->gain_entry_err = 0;
507  if (gain_entry) {
508  double result = 0.0;
509  ret = av_expr_parse_and_eval(&result, gain_entry, NULL, NULL, NULL, NULL,
510  gain_entry_func_names, gain_entry_funcs, ctx, 0, ctx);
511  if (ret < 0)
512  return ret;
513  if (s->gain_entry_err < 0)
514  return s->gain_entry_err;
515  }
516 
517  av_log(ctx, AV_LOG_DEBUG, "nb_gain_entry = %d.\n", s->nb_gain_entry);
518 
519  ret = av_expr_parse(&gain_expr, gain, var_names,
520  gain_func_names, gain_funcs, NULL, NULL, 0, ctx);
521  if (ret < 0)
522  return ret;
523 
524  if (s->dumpfile && (!s->dump_buf || !s->analysis_rdft || !(dump_fp = fopen(s->dumpfile, "w"))))
525  av_log(ctx, AV_LOG_WARNING, "dumping failed.\n");
526 
527  vars[VAR_CHS] = inlink->channels;
528  vars[VAR_CHLAYOUT] = inlink->channel_layout;
529  vars[VAR_SR] = inlink->sample_rate;
530  for (ch = 0; ch < inlink->channels; ch++) {
531  float *rdft_buf = s->kernel_tmp_buf + ch * s->rdft_len;
532  double result;
533  vars[VAR_CH] = ch;
535  vars[VAR_F] = 0.0;
536  if (xlog)
537  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
538  result = av_expr_eval(gain_expr, vars, ctx);
539  s->analysis_buf[0] = ylog ? pow(10.0, 0.05 * result) : result;
540 
541  vars[VAR_F] = 0.5 * inlink->sample_rate;
542  if (xlog)
543  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
544  result = av_expr_eval(gain_expr, vars, ctx);
545  s->analysis_buf[1] = ylog ? pow(10.0, 0.05 * result) : result;
546 
547  for (k = 1; k < s->analysis_rdft_len/2; k++) {
548  vars[VAR_F] = k * ((double)inlink->sample_rate /(double)s->analysis_rdft_len);
549  if (xlog)
550  vars[VAR_F] = log2(0.05 * vars[VAR_F]);
551  result = av_expr_eval(gain_expr, vars, ctx);
552  s->analysis_buf[2*k] = ylog ? pow(10.0, 0.05 * result) : result;
553  s->analysis_buf[2*k+1] = 0.0;
554  }
555 
556  if (s->dump_buf)
557  memcpy(s->dump_buf, s->analysis_buf, s->analysis_rdft_len * sizeof(*s->analysis_buf));
558 
560  center = s->fir_len / 2;
561 
562  for (k = 0; k <= center; k++) {
563  double u = k * (M_PI/center);
564  double win;
565  switch (s->wfunc) {
566  case WFUNC_RECTANGULAR:
567  win = 1.0;
568  break;
569  case WFUNC_HANN:
570  win = 0.5 + 0.5 * cos(u);
571  break;
572  case WFUNC_HAMMING:
573  win = 0.53836 + 0.46164 * cos(u);
574  break;
575  case WFUNC_BLACKMAN:
576  win = 0.42 + 0.5 * cos(u) + 0.08 * cos(2*u);
577  break;
578  case WFUNC_NUTTALL3:
579  win = 0.40897 + 0.5 * cos(u) + 0.09103 * cos(2*u);
580  break;
581  case WFUNC_MNUTTALL3:
582  win = 0.4243801 + 0.4973406 * cos(u) + 0.0782793 * cos(2*u);
583  break;
584  case WFUNC_NUTTALL:
585  win = 0.355768 + 0.487396 * cos(u) + 0.144232 * cos(2*u) + 0.012604 * cos(3*u);
586  break;
587  case WFUNC_BNUTTALL:
588  win = 0.3635819 + 0.4891775 * cos(u) + 0.1365995 * cos(2*u) + 0.0106411 * cos(3*u);
589  break;
590  case WFUNC_BHARRIS:
591  win = 0.35875 + 0.48829 * cos(u) + 0.14128 * cos(2*u) + 0.01168 * cos(3*u);
592  break;
593  case WFUNC_TUKEY:
594  win = (u <= 0.5 * M_PI) ? 1.0 : (0.5 + 0.5 * cos(2*u - M_PI));
595  break;
596  default:
597  av_assert0(0);
598  }
599  s->analysis_buf[k] *= (2.0/s->analysis_rdft_len) * (2.0/s->rdft_len) * win;
600  if (k)
601  s->analysis_buf[s->analysis_rdft_len - k] = s->analysis_buf[k];
602  }
603 
604  memset(s->analysis_buf + center + 1, 0, (s->analysis_rdft_len - s->fir_len) * sizeof(*s->analysis_buf));
605  memcpy(rdft_buf, s->analysis_buf, s->rdft_len/2 * sizeof(*s->analysis_buf));
606  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));
607  av_rdft_calc(s->rdft, rdft_buf);
608 
609  for (k = 0; k < s->rdft_len; k++) {
610  if (isnan(rdft_buf[k]) || isinf(rdft_buf[k])) {
611  av_log(ctx, AV_LOG_ERROR, "filter kernel contains nan or infinity.\n");
612  av_expr_free(gain_expr);
613  if (dump_fp)
614  fclose(dump_fp);
615  return AVERROR(EINVAL);
616  }
617  }
618 
619  rdft_buf[s->rdft_len-1] = rdft_buf[1];
620  for (k = 0; k < s->rdft_len/2; k++)
621  rdft_buf[k] = rdft_buf[2*k];
622  rdft_buf[s->rdft_len/2] = rdft_buf[s->rdft_len-1];
623 
624  if (dump_fp)
625  dump_fir(ctx, dump_fp, ch);
626 
627  if (!s->multi)
628  break;
629  }
630 
631  memcpy(s->kernel_buf, s->kernel_tmp_buf, (s->multi ? inlink->channels : 1) * s->rdft_len * sizeof(*s->kernel_buf));
632  av_expr_free(gain_expr);
633  if (dump_fp)
634  fclose(dump_fp);
635  return 0;
636 }
637 
638 #define SELECT_GAIN(s) (s->gain_cmd ? s->gain_cmd : s->gain)
639 #define SELECT_GAIN_ENTRY(s) (s->gain_entry_cmd ? s->gain_entry_cmd : s->gain_entry)
640 
641 static int config_input(AVFilterLink *inlink)
642 {
643  AVFilterContext *ctx = inlink->dst;
644  FIREqualizerContext *s = ctx->priv;
645  int rdft_bits;
646 
647  common_uninit(s);
648 
649  s->next_pts = 0;
650  s->frame_nsamples_max = 0;
651 
652  s->fir_len = FFMAX(2 * (int)(inlink->sample_rate * s->delay) + 1, 3);
653  s->remaining = s->fir_len - 1;
654 
655  for (rdft_bits = RDFT_BITS_MIN; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
656  s->rdft_len = 1 << rdft_bits;
657  s->nsamples_max = s->rdft_len - s->fir_len + 1;
658  if (s->nsamples_max * 2 >= s->fir_len)
659  break;
660  }
661 
662  if (rdft_bits > RDFT_BITS_MAX) {
663  av_log(ctx, AV_LOG_ERROR, "too large delay, please decrease it.\n");
664  return AVERROR(EINVAL);
665  }
666 
667  if (!(s->rdft = av_rdft_init(rdft_bits, DFT_R2C)) || !(s->irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
668  return AVERROR(ENOMEM);
669 
670  if (s->fft2 && !s->multi && inlink->channels > 1 && !(s->fft_ctx = av_fft_init(rdft_bits, 0)))
671  return AVERROR(ENOMEM);
672 
673  for ( ; rdft_bits <= RDFT_BITS_MAX; rdft_bits++) {
674  s->analysis_rdft_len = 1 << rdft_bits;
675  if (inlink->sample_rate <= s->accuracy * s->analysis_rdft_len)
676  break;
677  }
678 
679  if (rdft_bits > RDFT_BITS_MAX) {
680  av_log(ctx, AV_LOG_ERROR, "too small accuracy, please increase it.\n");
681  return AVERROR(EINVAL);
682  }
683 
684  if (!(s->analysis_irdft = av_rdft_init(rdft_bits, IDFT_C2R)))
685  return AVERROR(ENOMEM);
686 
687  if (s->dumpfile) {
688  s->analysis_rdft = av_rdft_init(rdft_bits, DFT_R2C);
689  s->dump_buf = av_malloc_array(s->analysis_rdft_len, sizeof(*s->dump_buf));
690  }
691 
693  s->kernel_tmp_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_tmp_buf));
694  s->kernel_buf = av_malloc_array(s->rdft_len * (s->multi ? inlink->channels : 1), sizeof(*s->kernel_buf));
695  s->conv_buf = av_calloc(2 * s->rdft_len * inlink->channels, sizeof(*s->conv_buf));
696  s->conv_idx = av_calloc(inlink->channels, sizeof(*s->conv_idx));
697  if (!s->analysis_buf || !s->kernel_tmp_buf || !s->kernel_buf || !s->conv_buf || !s->conv_idx)
698  return AVERROR(ENOMEM);
699 
700  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",
701  inlink->sample_rate, inlink->channels, s->analysis_rdft_len, s->rdft_len, s->fir_len, s->nsamples_max);
702 
703  if (s->fixed)
704  inlink->min_samples = inlink->max_samples = inlink->partial_buf_size = s->nsamples_max;
705 
706  return generate_kernel(ctx, SELECT_GAIN(s), SELECT_GAIN_ENTRY(s));
707 }
708 
709 static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
710 {
711  AVFilterContext *ctx = inlink->dst;
712  FIREqualizerContext *s = ctx->priv;
713  int ch;
714 
715  for (ch = 0; ch + 1 < inlink->channels && s->fft_ctx; ch += 2) {
716  fast_convolute2(s, s->kernel_buf, (FFTComplex *)(s->conv_buf + 2 * ch * s->rdft_len),
717  s->conv_idx + ch, (float *) frame->extended_data[ch],
718  (float *) frame->extended_data[ch+1], frame->nb_samples);
719  }
720 
721  for ( ; ch < inlink->channels; ch++) {
722  fast_convolute(s, s->kernel_buf + (s->multi ? ch * s->rdft_len : 0),
723  s->conv_buf + 2 * ch * s->rdft_len, s->conv_idx + ch,
724  (float *) frame->extended_data[ch], frame->nb_samples);
725  }
726 
728  if (frame->pts != AV_NOPTS_VALUE) {
729  s->next_pts = frame->pts + av_rescale_q(frame->nb_samples, av_make_q(1, inlink->sample_rate), inlink->time_base);
730  if (s->zero_phase)
731  frame->pts -= av_rescale_q(s->fir_len/2, av_make_q(1, inlink->sample_rate), inlink->time_base);
732  }
734  return ff_filter_frame(ctx->outputs[0], frame);
735 }
736 
737 static int request_frame(AVFilterLink *outlink)
738 {
739  AVFilterContext *ctx = outlink->src;
740  FIREqualizerContext *s= ctx->priv;
741  int ret;
742 
743  ret = ff_request_frame(ctx->inputs[0]);
744  if (ret == AVERROR_EOF && s->remaining > 0 && s->frame_nsamples_max > 0) {
746 
747  if (!frame)
748  return AVERROR(ENOMEM);
749 
750  av_samples_set_silence(frame->extended_data, 0, frame->nb_samples, outlink->channels, frame->format);
751  frame->pts = s->next_pts;
752  s->remaining -= frame->nb_samples;
753  ret = filter_frame(ctx->inputs[0], frame);
754  }
755 
756  return ret;
757 }
758 
759 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
760  char *res, int res_len, int flags)
761 {
762  FIREqualizerContext *s = ctx->priv;
763  int ret = AVERROR(ENOSYS);
764 
765  if (!strcmp(cmd, "gain")) {
766  char *gain_cmd;
767 
768  if (SELECT_GAIN(s) && !strcmp(SELECT_GAIN(s), args)) {
769  av_log(ctx, AV_LOG_DEBUG, "equal gain, do not rebuild.\n");
770  return 0;
771  }
772 
773  gain_cmd = av_strdup(args);
774  if (!gain_cmd)
775  return AVERROR(ENOMEM);
776 
777  ret = generate_kernel(ctx, gain_cmd, SELECT_GAIN_ENTRY(s));
778  if (ret >= 0) {
779  av_freep(&s->gain_cmd);
780  s->gain_cmd = gain_cmd;
781  } else {
782  av_freep(&gain_cmd);
783  }
784  } else if (!strcmp(cmd, "gain_entry")) {
785  char *gain_entry_cmd;
786 
787  if (SELECT_GAIN_ENTRY(s) && !strcmp(SELECT_GAIN_ENTRY(s), args)) {
788  av_log(ctx, AV_LOG_DEBUG, "equal gain_entry, do not rebuild.\n");
789  return 0;
790  }
791 
792  gain_entry_cmd = av_strdup(args);
793  if (!gain_entry_cmd)
794  return AVERROR(ENOMEM);
795 
796  ret = generate_kernel(ctx, SELECT_GAIN(s), gain_entry_cmd);
797  if (ret >= 0) {
799  s->gain_entry_cmd = gain_entry_cmd;
800  } else {
801  av_freep(&gain_entry_cmd);
802  }
803  }
804 
805  return ret;
806 }
807 
809  {
810  .name = "default",
811  .config_props = config_input,
812  .filter_frame = filter_frame,
813  .type = AVMEDIA_TYPE_AUDIO,
814  .needs_writable = 1,
815  },
816  { NULL }
817 };
818 
820  {
821  .name = "default",
822  .request_frame = request_frame,
823  .type = AVMEDIA_TYPE_AUDIO,
824  },
825  { NULL }
826 };
827 
829  .name = "firequalizer",
830  .description = NULL_IF_CONFIG_SMALL("Finite Impulse Response Equalizer."),
831  .uninit = uninit,
832  .query_formats = query_formats,
833  .process_command = process_command,
834  .priv_size = sizeof(FIREqualizerContext),
835  .inputs = firequalizer_inputs,
836  .outputs = firequalizer_outputs,
837  .priv_class = &firequalizer_class,
838 };
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:549
const char * s
Definition: avisynth_c.h:768
#define isinf(x)
Definition: libm.h:317
This structure describes decoded (raw) audio or video data.
Definition: frame.h:187
AVOption.
Definition: opt.h:246
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
av_cold void av_fft_end(FFTContext *s)
Definition: avfft.c:48
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 double gain_interpolate_func(void *p, double freq)
const char * b
Definition: vf_curves.c:113
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)
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:661
#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:230
#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:331
#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:1125
RDFTContext * irdft
#define av_cold
Definition: attributes.h:82
AVOptions.
static double cubic_interpolate_func(void *p, double freq)
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:271
#define RDFT_BITS_MAX
Definition: eval.c:150
static AVFrame * frame
static const char *const var_names[]
static int flags
Definition: log.c:57
#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:726
#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:568
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 AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:179
AVFILTER_DEFINE_CLASS(firequalizer)
void * priv
private data for use by the filter
Definition: avfilter.h:338
#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
#define FFMAX(a, b)
Definition: common.h:94
RDFTContext * analysis_irdft
static av_cold void uninit(AVFilterContext *ctx)
static const AVOption firequalizer_options[]
void av_rdft_calc(RDFTContext *s, FFTSample *data)
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
AVFormatContext * ctx
Definition: movenc.c:48
#define FLAGS
const char * gain_entry
Definition: avfft.h:72
void av_rdft_end(RDFTContext *s)
RDFTContext * av_rdft_init(int nbits, enum RDFTransformType trans)
Set up a real FFT.
static const AVFilterPad outputs[]
Definition: af_afftfilt.c:386
OverlapIndex * conv_idx
A list of supported channel layouts.
Definition: formats.h:85
static double entry_func(void *p, double freq, double gain)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:251
static const uint8_t vars[2][12]
Definition: camellia.c:179
static const AVFilterPad inputs[]
Definition: af_afftfilt.c:376
#define OFFSET(x)
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:237
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:320
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:690
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
GainEntry gain_entry_tbl[NB_GAIN_ENTRY_MAX]
const char * name
Filter name.
Definition: avfilter.h:148
#define u(width,...)
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:335
enum MovChannelLayoutTag * layouts
Definition: mov_chan.c:434
AVFilterFormats * ff_all_samplerates(void)
Definition: formats.c:395
static void dump_fir(AVFilterContext *ctx, FILE *fp, int ch)
FFTSample im
Definition: avfft.h:38
if(ret< 0)
Definition: vf_mcdeint.c:282
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 double c[64]
static int query_formats(AVFilterContext *ctx)
static int generate_kernel(AVFilterContext *ctx, const char *gain, const char *gain_entry)
uint8_t pi<< 24) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_U8,(uint64_t)((*(constuint8_t *) pi-0x80U))<< 56) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8,(*(constuint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16,(*(constint16_t *) pi >>8)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S16,(uint64_t)(*(constint16_t *) pi)<< 48) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16,*(constint16_t *) pi *(1.0/(1<< 15))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32,(*(constint32_t *) pi >>24)+0x80) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_S32,(uint64_t)(*(constint32_t *) pi)<< 32) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32,*(constint32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S64,(*(constint64_t *) pi >>56)+0x80) CONV_FUNC(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0f/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S64,*(constint64_t *) pi *(1.0/(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, av_clip_uint8(lrintf(*(constfloat *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, av_clip_int16(lrintf(*(constfloat *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, av_clipl_int32(llrintf(*(constfloat *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_FLT, llrintf(*(constfloat *) pi *(INT64_C(1)<< 63))) CONV_FUNC(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, av_clip_uint8(lrint(*(constdouble *) pi *(1<< 7))+0x80)) CONV_FUNC(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, av_clip_int16(lrint(*(constdouble *) pi *(1<< 15)))) CONV_FUNC(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, av_clipl_int32(llrint(*(constdouble *) pi *(1U<< 31)))) CONV_FUNC(AV_SAMPLE_FMT_S64, int64_t, AV_SAMPLE_FMT_DBL, llrint(*(constdouble *) pi *(INT64_C(1)<< 63)))#defineFMT_PAIR_FUNC(out, in) staticconv_func_type *constfmt_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),};staticvoidcpy1(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, len);}staticvoidcpy2(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 2 *len);}staticvoidcpy4(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 4 *len);}staticvoidcpy8(uint8_t **dst, constuint8_t **src, intlen){memcpy(*dst,*src, 8 *len);}AudioConvert *swri_audio_convert_alloc(enumAVSampleFormatout_fmt, enumAVSampleFormatin_fmt, intchannels, constint *ch_map, intflags){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) returnNULL;ctx=av_mallocz(sizeof(*ctx));if(!ctx) returnNULL;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)){case1:ctx->simd_f=cpy1;break;case2:ctx->simd_f=cpy2;break;case4:ctx->simd_f=cpy4;break;case8:ctx->simd_f=cpy8;break;}}if(HAVE_YASM &&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);returnctx;}voidswri_audio_convert_free(AudioConvert **ctx){av_freep(ctx);}intswri_audio_convert(AudioConvert *ctx, AudioData *out, AudioData *in, intlen){intch;intoff=0;constintos=(out->planar?1:out->ch_count)*out->bps;unsignedmisaligned=0;av_assert0(ctx->channels==out->ch_count);if(ctx->in_simd_align_mask){intplanes=in->planar?in->ch_count:1;unsignedm=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){intplanes=out->planar?out->ch_count:1;unsignedm=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){intplanes=out->planar?out->ch_count:1;for(ch=0;ch< planes;ch++){ctx->simd_f(out-> ch ch
Definition: audioconvert.c:56
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:716
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:323
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:405
formats
Definition: signature.h:48
internal API functions
AVFilterChannelLayouts * ff_all_channel_counts(void)
Construct an AVFilterChannelLayouts coding for any channel layout, with known or unknown disposition...
Definition: formats.c:410
uint8_t ** extended_data
pointers to the data planes/channels.
Definition: frame.h:234
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:244
int ff_set_common_samplerates(AVFilterContext *ctx, AVFilterFormats *samplerates)
Definition: formats.c:556
#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