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;
122 void (*filter)(struct BiquadsContext *s, const void *ibuf, void *obuf, int len,
123 double *i1, double *i2, double *o1, double *o2,
124 double b0, double b1, double b2, double a1, double a2, int *clippings,
128 static av_cold int init(AVFilterContext *ctx)
130 BiquadsContext *s = ctx->priv;
132 if (s->filter_type != biquad) {
133 if (s->frequency <= 0 || s->width <= 0) {
134 av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
135 s->frequency, s->width);
136 return AVERROR(EINVAL);
143 static int query_formats(AVFilterContext *ctx)
145 AVFilterFormats *formats;
146 AVFilterChannelLayouts *layouts;
147 static const enum AVSampleFormat sample_fmts[] = {
156 layouts = ff_all_channel_counts();
158 return AVERROR(ENOMEM);
159 ret = ff_set_common_channel_layouts(ctx, layouts);
163 formats = ff_make_format_list(sample_fmts);
165 return AVERROR(ENOMEM);
166 ret = ff_set_common_formats(ctx, formats);
170 formats = ff_all_samplerates();
172 return AVERROR(ENOMEM);
173 return ff_set_common_samplerates(ctx, formats);
176 #define BIQUAD_FILTER(name, type, min, max, need_clipping) \
177 static void biquad_## name (BiquadsContext *s, \
178 const void *input, void *output, int len, \
179 double *in1, double *in2, \
180 double *out1, double *out2, \
181 double b0, double b1, double b2, \
182 double a1, double a2, int *clippings, \
185 const type *ibuf = input; \
186 type *obuf = output; \
191 double wet = s->mix; \
192 double dry = 1. - wet; \
198 for (i = 0; i+1 < len; i++) { \
199 o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \
201 out = o2 * wet + i2 * dry; \
204 } else if (need_clipping && out < min) { \
207 } else if (need_clipping && out > max) { \
214 o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \
216 out = o1 * wet + i1 * dry; \
219 } else if (need_clipping && out < min) { \
222 } else if (need_clipping && out > max) { \
230 double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \
235 out = o0 * wet + i1 * dry; \
238 } else if (need_clipping && out < min) { \
241 } else if (need_clipping && out > max) { \
254 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
255 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
256 BIQUAD_FILTER(flt, float, -1., 1., 0)
257 BIQUAD_FILTER(dbl, double, -1., 1., 0)
259 static int config_filter(AVFilterLink *outlink, int reset)
261 AVFilterContext *ctx = outlink->src;
262 BiquadsContext *s = ctx->priv;
263 AVFilterLink *inlink = ctx->inputs[0];
264 double A = ff_exp10(s->gain / 40);
265 double w0 = 2 * M_PI * s->frequency / inlink->sample_rate;
269 av_log(ctx, AV_LOG_ERROR,
270 "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
271 s->frequency, inlink->sample_rate);
272 return AVERROR(EINVAL);
275 switch (s->width_type) {
280 alpha = sin(w0) / (2 * s->frequency / s->width);
283 alpha = sin(w0) / (2 * s->frequency / (s->width * 1000));
286 alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0));
289 alpha = sin(w0) / (2 * s->width);
292 alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2);
300 switch (s->filter_type) {
304 s->a0 = 1 + alpha / A;
305 s->a1 = -2 * cos(w0);
306 s->a2 = 1 - alpha / A;
307 s->b0 = 1 + alpha * A;
308 s->b1 = -2 * cos(w0);
309 s->b2 = 1 - alpha * A;
312 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
314 s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha;
315 s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
316 s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha;
317 s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
318 s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
319 s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
322 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
324 s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha;
325 s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
326 s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha;
327 s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
328 s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
329 s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
334 s->a1 = -2 * cos(w0);
338 s->b2 = -sin(w0) / 2;
341 s->a1 = -2 * cos(w0);
350 s->a1 = -2 * cos(w0);
353 s->b1 = -2 * cos(w0);
366 s->a1 = -2 * cos(w0);
368 s->b0 = (1 - cos(w0)) / 2;
370 s->b2 = (1 - cos(w0)) / 2;
378 s->b0 = (1 - s->a1) / 2;
383 s->a1 = -2 * cos(w0);
385 s->b0 = (1 + cos(w0)) / 2;
386 s->b1 = -(1 + cos(w0));
387 s->b2 = (1 + cos(w0)) / 2;
392 s->a1 = -2 * cos(w0);
395 s->b1 = -2 * cos(w0);
402 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);
411 s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels);
413 return AVERROR(ENOMEM);
415 memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
417 switch (inlink->format) {
418 case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
419 case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
420 case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
421 case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
422 default: av_assert0(0);
425 s->block_align = av_get_bytes_per_sample(inlink->format);
430 static int config_output(AVFilterLink *outlink)
432 return config_filter(outlink, 1);
435 typedef struct ThreadData {
439 static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
441 AVFilterLink *inlink = ctx->inputs[0];
442 ThreadData *td = arg;
443 AVFrame *buf = td->in;
444 AVFrame *out_buf = td->out;
445 BiquadsContext *s = ctx->priv;
446 const int start = (buf->channels * jobnr) / nb_jobs;
447 const int end = (buf->channels * (jobnr+1)) / nb_jobs;
450 for (ch = start; ch < end; ch++) {
451 if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) {
453 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
454 buf->nb_samples * s->block_align);
458 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
459 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
460 s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
466 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
468 AVFilterContext *ctx = inlink->dst;
469 BiquadsContext *s = ctx->priv;
470 AVFilterLink *outlink = ctx->outputs[0];
475 if (av_frame_is_writable(buf)) {
478 out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);
481 return AVERROR(ENOMEM);
483 av_frame_copy_props(out_buf, buf);
488 ctx->internal->execute(ctx, filter_channel, &td, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx)));
490 for (ch = 0; ch < outlink->channels; ch++) {
491 if (s->cache[ch].clippings > 0)
492 av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n",
493 ch, s->cache[ch].clippings);
494 s->cache[ch].clippings = 0;
500 return ff_filter_frame(outlink, out_buf);
503 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
504 char *res, int res_len, int flags)
506 BiquadsContext *s = ctx->priv;
507 AVFilterLink *outlink = ctx->outputs[0];
509 if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) &&
510 (s->filter_type == equalizer ||
511 s->filter_type == lowshelf ||
512 s->filter_type == highshelf ||
513 s->filter_type == bass ||
514 s->filter_type == treble ||
515 s->filter_type == bandpass ||
516 s->filter_type == bandreject||
517 s->filter_type == lowpass ||
518 s->filter_type == highpass ||
519 s->filter_type == allpass)) {
522 if (sscanf(args, "%lf", &freq) != 1) {
523 av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n");
524 return AVERROR(EINVAL);
528 } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) &&
529 (s->filter_type == equalizer ||
530 s->filter_type == lowshelf ||
531 s->filter_type == highshelf ||
532 s->filter_type == bass ||
533 s->filter_type == treble)) {
536 if (sscanf(args, "%lf", &gain) != 1) {
537 av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n");
538 return AVERROR(EINVAL);
541 s->gain = av_clipd(gain, -900, 900);
542 } else if (!strcmp(cmd, "mix") || !strcmp(cmd, "m")) {
545 if (sscanf(args, "%lf", &mix) != 1) {
546 av_log(ctx, AV_LOG_ERROR, "Invalid mix value.\n");
547 return AVERROR(EINVAL);
550 s->mix = av_clipd(mix, 0, 1);
551 } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) &&
552 (s->filter_type == equalizer ||
553 s->filter_type == lowshelf ||
554 s->filter_type == highshelf ||
555 s->filter_type == bass ||
556 s->filter_type == treble ||
557 s->filter_type == bandpass ||
558 s->filter_type == bandreject||
559 s->filter_type == lowpass ||
560 s->filter_type == highpass ||
561 s->filter_type == allpass)) {
564 if (sscanf(args, "%lf", &width) != 1) {
565 av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n");
566 return AVERROR(EINVAL);
570 } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) &&
571 (s->filter_type == equalizer ||
572 s->filter_type == lowshelf ||
573 s->filter_type == highshelf ||
574 s->filter_type == bass ||
575 s->filter_type == treble ||
576 s->filter_type == bandpass ||
577 s->filter_type == bandreject||
578 s->filter_type == lowpass ||
579 s->filter_type == highpass ||
580 s->filter_type == allpass)) {
583 if (sscanf(args, "%c", &width_type) != 1) {
584 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n");
585 return AVERROR(EINVAL);
588 switch (width_type) {
589 case 'h': width_type = HERTZ; break;
590 case 'q': width_type = QFACTOR; break;
591 case 'o': width_type = OCTAVE; break;
592 case 's': width_type = SLOPE; break;
593 case 'k': width_type = KHERTZ; break;
595 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type);
596 return AVERROR(EINVAL);
599 s->width_type = width_type;
600 } else if ((!strcmp(cmd, "a0") ||
601 !strcmp(cmd, "a1") ||
602 !strcmp(cmd, "a2") ||
603 !strcmp(cmd, "b0") ||
604 !strcmp(cmd, "b1") ||
605 !strcmp(cmd, "b2")) &&
606 s->filter_type == biquad) {
609 if (sscanf(args, "%lf", &value) != 1) {
610 av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n");
611 return AVERROR(EINVAL);
614 if (!strcmp(cmd, "a0"))
616 else if (!strcmp(cmd, "a1"))
618 else if (!strcmp(cmd, "a2"))
620 else if (!strcmp(cmd, "b0"))
622 else if (!strcmp(cmd, "b1"))
624 else if (!strcmp(cmd, "b2"))
628 return config_filter(outlink, 0);
631 static av_cold void uninit(AVFilterContext *ctx)
633 BiquadsContext *s = ctx->priv;
638 static const AVFilterPad inputs[] = {
641 .type = AVMEDIA_TYPE_AUDIO,
642 .filter_frame = filter_frame,
647 static const AVFilterPad outputs[] = {
650 .type = AVMEDIA_TYPE_AUDIO,
651 .config_props = config_output,
656 #define OFFSET(x) offsetof(BiquadsContext, x)
657 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
659 #define DEFINE_BIQUAD_FILTER(name_, description_) \
660 AVFILTER_DEFINE_CLASS(name_); \
661 static av_cold int name_##_init(AVFilterContext *ctx) \
663 BiquadsContext *s = ctx->priv; \
664 s->class = &name_##_class; \
665 s->filter_type = name_; \
669 AVFilter ff_af_##name_ = { \
671 .description = NULL_IF_CONFIG_SMALL(description_), \
672 .priv_size = sizeof(BiquadsContext), \
673 .init = name_##_init, \
675 .query_formats = query_formats, \
677 .outputs = outputs, \
678 .priv_class = &name_##_class, \
679 .process_command = process_command, \
680 .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, \
683 #if CONFIG_EQUALIZER_FILTER
684 static const AVOption equalizer_options[] = {
685 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
686 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
687 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
688 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
689 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
690 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
691 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
692 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
693 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
694 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
695 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
696 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
697 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
698 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
699 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
700 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
701 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
705 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
706 #endif /* CONFIG_EQUALIZER_FILTER */
707 #if CONFIG_BASS_FILTER
708 static const AVOption bass_options[] = {
709 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
710 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
711 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
712 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
713 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
714 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
715 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
716 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
717 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
718 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
719 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
720 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
721 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
722 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
723 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
724 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
725 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
729 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
730 #endif /* CONFIG_BASS_FILTER */
731 #if CONFIG_TREBLE_FILTER
732 static const AVOption treble_options[] = {
733 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
734 {"f", "set central 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 shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
743 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
744 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
745 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
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},
753 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
754 #endif /* CONFIG_TREBLE_FILTER */
755 #if CONFIG_BANDPASS_FILTER
756 static const AVOption bandpass_options[] = {
757 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
758 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
759 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
760 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
761 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
762 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
763 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
764 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
765 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
766 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
767 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
768 {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
769 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
770 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
771 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
772 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
776 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
777 #endif /* CONFIG_BANDPASS_FILTER */
778 #if CONFIG_BANDREJECT_FILTER
779 static const AVOption bandreject_options[] = {
780 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
781 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
782 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
783 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
784 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
785 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
786 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
787 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
788 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
789 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
790 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
791 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
792 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
793 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
794 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
798 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
799 #endif /* CONFIG_BANDREJECT_FILTER */
800 #if CONFIG_LOWPASS_FILTER
801 static const AVOption lowpass_options[] = {
802 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
803 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
804 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
805 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
806 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
807 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
808 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
809 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
810 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
811 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
812 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
813 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
814 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
815 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
816 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
817 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
818 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
822 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
823 #endif /* CONFIG_LOWPASS_FILTER */
824 #if CONFIG_HIGHPASS_FILTER
825 static const AVOption highpass_options[] = {
826 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
827 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
828 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
829 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
830 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
831 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
832 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
833 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
834 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
835 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
836 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
837 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
838 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
839 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
840 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
841 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
842 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
846 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
847 #endif /* CONFIG_HIGHPASS_FILTER */
848 #if CONFIG_ALLPASS_FILTER
849 static const AVOption allpass_options[] = {
850 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
851 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
852 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
853 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
854 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
855 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
856 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
857 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
858 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
859 {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
860 {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
861 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
862 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
863 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
864 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
868 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
869 #endif /* CONFIG_ALLPASS_FILTER */
870 #if CONFIG_LOWSHELF_FILTER
871 static const AVOption lowshelf_options[] = {
872 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
873 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
874 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
875 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
876 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
877 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
878 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
879 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
880 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
881 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
882 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
883 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
884 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
885 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
886 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
887 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
888 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
892 DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter.");
893 #endif /* CONFIG_LOWSHELF_FILTER */
894 #if CONFIG_HIGHSHELF_FILTER
895 static const AVOption highshelf_options[] = {
896 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
897 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
898 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
899 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
900 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
901 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
902 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
903 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
904 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
905 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
906 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
907 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
908 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
909 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
910 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
911 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
912 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
916 DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter.");
917 #endif /* CONFIG_HIGHSHELF_FILTER */
918 #if CONFIG_BIQUAD_FILTER
919 static const AVOption biquad_options[] = {
920 {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS},
921 {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
922 {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
923 {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
924 {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
925 {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
926 {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
927 {"m", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
928 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
929 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
933 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
934 #endif /* CONFIG_BIQUAD_FILTER */