FFmpeg
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
af_biquads.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Paul B Mahol
3  * Copyright (c) 2006-2008 Rob Sykes <robs@users.sourceforge.net>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 /*
23  * 2-pole filters designed by Robert Bristow-Johnson <rbj@audioimagination.com>
24  * see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
25  *
26  * 1-pole filters based on code (c) 2000 Chris Bagwell <cbagwell@sprynet.com>
27  * Algorithms: Recursive single pole low/high pass filter
28  * Reference: The Scientist and Engineer's Guide to Digital Signal Processing
29  *
30  * low-pass: output[N] = input[N] * A + output[N-1] * B
31  * X = exp(-2.0 * pi * Fc)
32  * A = 1 - X
33  * B = X
34  * Fc = cutoff freq / sample rate
35  *
36  * Mimics an RC low-pass filter:
37  *
38  * ---/\/\/\/\----------->
39  * |
40  * --- C
41  * ---
42  * |
43  * |
44  * V
45  *
46  * high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1]
47  * X = exp(-2.0 * pi * Fc)
48  * A0 = (1 + X) / 2
49  * A1 = -(1 + X) / 2
50  * B1 = X
51  * Fc = cutoff freq / sample rate
52  *
53  * Mimics an RC high-pass filter:
54  *
55  * || C
56  * ----||--------->
57  * || |
58  * <
59  * > R
60  * <
61  * |
62  * V
63  */
64 
65 #include "libavutil/opt.h"
66 #include "libavutil/avassert.h"
67 #include "audio.h"
68 #include "avfilter.h"
69 #include "internal.h"
70 
71 enum FilterType {
82 };
83 
84 enum WidthType {
86  HZ,
90 };
91 
92 typedef struct ChanCache {
93  double i1, i2;
94  double o1, o2;
95 } ChanCache;
96 
97 typedef struct {
98  const AVClass *class;
99 
102  int poles;
103  int csg;
104 
105  double gain;
106  double frequency;
107  double width;
108 
109  double a0, a1, a2;
110  double b0, b1, b2;
111 
113 
114  void (*filter)(const void *ibuf, void *obuf, int len,
115  double *i1, double *i2, double *o1, double *o2,
116  double b0, double b1, double b2, double a1, double a2);
118 
119 static av_cold int init(AVFilterContext *ctx, const char *args)
120 {
121  BiquadsContext *p = ctx->priv;
122  int ret;
123 
125 
126  if ((ret = av_set_options_string(p, args, "=", ":")) < 0)
127  return ret;
128 
129  if (p->filter_type != biquad) {
130  if (p->frequency <= 0 || p->width <= 0) {
131  av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
132  p->frequency, p->width);
133  return AVERROR(EINVAL);
134  }
135  }
136 
137  return 0;
138 }
139 
141 {
144  static const enum AVSampleFormat sample_fmts[] = {
150  };
151 
152  layouts = ff_all_channel_layouts();
153  if (!layouts)
154  return AVERROR(ENOMEM);
155  ff_set_common_channel_layouts(ctx, layouts);
156 
157  formats = ff_make_format_list(sample_fmts);
158  if (!formats)
159  return AVERROR(ENOMEM);
160  ff_set_common_formats(ctx, formats);
161 
162  formats = ff_all_samplerates();
163  if (!formats)
164  return AVERROR(ENOMEM);
165  ff_set_common_samplerates(ctx, formats);
166 
167  return 0;
168 }
169 
170 #define BIQUAD_FILTER(name, type, min, max) \
171 static void biquad_## name (const void *input, void *output, int len, \
172  double *in1, double *in2, \
173  double *out1, double *out2, \
174  double b0, double b1, double b2, \
175  double a1, double a2) \
176 { \
177  const type *ibuf = input; \
178  type *obuf = output; \
179  double i1 = *in1; \
180  double i2 = *in2; \
181  double o1 = *out1; \
182  double o2 = *out2; \
183  int i; \
184  a1 = -a1; \
185  a2 = -a2; \
186  \
187  for (i = 0; i+1 < len; i++) { \
188  o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \
189  i2 = ibuf[i]; \
190  if (o2 < min) { \
191  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
192  obuf[i] = min; \
193  } else if (o2 > max) { \
194  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
195  obuf[i] = max; \
196  } else { \
197  obuf[i] = o2; \
198  } \
199  i++; \
200  o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \
201  i1 = ibuf[i]; \
202  if (o1 < min) { \
203  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
204  obuf[i] = min; \
205  } else if (o1 > max) { \
206  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
207  obuf[i] = max; \
208  } else { \
209  obuf[i] = o1; \
210  } \
211  } \
212  if (i < len) { \
213  double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \
214  i2 = i1; \
215  i1 = ibuf[i]; \
216  o2 = o1; \
217  o1 = o0; \
218  if (o0 < min) { \
219  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
220  obuf[i] = min; \
221  } else if (o0 > max) { \
222  av_log(NULL, AV_LOG_WARNING, "clipping\n"); \
223  obuf[i] = max; \
224  } else { \
225  obuf[i] = o0; \
226  } \
227  } \
228  *in1 = i1; \
229  *in2 = i2; \
230  *out1 = o1; \
231  *out2 = o2; \
232 }
233 
234 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX)
235 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX)
236 BIQUAD_FILTER(flt, float, -1., 1.)
237 BIQUAD_FILTER(dbl, double, -1., 1.)
238 
239 static int config_output(AVFilterLink *outlink)
240 {
241  AVFilterContext *ctx = outlink->src;
242  BiquadsContext *p = ctx->priv;
243  AVFilterLink *inlink = ctx->inputs[0];
244  double A = exp(p->gain / 40 * log(10.));
245  double w0 = 2 * M_PI * p->frequency / inlink->sample_rate;
246  double alpha;
247 
248  if (w0 > M_PI) {
249  av_log(ctx, AV_LOG_ERROR,
250  "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
251  p->frequency, inlink->sample_rate);
252  return AVERROR(EINVAL);
253  }
254 
255  switch (p->width_type) {
256  case NONE:
257  alpha = 0.0;
258  break;
259  case HZ:
260  alpha = sin(w0) / (2 * p->frequency / p->width);
261  break;
262  case OCTAVE:
263  alpha = sin(w0) * sinh(log(2.) / 2 * p->width * w0 / sin(w0));
264  break;
265  case QFACTOR:
266  alpha = sin(w0) / (2 * p->width);
267  break;
268  case SLOPE:
269  alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / p->width - 1) + 2);
270  break;
271  default:
272  av_assert0(0);
273  }
274 
275  switch (p->filter_type) {
276  case biquad:
277  break;
278  case equalizer:
279  p->a0 = 1 + alpha / A;
280  p->a1 = -2 * cos(w0);
281  p->a2 = 1 - alpha / A;
282  p->b0 = 1 + alpha * A;
283  p->b1 = -2 * cos(w0);
284  p->b2 = 1 - alpha * A;
285  break;
286  case bass:
287  p->a0 = (A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha;
288  p->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
289  p->a2 = (A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha;
290  p->b0 = A * ((A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha);
291  p->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
292  p->b2 = A * ((A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha);
293  break;
294  case treble:
295  p->a0 = (A + 1) - (A - 1) * cos(w0) + 2 * sqrt(A) * alpha;
296  p->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
297  p->a2 = (A + 1) - (A - 1) * cos(w0) - 2 * sqrt(A) * alpha;
298  p->b0 = A * ((A + 1) + (A - 1) * cos(w0) + 2 * sqrt(A) * alpha);
299  p->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
300  p->b2 = A * ((A + 1) + (A - 1) * cos(w0) - 2 * sqrt(A) * alpha);
301  break;
302  case bandpass:
303  if (p->csg) {
304  p->a0 = 1 + alpha;
305  p->a1 = -2 * cos(w0);
306  p->a2 = 1 - alpha;
307  p->b0 = sin(w0) / 2;
308  p->b1 = 0;
309  p->b2 = -sin(w0) / 2;
310  } else {
311  p->a0 = 1 + alpha;
312  p->a1 = -2 * cos(w0);
313  p->a2 = 1 - alpha;
314  p->b0 = alpha;
315  p->b1 = 0;
316  p->b2 = -alpha;
317  }
318  break;
319  case bandreject:
320  p->a0 = 1 + alpha;
321  p->a1 = -2 * cos(w0);
322  p->a2 = 1 - alpha;
323  p->b0 = 1;
324  p->b1 = -2 * cos(w0);
325  p->b2 = 1;
326  break;
327  case lowpass:
328  if (p->poles == 1) {
329  p->a0 = 1;
330  p->a1 = -exp(-w0);
331  p->a2 = 0;
332  p->b0 = 1 + p->a1;
333  p->b1 = 0;
334  p->b2 = 0;
335  } else {
336  p->a0 = 1 + alpha;
337  p->a1 = -2 * cos(w0);
338  p->a2 = 1 - alpha;
339  p->b0 = (1 - cos(w0)) / 2;
340  p->b1 = 1 - cos(w0);
341  p->b2 = (1 - cos(w0)) / 2;
342  }
343  break;
344  case highpass:
345  if (p->poles == 1) {
346  p->a0 = 1;
347  p->a1 = -exp(-w0);
348  p->a2 = 0;
349  p->b0 = (1 - p->a1) / 2;
350  p->b1 = -p->b0;
351  p->b2 = 0;
352  } else {
353  p->a0 = 1 + alpha;
354  p->a1 = -2 * cos(w0);
355  p->a2 = 1 - alpha;
356  p->b0 = (1 + cos(w0)) / 2;
357  p->b1 = -(1 + cos(w0));
358  p->b2 = (1 + cos(w0)) / 2;
359  }
360  break;
361  case allpass:
362  p->a0 = 1 + alpha;
363  p->a1 = -2 * cos(w0);
364  p->a2 = 1 - alpha;
365  p->b0 = 1 - alpha;
366  p->b1 = -2 * cos(w0);
367  p->b2 = 1 + alpha;
368  break;
369  default:
370  av_assert0(0);
371  }
372 
373  p->a1 /= p->a0;
374  p->a2 /= p->a0;
375  p->b0 /= p->a0;
376  p->b1 /= p->a0;
377  p->b2 /= p->a0;
378 
379  p->cache = av_realloc_f(p->cache, sizeof(ChanCache), inlink->channels);
380  if (!p->cache)
381  return AVERROR(ENOMEM);
382  memset(p->cache, 0, sizeof(ChanCache) * inlink->channels);
383 
384  switch (inlink->format) {
385  case AV_SAMPLE_FMT_S16P: p->filter = biquad_s16; break;
386  case AV_SAMPLE_FMT_S32P: p->filter = biquad_s32; break;
387  case AV_SAMPLE_FMT_FLTP: p->filter = biquad_flt; break;
388  case AV_SAMPLE_FMT_DBLP: p->filter = biquad_dbl; break;
389  default: av_assert0(0);
390  }
391 
392  return 0;
393 }
394 
395 static int filter_frame(AVFilterLink *inlink, AVFilterBufferRef *buf)
396 {
397  BiquadsContext *p = inlink->dst->priv;
398  AVFilterLink *outlink = inlink->dst->outputs[0];
399  AVFilterBufferRef *out_buf;
400  int nb_samples = buf->audio->nb_samples;
401  int ch;
402 
403  if (buf->perms & AV_PERM_WRITE) {
404  out_buf = buf;
405  } else {
406  out_buf = ff_get_audio_buffer(inlink, AV_PERM_WRITE, nb_samples);
407  if (!out_buf)
408  return AVERROR(ENOMEM);
409  out_buf->pts = buf->pts;
410  }
411 
412  for (ch = 0; ch < buf->audio->channels; ch++)
413  p->filter(buf->extended_data[ch],
414  out_buf->extended_data[ch], nb_samples,
415  &p->cache[ch].i1, &p->cache[ch].i2,
416  &p->cache[ch].o1, &p->cache[ch].o2,
417  p->b0, p->b1, p->b2, p->a1, p->a2);
418 
419  if (buf != out_buf)
421 
422  return ff_filter_frame(outlink, out_buf);
423 }
424 
425 static av_cold void uninit(AVFilterContext *ctx)
426 {
427  BiquadsContext *p = ctx->priv;
428 
429  av_freep(&p->cache);
430  av_opt_free(p);
431 }
432 
433 static const AVFilterPad inputs[] = {
434  {
435  .name = "default",
436  .type = AVMEDIA_TYPE_AUDIO,
437  .filter_frame = filter_frame,
438  },
439  { NULL }
440 };
441 
442 static const AVFilterPad outputs[] = {
443  {
444  .name = "default",
445  .type = AVMEDIA_TYPE_AUDIO,
446  .config_props = config_output,
447  },
448  { NULL }
449 };
450 
451 #define OFFSET(x) offsetof(BiquadsContext, x)
452 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
453 
454 #define DEFINE_BIQUAD_FILTER(name_, description_) \
455 AVFILTER_DEFINE_CLASS(name_); \
456 static av_cold int name_##_init(AVFilterContext *ctx, const char *args) \
457 { \
458  BiquadsContext *p = ctx->priv; \
459  p->class = &name_##_class; \
460  p->filter_type = name_; \
461  return init(ctx, args); \
462 } \
463  \
464 AVFilter avfilter_af_##name_ = { \
465  .name = #name_, \
466  .description = NULL_IF_CONFIG_SMALL(description_), \
467  .priv_size = sizeof(BiquadsContext), \
468  .init = name_##_init, \
469  .uninit = uninit, \
470  .query_formats = query_formats, \
471  .inputs = inputs, \
472  .outputs = outputs, \
473  .priv_class = &name_##_class, \
474 }
475 
476 #if CONFIG_EQUALIZER_FILTER
477 static const AVOption equalizer_options[] = {
478  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
479  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
480  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
481  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
482  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
483  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
484  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
485  {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS},
486  {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 999, FLAGS},
487  {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
488  {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
489  {NULL},
490 };
491 
492 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
493 #endif /* CONFIG_EQUALIZER_FILTER */
494 #if CONFIG_BASS_FILTER
495 static const AVOption bass_options[] = {
496  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
497  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
498  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
499  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
500  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
501  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
502  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
503  {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
504  {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
505  {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
506  {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
507  {NULL},
508 };
509 
510 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
511 #endif /* CONFIG_BASS_FILTER */
512 #if CONFIG_TREBLE_FILTER
513 static const AVOption treble_options[] = {
514  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
515  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
516  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
517  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
518  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
519  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
520  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
521  {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
522  {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
523  {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
524  {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
525  {NULL},
526 };
527 
528 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
529 #endif /* CONFIG_TREBLE_FILTER */
530 #if CONFIG_BANDPASS_FILTER
531 static const AVOption bandpass_options[] = {
532  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
533  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
534  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
535  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
536  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
537  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
538  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
539  {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
540  {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
541  {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS},
542  {NULL},
543 };
544 
545 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
546 #endif /* CONFIG_BANDPASS_FILTER */
547 #if CONFIG_BANDREJECT_FILTER
548 static const AVOption bandreject_options[] = {
549  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
550  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
551  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
552  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
553  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
554  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
555  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
556  {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
557  {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 999, FLAGS},
558  {NULL},
559 };
560 
561 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
562 #endif /* CONFIG_BANDREJECT_FILTER */
563 #if CONFIG_LOWPASS_FILTER
564 static const AVOption lowpass_options[] = {
565  {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
566  {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
567  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
568  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
569  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
570  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
571  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
572  {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
573  {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
574  {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
575  {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
576  {NULL},
577 };
578 
579 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
580 #endif /* CONFIG_LOWPASS_FILTER */
581 #if CONFIG_HIGHPASS_FILTER
582 static const AVOption highpass_options[] = {
583  {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
584  {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
585  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HZ, SLOPE, FLAGS, "width_type"},
586  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
587  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
588  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
589  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
590  {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
591  {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
592  {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
593  {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
594  {NULL},
595 };
596 
597 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
598 #endif /* CONFIG_HIGHPASS_FILTER */
599 #if CONFIG_ALLPASS_FILTER
600 static const AVOption allpass_options[] = {
601  {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
602  {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
603  {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HZ}, HZ, SLOPE, FLAGS, "width_type"},
604  {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HZ}, 0, 0, FLAGS, "width_type"},
605  {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
606  {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
607  {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
608  {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
609  {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
610  {NULL},
611 };
612 
613 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
614 #endif /* CONFIG_ALLPASS_FILTER */
615 #if CONFIG_BIQUAD_FILTER
616 static const AVOption biquad_options[] = {
617  {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
618  {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
619  {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
620  {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
621  {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
622  {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT16_MAX, INT16_MAX, FLAGS},
623  {NULL},
624 };
625 
626 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
627 #endif /* CONFIG_BIQUAD_FILTER */