]> git.sesse.net Git - ffmpeg/blob - libavfilter/af_biquads.c
avfilter/af_biquads: add new normalize/n option
[ffmpeg] / libavfilter / af_biquads.c
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/avassert.h"
66 #include "libavutil/ffmath.h"
67 #include "libavutil/opt.h"
68 #include "audio.h"
69 #include "avfilter.h"
70 #include "internal.h"
71
72 enum FilterType {
73     biquad,
74     equalizer,
75     bass,
76     treble,
77     bandpass,
78     bandreject,
79     allpass,
80     highpass,
81     lowpass,
82     lowshelf,
83     highshelf,
84 };
85
86 enum WidthType {
87     NONE,
88     HERTZ,
89     OCTAVE,
90     QFACTOR,
91     SLOPE,
92     KHERTZ,
93     NB_WTYPE,
94 };
95
96 typedef struct ChanCache {
97     double i1, i2;
98     double o1, o2;
99     int clippings;
100 } ChanCache;
101
102 typedef struct BiquadsContext {
103     const AVClass *class;
104
105     enum FilterType filter_type;
106     int width_type;
107     int poles;
108     int csg;
109
110     double gain;
111     double frequency;
112     double width;
113     double mix;
114     uint64_t channels;
115     int normalize;
116
117     double a0, a1, a2;
118     double b0, b1, b2;
119
120     ChanCache *cache;
121     int block_align;
122
123     void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,
124                    double *i1, double *i2, double *o1, double *o2,
125                    double b0, double b1, double b2, double a1, double a2, int *clippings,
126                    int disabled);
127 } BiquadsContext;
128
129 static av_cold int init(AVFilterContext *ctx)
130 {
131     BiquadsContext *s = ctx->priv;
132
133     if (s->filter_type != biquad) {
134         if (s->frequency <= 0 || s->width <= 0) {
135             av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
136                    s->frequency, s->width);
137             return AVERROR(EINVAL);
138         }
139     }
140
141     return 0;
142 }
143
144 static int query_formats(AVFilterContext *ctx)
145 {
146     AVFilterFormats *formats;
147     AVFilterChannelLayouts *layouts;
148     static const enum AVSampleFormat sample_fmts[] = {
149         AV_SAMPLE_FMT_S16P,
150         AV_SAMPLE_FMT_S32P,
151         AV_SAMPLE_FMT_FLTP,
152         AV_SAMPLE_FMT_DBLP,
153         AV_SAMPLE_FMT_NONE
154     };
155     int ret;
156
157     layouts = ff_all_channel_counts();
158     if (!layouts)
159         return AVERROR(ENOMEM);
160     ret = ff_set_common_channel_layouts(ctx, layouts);
161     if (ret < 0)
162         return ret;
163
164     formats = ff_make_format_list(sample_fmts);
165     if (!formats)
166         return AVERROR(ENOMEM);
167     ret = ff_set_common_formats(ctx, formats);
168     if (ret < 0)
169         return ret;
170
171     formats = ff_all_samplerates();
172     if (!formats)
173         return AVERROR(ENOMEM);
174     return ff_set_common_samplerates(ctx, formats);
175 }
176
177 #define BIQUAD_FILTER(name, type, min, max, need_clipping)                    \
178 static void biquad_## name (BiquadsContext *s,                                \
179                             const void *input, void *output, int len,         \
180                             double *in1, double *in2,                         \
181                             double *out1, double *out2,                       \
182                             double b0, double b1, double b2,                  \
183                             double a1, double a2, int *clippings,             \
184                             int disabled)                                     \
185 {                                                                             \
186     const type *ibuf = input;                                                 \
187     type *obuf = output;                                                      \
188     double i1 = *in1;                                                         \
189     double i2 = *in2;                                                         \
190     double o1 = *out1;                                                        \
191     double o2 = *out2;                                                        \
192     double wet = s->mix;                                                      \
193     double dry = 1. - wet;                                                    \
194     double out;                                                               \
195     int i;                                                                    \
196     a1 = -a1;                                                                 \
197     a2 = -a2;                                                                 \
198                                                                               \
199     for (i = 0; i+1 < len; i++) {                                             \
200         o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1;            \
201         i2 = ibuf[i];                                                         \
202         out = o2 * wet + i2 * dry;                                            \
203         if (disabled) {                                                       \
204             obuf[i] = i2;                                                     \
205         } else if (need_clipping && out < min) {                              \
206             (*clippings)++;                                                   \
207             obuf[i] = min;                                                    \
208         } else if (need_clipping && out > max) {                              \
209             (*clippings)++;                                                   \
210             obuf[i] = max;                                                    \
211         } else {                                                              \
212             obuf[i] = out;                                                    \
213         }                                                                     \
214         i++;                                                                  \
215         o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1;            \
216         i1 = ibuf[i];                                                         \
217         out = o1 * wet + i1 * dry;                                            \
218         if (disabled) {                                                       \
219             obuf[i] = i1;                                                     \
220         } else if (need_clipping && out < min) {                              \
221             (*clippings)++;                                                   \
222             obuf[i] = min;                                                    \
223         } else if (need_clipping && out > max) {                              \
224             (*clippings)++;                                                   \
225             obuf[i] = max;                                                    \
226         } else {                                                              \
227             obuf[i] = out;                                                    \
228         }                                                                     \
229     }                                                                         \
230     if (i < len) {                                                            \
231         double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2;     \
232         i2 = i1;                                                              \
233         i1 = ibuf[i];                                                         \
234         o2 = o1;                                                              \
235         o1 = o0;                                                              \
236         out = o0 * wet + i1 * dry;                                            \
237         if (disabled) {                                                       \
238             obuf[i] = i1;                                                     \
239         } else if (need_clipping && out < min) {                              \
240             (*clippings)++;                                                   \
241             obuf[i] = min;                                                    \
242         } else if (need_clipping && out > max) {                              \
243             (*clippings)++;                                                   \
244             obuf[i] = max;                                                    \
245         } else {                                                              \
246             obuf[i] = out;                                                    \
247         }                                                                     \
248     }                                                                         \
249     *in1  = i1;                                                               \
250     *in2  = i2;                                                               \
251     *out1 = o1;                                                               \
252     *out2 = o2;                                                               \
253 }
254
255 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
256 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
257 BIQUAD_FILTER(flt, float,   -1., 1., 0)
258 BIQUAD_FILTER(dbl, double,  -1., 1., 0)
259
260 static int config_filter(AVFilterLink *outlink, int reset)
261 {
262     AVFilterContext *ctx    = outlink->src;
263     BiquadsContext *s       = ctx->priv;
264     AVFilterLink *inlink    = ctx->inputs[0];
265     double A = ff_exp10(s->gain / 40);
266     double w0 = 2 * M_PI * s->frequency / inlink->sample_rate;
267     double alpha, beta;
268
269     if (w0 > M_PI) {
270         av_log(ctx, AV_LOG_ERROR,
271                "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
272                s->frequency, inlink->sample_rate);
273         return AVERROR(EINVAL);
274     }
275
276     switch (s->width_type) {
277     case NONE:
278         alpha = 0.0;
279         break;
280     case HERTZ:
281         alpha = sin(w0) / (2 * s->frequency / s->width);
282         break;
283     case KHERTZ:
284         alpha = sin(w0) / (2 * s->frequency / (s->width * 1000));
285         break;
286     case OCTAVE:
287         alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0));
288         break;
289     case QFACTOR:
290         alpha = sin(w0) / (2 * s->width);
291         break;
292     case SLOPE:
293         alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2);
294         break;
295     default:
296         av_assert0(0);
297     }
298
299     beta = 2 * sqrt(A);
300
301     switch (s->filter_type) {
302     case biquad:
303         break;
304     case equalizer:
305         s->a0 =   1 + alpha / A;
306         s->a1 =  -2 * cos(w0);
307         s->a2 =   1 - alpha / A;
308         s->b0 =   1 + alpha * A;
309         s->b1 =  -2 * cos(w0);
310         s->b2 =   1 - alpha * A;
311         break;
312     case bass:
313         beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
314     case lowshelf:
315         s->a0 =          (A + 1) + (A - 1) * cos(w0) + beta * alpha;
316         s->a1 =    -2 * ((A - 1) + (A + 1) * cos(w0));
317         s->a2 =          (A + 1) + (A - 1) * cos(w0) - beta * alpha;
318         s->b0 =     A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
319         s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
320         s->b2 =     A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
321         break;
322     case treble:
323         beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
324     case highshelf:
325         s->a0 =          (A + 1) - (A - 1) * cos(w0) + beta * alpha;
326         s->a1 =     2 * ((A - 1) - (A + 1) * cos(w0));
327         s->a2 =          (A + 1) - (A - 1) * cos(w0) - beta * alpha;
328         s->b0 =     A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
329         s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
330         s->b2 =     A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
331         break;
332     case bandpass:
333         if (s->csg) {
334             s->a0 =  1 + alpha;
335             s->a1 = -2 * cos(w0);
336             s->a2 =  1 - alpha;
337             s->b0 =  sin(w0) / 2;
338             s->b1 =  0;
339             s->b2 = -sin(w0) / 2;
340         } else {
341             s->a0 =  1 + alpha;
342             s->a1 = -2 * cos(w0);
343             s->a2 =  1 - alpha;
344             s->b0 =  alpha;
345             s->b1 =  0;
346             s->b2 = -alpha;
347         }
348         break;
349     case bandreject:
350         s->a0 =  1 + alpha;
351         s->a1 = -2 * cos(w0);
352         s->a2 =  1 - alpha;
353         s->b0 =  1;
354         s->b1 = -2 * cos(w0);
355         s->b2 =  1;
356         break;
357     case lowpass:
358         if (s->poles == 1) {
359             s->a0 = 1;
360             s->a1 = -exp(-w0);
361             s->a2 = 0;
362             s->b0 = 1 + s->a1;
363             s->b1 = 0;
364             s->b2 = 0;
365         } else {
366             s->a0 =  1 + alpha;
367             s->a1 = -2 * cos(w0);
368             s->a2 =  1 - alpha;
369             s->b0 = (1 - cos(w0)) / 2;
370             s->b1 =  1 - cos(w0);
371             s->b2 = (1 - cos(w0)) / 2;
372         }
373         break;
374     case highpass:
375         if (s->poles == 1) {
376             s->a0 = 1;
377             s->a1 = -exp(-w0);
378             s->a2 = 0;
379             s->b0 = (1 - s->a1) / 2;
380             s->b1 = -s->b0;
381             s->b2 = 0;
382         } else {
383             s->a0 =   1 + alpha;
384             s->a1 =  -2 * cos(w0);
385             s->a2 =   1 - alpha;
386             s->b0 =  (1 + cos(w0)) / 2;
387             s->b1 = -(1 + cos(w0));
388             s->b2 =  (1 + cos(w0)) / 2;
389         }
390         break;
391     case allpass:
392         s->a0 =  1 + alpha;
393         s->a1 = -2 * cos(w0);
394         s->a2 =  1 - alpha;
395         s->b0 =  1 - alpha;
396         s->b1 = -2 * cos(w0);
397         s->b2 =  1 + alpha;
398         break;
399     default:
400         av_assert0(0);
401     }
402
403     av_log(ctx, AV_LOG_VERBOSE, "a=%f %f %f:b=%f %f %f\n", s->a0, s->a1, s->a2, s->b0, s->b1, s->b2);
404
405     s->a1 /= s->a0;
406     s->a2 /= s->a0;
407     s->b0 /= s->a0;
408     s->b1 /= s->a0;
409     s->b2 /= s->a0;
410     s->a0 /= s->a0;
411
412     if (s->normalize && fabs(s->b0 + s->b1 + s->b2) > 1e-6) {
413         double factor = (s->a0 + s->a1 + s->a2) / (s->b0 + s->b1 + s->b2);
414
415         s->b0 *= factor;
416         s->b1 *= factor;
417         s->b2 *= factor;
418     }
419
420     s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels);
421     if (!s->cache)
422         return AVERROR(ENOMEM);
423     if (reset)
424         memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
425
426     switch (inlink->format) {
427     case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
428     case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
429     case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
430     case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
431     default: av_assert0(0);
432     }
433
434     s->block_align = av_get_bytes_per_sample(inlink->format);
435
436     return 0;
437 }
438
439 static int config_output(AVFilterLink *outlink)
440 {
441     return config_filter(outlink, 1);
442 }
443
444 typedef struct ThreadData {
445     AVFrame *in, *out;
446 } ThreadData;
447
448 static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
449 {
450     AVFilterLink *inlink = ctx->inputs[0];
451     ThreadData *td = arg;
452     AVFrame *buf = td->in;
453     AVFrame *out_buf = td->out;
454     BiquadsContext *s = ctx->priv;
455     const int start = (buf->channels * jobnr) / nb_jobs;
456     const int end = (buf->channels * (jobnr+1)) / nb_jobs;
457     int ch;
458
459     for (ch = start; ch < end; ch++) {
460         if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) {
461             if (buf != out_buf)
462                 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
463                        buf->nb_samples * s->block_align);
464             continue;
465         }
466
467         s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
468                   &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
469                   s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
470     }
471
472     return 0;
473 }
474
475 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
476 {
477     AVFilterContext  *ctx = inlink->dst;
478     BiquadsContext *s     = ctx->priv;
479     AVFilterLink *outlink = ctx->outputs[0];
480     AVFrame *out_buf;
481     ThreadData td;
482     int ch;
483
484     if (av_frame_is_writable(buf)) {
485         out_buf = buf;
486     } else {
487         out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);
488         if (!out_buf) {
489             av_frame_free(&buf);
490             return AVERROR(ENOMEM);
491         }
492         av_frame_copy_props(out_buf, buf);
493     }
494
495     td.in = buf;
496     td.out = out_buf;
497     ctx->internal->execute(ctx, filter_channel, &td, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx)));
498
499     for (ch = 0; ch < outlink->channels; ch++) {
500         if (s->cache[ch].clippings > 0)
501             av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n",
502                    ch, s->cache[ch].clippings);
503         s->cache[ch].clippings = 0;
504     }
505
506     if (buf != out_buf)
507         av_frame_free(&buf);
508
509     return ff_filter_frame(outlink, out_buf);
510 }
511
512 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
513                            char *res, int res_len, int flags)
514 {
515     AVFilterLink *outlink = ctx->outputs[0];
516     int ret;
517
518     ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
519     if (ret < 0)
520         return ret;
521
522     return config_filter(outlink, 0);
523 }
524
525 static av_cold void uninit(AVFilterContext *ctx)
526 {
527     BiquadsContext *s = ctx->priv;
528
529     av_freep(&s->cache);
530 }
531
532 static const AVFilterPad inputs[] = {
533     {
534         .name         = "default",
535         .type         = AVMEDIA_TYPE_AUDIO,
536         .filter_frame = filter_frame,
537     },
538     { NULL }
539 };
540
541 static const AVFilterPad outputs[] = {
542     {
543         .name         = "default",
544         .type         = AVMEDIA_TYPE_AUDIO,
545         .config_props = config_output,
546     },
547     { NULL }
548 };
549
550 #define OFFSET(x) offsetof(BiquadsContext, x)
551 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
552 #define AF AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
553
554 #define DEFINE_BIQUAD_FILTER(name_, description_)                       \
555 AVFILTER_DEFINE_CLASS(name_);                                           \
556 static av_cold int name_##_init(AVFilterContext *ctx) \
557 {                                                                       \
558     BiquadsContext *s = ctx->priv;                                      \
559     s->class = &name_##_class;                                          \
560     s->filter_type = name_;                                             \
561     return init(ctx);                                             \
562 }                                                                       \
563                                                          \
564 AVFilter ff_af_##name_ = {                         \
565     .name          = #name_,                             \
566     .description   = NULL_IF_CONFIG_SMALL(description_), \
567     .priv_size     = sizeof(BiquadsContext),             \
568     .init          = name_##_init,                       \
569     .uninit        = uninit,                             \
570     .query_formats = query_formats,                      \
571     .inputs        = inputs,                             \
572     .outputs       = outputs,                            \
573     .priv_class    = &name_##_class,                     \
574     .process_command = process_command,                  \
575     .flags         = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, \
576 }
577
578 #if CONFIG_EQUALIZER_FILTER
579 static const AVOption equalizer_options[] = {
580     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
581     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
582     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
583     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
584     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
585     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
586     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
587     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
588     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
589     {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
590     {"w",     "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
591     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
592     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
593     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
594     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
595     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
596     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
597     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
598     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
599     {NULL}
600 };
601
602 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
603 #endif  /* CONFIG_EQUALIZER_FILTER */
604 #if CONFIG_BASS_FILTER
605 static const AVOption bass_options[] = {
606     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
607     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
608     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
609     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
610     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
611     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
612     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
613     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
614     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
615     {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
616     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
617     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
618     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
619     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
620     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
621     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
622     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
623     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
624     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
625     {NULL}
626 };
627
628 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
629 #endif  /* CONFIG_BASS_FILTER */
630 #if CONFIG_TREBLE_FILTER
631 static const AVOption treble_options[] = {
632     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
633     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
634     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
635     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
636     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
637     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
638     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
639     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
640     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
641     {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
642     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
643     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
644     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
645     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
646     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
647     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
648     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
649     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
650     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
651     {NULL}
652 };
653
654 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
655 #endif  /* CONFIG_TREBLE_FILTER */
656 #if CONFIG_BANDPASS_FILTER
657 static const AVOption bandpass_options[] = {
658     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
659     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
660     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
661     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
662     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
663     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
664     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
665     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
666     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
667     {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
668     {"w",     "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
669     {"csg",   "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
670     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
671     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
672     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
673     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
674     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
675     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
676     {NULL}
677 };
678
679 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
680 #endif  /* CONFIG_BANDPASS_FILTER */
681 #if CONFIG_BANDREJECT_FILTER
682 static const AVOption bandreject_options[] = {
683     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
684     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
685     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
686     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
687     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
688     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
689     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
690     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
691     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
692     {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
693     {"w",     "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
694     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
695     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
696     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
697     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
698     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
699     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
700     {NULL}
701 };
702
703 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
704 #endif  /* CONFIG_BANDREJECT_FILTER */
705 #if CONFIG_LOWPASS_FILTER
706 static const AVOption lowpass_options[] = {
707     {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
708     {"f",         "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
709     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
710     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
711     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
712     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
713     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
714     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
715     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
716     {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
717     {"w",     "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
718     {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
719     {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
720     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
721     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
722     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
723     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
724     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
725     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
726     {NULL}
727 };
728
729 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
730 #endif  /* CONFIG_LOWPASS_FILTER */
731 #if CONFIG_HIGHPASS_FILTER
732 static const AVOption highpass_options[] = {
733     {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
734     {"f",         "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
735     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
736     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
737     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
738     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
739     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
740     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
741     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
742     {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
743     {"w",     "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
744     {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
745     {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
746     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
747     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
748     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
749     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
750     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
751     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
752     {NULL}
753 };
754
755 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
756 #endif  /* CONFIG_HIGHPASS_FILTER */
757 #if CONFIG_ALLPASS_FILTER
758 static const AVOption allpass_options[] = {
759     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
760     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
761     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
762     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
763     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
764     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
765     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
766     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
767     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
768     {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
769     {"w",     "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
770     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
771     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
772     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
773     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
774     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
775     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
776     {NULL}
777 };
778
779 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
780 #endif  /* CONFIG_ALLPASS_FILTER */
781 #if CONFIG_LOWSHELF_FILTER
782 static const AVOption lowshelf_options[] = {
783     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
784     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
785     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
786     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
787     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
788     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
789     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
790     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
791     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
792     {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
793     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
794     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
795     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
796     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
797     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
798     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
799     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
800     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
801     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
802     {NULL}
803 };
804
805 DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter.");
806 #endif  /* CONFIG_LOWSHELF_FILTER */
807 #if CONFIG_HIGHSHELF_FILTER
808 static const AVOption highshelf_options[] = {
809     {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
810     {"f",         "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
811     {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
812     {"t",          "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
813     {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
814     {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
815     {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
816     {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
817     {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
818     {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
819     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
820     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
821     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
822     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
823     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
824     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
825     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
826     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
827     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
828     {NULL}
829 };
830
831 DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter.");
832 #endif  /* CONFIG_HIGHSHELF_FILTER */
833 #if CONFIG_BIQUAD_FILTER
834 static const AVOption biquad_options[] = {
835     {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS},
836     {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
837     {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
838     {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
839     {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
840     {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
841     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
842     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
843     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
844     {"c",        "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
845     {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
846     {"n",         "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
847     {NULL}
848 };
849
850 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
851 #endif  /* CONFIG_BIQUAD_FILTER */