2 * Copyright (c) 2013 Paul B Mahol
3 * Copyright (c) 2006-2008 Rob Sykes <robs@users.sourceforge.net>
5 * This file is part of FFmpeg.
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.
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.
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
23 * 2-pole filters designed by Robert Bristow-Johnson <rbj@audioimagination.com>
24 * see http://www.musicdsp.org/files/Audio-EQ-Cookbook.txt
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
30 * low-pass: output[N] = input[N] * A + output[N-1] * B
31 * X = exp(-2.0 * pi * Fc)
34 * Fc = cutoff freq / sample rate
36 * Mimics an RC low-pass filter:
38 * ---/\/\/\/\----------->
46 * high-pass: output[N] = A0 * input[N] + A1 * input[N-1] + B1 * output[N-1]
47 * X = exp(-2.0 * pi * Fc)
51 * Fc = cutoff freq / sample rate
53 * Mimics an RC high-pass filter:
65 #include "libavutil/avassert.h"
66 #include "libavutil/opt.h"
95 typedef struct ChanCache {
101 typedef struct BiquadsContext {
102 const AVClass *class;
104 enum FilterType filter_type;
120 void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,
121 double *i1, double *i2, double *o1, double *o2,
122 double b0, double b1, double b2, double a1, double a2, int *clippings);
125 static av_cold int init(AVFilterContext *ctx)
127 BiquadsContext *s = ctx->priv;
129 if (s->filter_type != biquad) {
130 if (s->frequency <= 0 || s->width <= 0) {
131 av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
132 s->frequency, s->width);
133 return AVERROR(EINVAL);
140 static int query_formats(AVFilterContext *ctx)
142 AVFilterFormats *formats;
143 AVFilterChannelLayouts *layouts;
144 static const enum AVSampleFormat sample_fmts[] = {
153 layouts = ff_all_channel_counts();
155 return AVERROR(ENOMEM);
156 ret = ff_set_common_channel_layouts(ctx, layouts);
160 formats = ff_make_format_list(sample_fmts);
162 return AVERROR(ENOMEM);
163 ret = ff_set_common_formats(ctx, formats);
167 formats = ff_all_samplerates();
169 return AVERROR(ENOMEM);
170 return ff_set_common_samplerates(ctx, formats);
173 #define BIQUAD_FILTER(name, type, min, max, need_clipping) \
174 static void biquad_## name (BiquadsContext *s, \
175 const void *input, void *output, int len, \
176 double *in1, double *in2, \
177 double *out1, double *out2, \
178 double b0, double b1, double b2, \
179 double a1, double a2, int *clippings) \
181 const type *ibuf = input; \
182 type *obuf = output; \
191 for (i = 0; i+1 < len; i++) { \
192 o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \
194 if (need_clipping && o2 < min) { \
197 } else if (need_clipping && o2 > max) { \
204 o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \
206 if (need_clipping && o1 < min) { \
209 } else if (need_clipping && o1 > max) { \
217 double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \
222 if (need_clipping && o0 < min) { \
225 } else if (need_clipping && o0 > max) { \
238 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
239 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
240 BIQUAD_FILTER(flt, float, -1., 1., 0)
241 BIQUAD_FILTER(dbl, double, -1., 1., 0)
243 static int config_filter(AVFilterLink *outlink, int reset)
245 AVFilterContext *ctx = outlink->src;
246 BiquadsContext *s = ctx->priv;
247 AVFilterLink *inlink = ctx->inputs[0];
248 double A = exp(s->gain / 40 * log(10.));
249 double w0 = 2 * M_PI * s->frequency / inlink->sample_rate;
253 av_log(ctx, AV_LOG_ERROR,
254 "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
255 s->frequency, inlink->sample_rate);
256 return AVERROR(EINVAL);
259 switch (s->width_type) {
264 alpha = sin(w0) / (2 * s->frequency / s->width);
267 alpha = sin(w0) / (2 * s->frequency / (s->width * 1000));
270 alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0));
273 alpha = sin(w0) / (2 * s->width);
276 alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2);
284 switch (s->filter_type) {
288 s->a0 = 1 + alpha / A;
289 s->a1 = -2 * cos(w0);
290 s->a2 = 1 - alpha / A;
291 s->b0 = 1 + alpha * A;
292 s->b1 = -2 * cos(w0);
293 s->b2 = 1 - alpha * A;
296 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
298 s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha;
299 s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
300 s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha;
301 s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
302 s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
303 s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
306 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
308 s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha;
309 s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
310 s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha;
311 s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
312 s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
313 s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
318 s->a1 = -2 * cos(w0);
322 s->b2 = -sin(w0) / 2;
325 s->a1 = -2 * cos(w0);
334 s->a1 = -2 * cos(w0);
337 s->b1 = -2 * cos(w0);
350 s->a1 = -2 * cos(w0);
352 s->b0 = (1 - cos(w0)) / 2;
354 s->b2 = (1 - cos(w0)) / 2;
362 s->b0 = (1 - s->a1) / 2;
367 s->a1 = -2 * cos(w0);
369 s->b0 = (1 + cos(w0)) / 2;
370 s->b1 = -(1 + cos(w0));
371 s->b2 = (1 + cos(w0)) / 2;
376 s->a1 = -2 * cos(w0);
379 s->b1 = -2 * cos(w0);
386 av_log(ctx, AV_LOG_VERBOSE, "a=%lf %lf %lf:b=%lf %lf %lf\n", s->a0, s->a1, s->a2, s->b0, s->b1, s->b2);
395 s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels);
397 return AVERROR(ENOMEM);
399 memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
401 switch (inlink->format) {
402 case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
403 case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
404 case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
405 case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
406 default: av_assert0(0);
409 s->block_align = av_get_bytes_per_sample(inlink->format);
414 static int config_output(AVFilterLink *outlink)
416 return config_filter(outlink, 1);
419 typedef struct ThreadData {
423 static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
425 AVFilterLink *inlink = ctx->inputs[0];
426 ThreadData *td = arg;
427 AVFrame *buf = td->in;
428 AVFrame *out_buf = td->out;
429 BiquadsContext *s = ctx->priv;
430 const int start = (buf->channels * jobnr) / nb_jobs;
431 const int end = (buf->channels * (jobnr+1)) / nb_jobs;
434 for (ch = start; ch < end; ch++) {
435 if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) {
437 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
438 buf->nb_samples * s->block_align);
442 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
443 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
444 s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings);
450 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
452 AVFilterContext *ctx = inlink->dst;
453 BiquadsContext *s = ctx->priv;
454 AVFilterLink *outlink = ctx->outputs[0];
459 if (av_frame_is_writable(buf)) {
462 out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);
465 return AVERROR(ENOMEM);
467 av_frame_copy_props(out_buf, buf);
472 ctx->internal->execute(ctx, filter_channel, &td, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx)));
474 for (ch = 0; ch < outlink->channels; ch++) {
475 if (s->cache[ch].clippings > 0)
476 av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n",
477 ch, s->cache[ch].clippings);
478 s->cache[ch].clippings = 0;
484 return ff_filter_frame(outlink, out_buf);
487 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
488 char *res, int res_len, int flags)
490 BiquadsContext *s = ctx->priv;
491 AVFilterLink *outlink = ctx->outputs[0];
493 if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) &&
494 (s->filter_type == equalizer ||
495 s->filter_type == lowshelf ||
496 s->filter_type == highshelf ||
497 s->filter_type == bass ||
498 s->filter_type == treble ||
499 s->filter_type == bandpass ||
500 s->filter_type == bandreject||
501 s->filter_type == lowpass ||
502 s->filter_type == highpass ||
503 s->filter_type == allpass)) {
506 if (sscanf(args, "%lf", &freq) != 1) {
507 av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n");
508 return AVERROR(EINVAL);
512 } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) &&
513 (s->filter_type == equalizer ||
514 s->filter_type == lowshelf ||
515 s->filter_type == highshelf ||
516 s->filter_type == bass ||
517 s->filter_type == treble)) {
520 if (sscanf(args, "%lf", &gain) != 1) {
521 av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n");
522 return AVERROR(EINVAL);
526 } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) &&
527 (s->filter_type == equalizer ||
528 s->filter_type == lowshelf ||
529 s->filter_type == highshelf ||
530 s->filter_type == bass ||
531 s->filter_type == treble ||
532 s->filter_type == bandpass ||
533 s->filter_type == bandreject||
534 s->filter_type == lowpass ||
535 s->filter_type == highpass ||
536 s->filter_type == allpass)) {
539 if (sscanf(args, "%lf", &width) != 1) {
540 av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n");
541 return AVERROR(EINVAL);
545 } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) &&
546 (s->filter_type == equalizer ||
547 s->filter_type == lowshelf ||
548 s->filter_type == highshelf ||
549 s->filter_type == bass ||
550 s->filter_type == treble ||
551 s->filter_type == bandpass ||
552 s->filter_type == bandreject||
553 s->filter_type == lowpass ||
554 s->filter_type == highpass ||
555 s->filter_type == allpass)) {
558 if (sscanf(args, "%c", &width_type) != 1) {
559 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n");
560 return AVERROR(EINVAL);
563 switch (width_type) {
564 case 'h': width_type = HERTZ; break;
565 case 'q': width_type = QFACTOR; break;
566 case 'o': width_type = OCTAVE; break;
567 case 's': width_type = SLOPE; break;
568 case 'k': width_type = KHERTZ; break;
570 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type);
571 return AVERROR(EINVAL);
574 s->width_type = width_type;
575 } else if ((!strcmp(cmd, "a0") ||
576 !strcmp(cmd, "a1") ||
577 !strcmp(cmd, "a2") ||
578 !strcmp(cmd, "b0") ||
579 !strcmp(cmd, "b1") ||
580 !strcmp(cmd, "b2")) &&
581 s->filter_type == biquad) {
584 if (sscanf(args, "%lf", &value) != 1) {
585 av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n");
586 return AVERROR(EINVAL);
589 if (!strcmp(cmd, "a0"))
591 else if (!strcmp(cmd, "a1"))
593 else if (!strcmp(cmd, "a2"))
595 else if (!strcmp(cmd, "b0"))
597 else if (!strcmp(cmd, "b1"))
599 else if (!strcmp(cmd, "b2"))
603 return config_filter(outlink, 0);
606 static av_cold void uninit(AVFilterContext *ctx)
608 BiquadsContext *s = ctx->priv;
613 static const AVFilterPad inputs[] = {
616 .type = AVMEDIA_TYPE_AUDIO,
617 .filter_frame = filter_frame,
622 static const AVFilterPad outputs[] = {
625 .type = AVMEDIA_TYPE_AUDIO,
626 .config_props = config_output,
631 #define OFFSET(x) offsetof(BiquadsContext, x)
632 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
634 #define DEFINE_BIQUAD_FILTER(name_, description_) \
635 AVFILTER_DEFINE_CLASS(name_); \
636 static av_cold int name_##_init(AVFilterContext *ctx) \
638 BiquadsContext *s = ctx->priv; \
639 s->class = &name_##_class; \
640 s->filter_type = name_; \
644 AVFilter ff_af_##name_ = { \
646 .description = NULL_IF_CONFIG_SMALL(description_), \
647 .priv_size = sizeof(BiquadsContext), \
648 .init = name_##_init, \
650 .query_formats = query_formats, \
652 .outputs = outputs, \
653 .priv_class = &name_##_class, \
654 .process_command = process_command, \
655 .flags = AVFILTER_FLAG_SLICE_THREADS, \
658 #if CONFIG_EQUALIZER_FILTER
659 static const AVOption equalizer_options[] = {
660 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
661 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
662 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
663 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
664 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
665 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
666 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
667 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
668 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
669 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
670 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
671 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
672 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
673 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
674 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
678 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
679 #endif /* CONFIG_EQUALIZER_FILTER */
680 #if CONFIG_BASS_FILTER
681 static const AVOption bass_options[] = {
682 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
683 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
684 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
685 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
686 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
687 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
688 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
689 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
690 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
691 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
692 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
693 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
694 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
695 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
696 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
700 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
701 #endif /* CONFIG_BASS_FILTER */
702 #if CONFIG_TREBLE_FILTER
703 static const AVOption treble_options[] = {
704 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
705 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
706 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
707 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
708 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
709 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
710 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
711 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
712 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
713 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
714 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
715 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
716 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
717 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
718 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
722 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
723 #endif /* CONFIG_TREBLE_FILTER */
724 #if CONFIG_BANDPASS_FILTER
725 static const AVOption bandpass_options[] = {
726 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
727 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
728 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
729 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
730 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
731 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
732 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
733 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
734 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
735 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
736 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
737 {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
738 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
739 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
743 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
744 #endif /* CONFIG_BANDPASS_FILTER */
745 #if CONFIG_BANDREJECT_FILTER
746 static const AVOption bandreject_options[] = {
747 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
748 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
749 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
750 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
751 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
752 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
753 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
754 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
755 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
756 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
757 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
758 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
759 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
763 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
764 #endif /* CONFIG_BANDREJECT_FILTER */
765 #if CONFIG_LOWPASS_FILTER
766 static const AVOption lowpass_options[] = {
767 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
768 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
769 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
770 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
771 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
772 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
773 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
774 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
775 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
776 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
777 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
778 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
779 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
780 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
781 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
785 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
786 #endif /* CONFIG_LOWPASS_FILTER */
787 #if CONFIG_HIGHPASS_FILTER
788 static const AVOption highpass_options[] = {
789 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
790 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
791 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
792 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
793 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
794 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
795 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
796 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
797 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
798 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
799 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
800 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
801 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
802 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
803 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
807 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
808 #endif /* CONFIG_HIGHPASS_FILTER */
809 #if CONFIG_ALLPASS_FILTER
810 static const AVOption allpass_options[] = {
811 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
812 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
813 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
814 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
815 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
816 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
817 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
818 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
819 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
820 {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
821 {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
822 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
823 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
827 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
828 #endif /* CONFIG_ALLPASS_FILTER */
829 #if CONFIG_LOWSHELF_FILTER
830 static const AVOption lowshelf_options[] = {
831 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
832 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
833 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
834 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
835 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
836 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
837 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
838 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
839 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
840 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
841 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
842 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
843 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
844 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
845 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
849 DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter.");
850 #endif /* CONFIG_LOWSHELF_FILTER */
851 #if CONFIG_HIGHSHELF_FILTER
852 static const AVOption highshelf_options[] = {
853 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
854 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
855 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
856 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
857 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
858 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
859 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
860 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
861 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
862 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
863 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
864 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
865 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
866 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
867 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
871 DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter.");
872 #endif /* CONFIG_HIGHSHELF_FILTER */
873 #if CONFIG_BIQUAD_FILTER
874 static const AVOption biquad_options[] = {
875 {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS},
876 {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
877 {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
878 {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
879 {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
880 {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
881 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
882 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
886 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
887 #endif /* CONFIG_BIQUAD_FILTER */