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/ffmath.h"
67 #include "libavutil/opt.h"
96 typedef struct ChanCache {
102 typedef struct BiquadsContext {
103 const AVClass *class;
105 enum FilterType filter_type;
121 void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,
122 double *i1, double *i2, double *o1, double *o2,
123 double b0, double b1, double b2, double a1, double a2, int *clippings);
126 static av_cold int init(AVFilterContext *ctx)
128 BiquadsContext *s = ctx->priv;
130 if (s->filter_type != biquad) {
131 if (s->frequency <= 0 || s->width <= 0) {
132 av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
133 s->frequency, s->width);
134 return AVERROR(EINVAL);
141 static int query_formats(AVFilterContext *ctx)
143 AVFilterFormats *formats;
144 AVFilterChannelLayouts *layouts;
145 static const enum AVSampleFormat sample_fmts[] = {
154 layouts = ff_all_channel_counts();
156 return AVERROR(ENOMEM);
157 ret = ff_set_common_channel_layouts(ctx, layouts);
161 formats = ff_make_format_list(sample_fmts);
163 return AVERROR(ENOMEM);
164 ret = ff_set_common_formats(ctx, formats);
168 formats = ff_all_samplerates();
170 return AVERROR(ENOMEM);
171 return ff_set_common_samplerates(ctx, formats);
174 #define BIQUAD_FILTER(name, type, min, max, need_clipping) \
175 static void biquad_## name (BiquadsContext *s, \
176 const void *input, void *output, int len, \
177 double *in1, double *in2, \
178 double *out1, double *out2, \
179 double b0, double b1, double b2, \
180 double a1, double a2, int *clippings) \
182 const type *ibuf = input; \
183 type *obuf = output; \
192 for (i = 0; i+1 < len; i++) { \
193 o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \
195 if (need_clipping && o2 < min) { \
198 } else if (need_clipping && o2 > max) { \
205 o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \
207 if (need_clipping && o1 < min) { \
210 } else if (need_clipping && o1 > max) { \
218 double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \
223 if (need_clipping && o0 < min) { \
226 } else if (need_clipping && o0 > max) { \
239 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
240 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
241 BIQUAD_FILTER(flt, float, -1., 1., 0)
242 BIQUAD_FILTER(dbl, double, -1., 1., 0)
244 static int config_filter(AVFilterLink *outlink, int reset)
246 AVFilterContext *ctx = outlink->src;
247 BiquadsContext *s = ctx->priv;
248 AVFilterLink *inlink = ctx->inputs[0];
249 double A = ff_exp10(s->gain / 40);
250 double w0 = 2 * M_PI * s->frequency / inlink->sample_rate;
254 av_log(ctx, AV_LOG_ERROR,
255 "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
256 s->frequency, inlink->sample_rate);
257 return AVERROR(EINVAL);
260 switch (s->width_type) {
265 alpha = sin(w0) / (2 * s->frequency / s->width);
268 alpha = sin(w0) / (2 * s->frequency / (s->width * 1000));
271 alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0));
274 alpha = sin(w0) / (2 * s->width);
277 alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2);
285 switch (s->filter_type) {
289 s->a0 = 1 + alpha / A;
290 s->a1 = -2 * cos(w0);
291 s->a2 = 1 - alpha / A;
292 s->b0 = 1 + alpha * A;
293 s->b1 = -2 * cos(w0);
294 s->b2 = 1 - alpha * A;
297 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
299 s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha;
300 s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
301 s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha;
302 s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
303 s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
304 s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
307 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
309 s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha;
310 s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
311 s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha;
312 s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
313 s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
314 s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
319 s->a1 = -2 * cos(w0);
323 s->b2 = -sin(w0) / 2;
326 s->a1 = -2 * cos(w0);
335 s->a1 = -2 * cos(w0);
338 s->b1 = -2 * cos(w0);
351 s->a1 = -2 * cos(w0);
353 s->b0 = (1 - cos(w0)) / 2;
355 s->b2 = (1 - cos(w0)) / 2;
363 s->b0 = (1 - s->a1) / 2;
368 s->a1 = -2 * cos(w0);
370 s->b0 = (1 + cos(w0)) / 2;
371 s->b1 = -(1 + cos(w0));
372 s->b2 = (1 + cos(w0)) / 2;
377 s->a1 = -2 * cos(w0);
380 s->b1 = -2 * cos(w0);
387 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);
396 s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels);
398 return AVERROR(ENOMEM);
400 memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
402 switch (inlink->format) {
403 case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
404 case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
405 case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
406 case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
407 default: av_assert0(0);
410 s->block_align = av_get_bytes_per_sample(inlink->format);
415 static int config_output(AVFilterLink *outlink)
417 return config_filter(outlink, 1);
420 typedef struct ThreadData {
424 static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
426 AVFilterLink *inlink = ctx->inputs[0];
427 ThreadData *td = arg;
428 AVFrame *buf = td->in;
429 AVFrame *out_buf = td->out;
430 BiquadsContext *s = ctx->priv;
431 const int start = (buf->channels * jobnr) / nb_jobs;
432 const int end = (buf->channels * (jobnr+1)) / nb_jobs;
435 for (ch = start; ch < end; ch++) {
436 if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) {
438 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
439 buf->nb_samples * s->block_align);
443 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
444 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
445 s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings);
451 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
453 AVFilterContext *ctx = inlink->dst;
454 BiquadsContext *s = ctx->priv;
455 AVFilterLink *outlink = ctx->outputs[0];
460 if (av_frame_is_writable(buf)) {
463 out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);
466 return AVERROR(ENOMEM);
468 av_frame_copy_props(out_buf, buf);
473 ctx->internal->execute(ctx, filter_channel, &td, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx)));
475 for (ch = 0; ch < outlink->channels; ch++) {
476 if (s->cache[ch].clippings > 0)
477 av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n",
478 ch, s->cache[ch].clippings);
479 s->cache[ch].clippings = 0;
485 return ff_filter_frame(outlink, out_buf);
488 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
489 char *res, int res_len, int flags)
491 BiquadsContext *s = ctx->priv;
492 AVFilterLink *outlink = ctx->outputs[0];
494 if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) &&
495 (s->filter_type == equalizer ||
496 s->filter_type == lowshelf ||
497 s->filter_type == highshelf ||
498 s->filter_type == bass ||
499 s->filter_type == treble ||
500 s->filter_type == bandpass ||
501 s->filter_type == bandreject||
502 s->filter_type == lowpass ||
503 s->filter_type == highpass ||
504 s->filter_type == allpass)) {
507 if (sscanf(args, "%lf", &freq) != 1) {
508 av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n");
509 return AVERROR(EINVAL);
513 } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) &&
514 (s->filter_type == equalizer ||
515 s->filter_type == lowshelf ||
516 s->filter_type == highshelf ||
517 s->filter_type == bass ||
518 s->filter_type == treble)) {
521 if (sscanf(args, "%lf", &gain) != 1) {
522 av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n");
523 return AVERROR(EINVAL);
527 } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) &&
528 (s->filter_type == equalizer ||
529 s->filter_type == lowshelf ||
530 s->filter_type == highshelf ||
531 s->filter_type == bass ||
532 s->filter_type == treble ||
533 s->filter_type == bandpass ||
534 s->filter_type == bandreject||
535 s->filter_type == lowpass ||
536 s->filter_type == highpass ||
537 s->filter_type == allpass)) {
540 if (sscanf(args, "%lf", &width) != 1) {
541 av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n");
542 return AVERROR(EINVAL);
546 } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) &&
547 (s->filter_type == equalizer ||
548 s->filter_type == lowshelf ||
549 s->filter_type == highshelf ||
550 s->filter_type == bass ||
551 s->filter_type == treble ||
552 s->filter_type == bandpass ||
553 s->filter_type == bandreject||
554 s->filter_type == lowpass ||
555 s->filter_type == highpass ||
556 s->filter_type == allpass)) {
559 if (sscanf(args, "%c", &width_type) != 1) {
560 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n");
561 return AVERROR(EINVAL);
564 switch (width_type) {
565 case 'h': width_type = HERTZ; break;
566 case 'q': width_type = QFACTOR; break;
567 case 'o': width_type = OCTAVE; break;
568 case 's': width_type = SLOPE; break;
569 case 'k': width_type = KHERTZ; break;
571 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type);
572 return AVERROR(EINVAL);
575 s->width_type = width_type;
576 } else if ((!strcmp(cmd, "a0") ||
577 !strcmp(cmd, "a1") ||
578 !strcmp(cmd, "a2") ||
579 !strcmp(cmd, "b0") ||
580 !strcmp(cmd, "b1") ||
581 !strcmp(cmd, "b2")) &&
582 s->filter_type == biquad) {
585 if (sscanf(args, "%lf", &value) != 1) {
586 av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n");
587 return AVERROR(EINVAL);
590 if (!strcmp(cmd, "a0"))
592 else if (!strcmp(cmd, "a1"))
594 else if (!strcmp(cmd, "a2"))
596 else if (!strcmp(cmd, "b0"))
598 else if (!strcmp(cmd, "b1"))
600 else if (!strcmp(cmd, "b2"))
604 return config_filter(outlink, 0);
607 static av_cold void uninit(AVFilterContext *ctx)
609 BiquadsContext *s = ctx->priv;
614 static const AVFilterPad inputs[] = {
617 .type = AVMEDIA_TYPE_AUDIO,
618 .filter_frame = filter_frame,
623 static const AVFilterPad outputs[] = {
626 .type = AVMEDIA_TYPE_AUDIO,
627 .config_props = config_output,
632 #define OFFSET(x) offsetof(BiquadsContext, x)
633 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
635 #define DEFINE_BIQUAD_FILTER(name_, description_) \
636 AVFILTER_DEFINE_CLASS(name_); \
637 static av_cold int name_##_init(AVFilterContext *ctx) \
639 BiquadsContext *s = ctx->priv; \
640 s->class = &name_##_class; \
641 s->filter_type = name_; \
645 AVFilter ff_af_##name_ = { \
647 .description = NULL_IF_CONFIG_SMALL(description_), \
648 .priv_size = sizeof(BiquadsContext), \
649 .init = name_##_init, \
651 .query_formats = query_formats, \
653 .outputs = outputs, \
654 .priv_class = &name_##_class, \
655 .process_command = process_command, \
656 .flags = AVFILTER_FLAG_SLICE_THREADS, \
659 #if CONFIG_EQUALIZER_FILTER
660 static const AVOption equalizer_options[] = {
661 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
662 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
663 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
664 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
665 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
666 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
667 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
668 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
669 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
670 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
671 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
672 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
673 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
674 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
675 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
679 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
680 #endif /* CONFIG_EQUALIZER_FILTER */
681 #if CONFIG_BASS_FILTER
682 static const AVOption bass_options[] = {
683 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
684 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 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 shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
693 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
694 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
695 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, 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},
701 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
702 #endif /* CONFIG_BASS_FILTER */
703 #if CONFIG_TREBLE_FILTER
704 static const AVOption treble_options[] = {
705 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
706 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
707 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
708 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
709 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
710 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
711 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
712 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
713 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
714 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
715 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
716 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
717 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
718 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
719 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
723 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
724 #endif /* CONFIG_TREBLE_FILTER */
725 #if CONFIG_BANDPASS_FILTER
726 static const AVOption bandpass_options[] = {
727 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
728 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
729 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
730 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
731 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
732 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
733 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
734 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
735 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
736 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
737 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
738 {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
739 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
740 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
744 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
745 #endif /* CONFIG_BANDPASS_FILTER */
746 #if CONFIG_BANDREJECT_FILTER
747 static const AVOption bandreject_options[] = {
748 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
749 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
750 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
751 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
752 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
753 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
754 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
755 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
756 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
757 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
758 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
759 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
760 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
764 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
765 #endif /* CONFIG_BANDREJECT_FILTER */
766 #if CONFIG_LOWPASS_FILTER
767 static const AVOption lowpass_options[] = {
768 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
769 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
770 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
771 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
772 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
773 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
774 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
775 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
776 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
777 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
778 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
779 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
780 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
781 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
782 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
786 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
787 #endif /* CONFIG_LOWPASS_FILTER */
788 #if CONFIG_HIGHPASS_FILTER
789 static const AVOption highpass_options[] = {
790 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
791 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
792 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
793 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
794 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
795 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
796 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
797 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
798 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
799 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
800 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
801 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
802 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
803 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
804 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
808 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
809 #endif /* CONFIG_HIGHPASS_FILTER */
810 #if CONFIG_ALLPASS_FILTER
811 static const AVOption allpass_options[] = {
812 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
813 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
814 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
815 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
816 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
817 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
818 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
819 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
820 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
821 {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
822 {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
823 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
824 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
828 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
829 #endif /* CONFIG_ALLPASS_FILTER */
830 #if CONFIG_LOWSHELF_FILTER
831 static const AVOption lowshelf_options[] = {
832 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
833 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
834 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
835 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
836 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
837 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
838 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
839 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
840 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
841 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
842 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
843 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
844 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
845 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
846 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
850 DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter.");
851 #endif /* CONFIG_LOWSHELF_FILTER */
852 #if CONFIG_HIGHSHELF_FILTER
853 static const AVOption highshelf_options[] = {
854 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
855 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
856 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
857 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
858 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
859 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
860 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
861 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
862 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
863 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
864 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
865 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
866 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
867 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
868 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
872 DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter.");
873 #endif /* CONFIG_HIGHSHELF_FILTER */
874 #if CONFIG_BIQUAD_FILTER
875 static const AVOption biquad_options[] = {
876 {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS},
877 {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
878 {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
879 {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
880 {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
881 {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
882 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
883 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
887 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
888 #endif /* CONFIG_BIQUAD_FILTER */