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,
127 static av_cold int init(AVFilterContext *ctx)
129 BiquadsContext *s = ctx->priv;
131 if (s->filter_type != biquad) {
132 if (s->frequency <= 0 || s->width <= 0) {
133 av_log(ctx, AV_LOG_ERROR, "Invalid frequency %f and/or width %f <= 0\n",
134 s->frequency, s->width);
135 return AVERROR(EINVAL);
142 static int query_formats(AVFilterContext *ctx)
144 AVFilterFormats *formats;
145 AVFilterChannelLayouts *layouts;
146 static const enum AVSampleFormat sample_fmts[] = {
155 layouts = ff_all_channel_counts();
157 return AVERROR(ENOMEM);
158 ret = ff_set_common_channel_layouts(ctx, layouts);
162 formats = ff_make_format_list(sample_fmts);
164 return AVERROR(ENOMEM);
165 ret = ff_set_common_formats(ctx, formats);
169 formats = ff_all_samplerates();
171 return AVERROR(ENOMEM);
172 return ff_set_common_samplerates(ctx, formats);
175 #define BIQUAD_FILTER(name, type, min, max, need_clipping) \
176 static void biquad_## name (BiquadsContext *s, \
177 const void *input, void *output, int len, \
178 double *in1, double *in2, \
179 double *out1, double *out2, \
180 double b0, double b1, double b2, \
181 double a1, double a2, int *clippings, \
184 const type *ibuf = input; \
185 type *obuf = output; \
194 for (i = 0; i+1 < len; i++) { \
195 o2 = i2 * b2 + i1 * b1 + ibuf[i] * b0 + o2 * a2 + o1 * a1; \
199 } else if (need_clipping && o2 < min) { \
202 } else if (need_clipping && o2 > max) { \
209 o1 = i1 * b2 + i2 * b1 + ibuf[i] * b0 + o1 * a2 + o2 * a1; \
213 } else if (need_clipping && o1 < min) { \
216 } else if (need_clipping && o1 > max) { \
224 double o0 = ibuf[i] * b0 + i1 * b1 + i2 * b2 + o1 * a1 + o2 * a2; \
231 } else if (need_clipping && o0 < min) { \
234 } else if (need_clipping && o0 > max) { \
247 BIQUAD_FILTER(s16, int16_t, INT16_MIN, INT16_MAX, 1)
248 BIQUAD_FILTER(s32, int32_t, INT32_MIN, INT32_MAX, 1)
249 BIQUAD_FILTER(flt, float, -1., 1., 0)
250 BIQUAD_FILTER(dbl, double, -1., 1., 0)
252 static int config_filter(AVFilterLink *outlink, int reset)
254 AVFilterContext *ctx = outlink->src;
255 BiquadsContext *s = ctx->priv;
256 AVFilterLink *inlink = ctx->inputs[0];
257 double A = ff_exp10(s->gain / 40);
258 double w0 = 2 * M_PI * s->frequency / inlink->sample_rate;
262 av_log(ctx, AV_LOG_ERROR,
263 "Invalid frequency %f. Frequency must be less than half the sample-rate %d.\n",
264 s->frequency, inlink->sample_rate);
265 return AVERROR(EINVAL);
268 switch (s->width_type) {
273 alpha = sin(w0) / (2 * s->frequency / s->width);
276 alpha = sin(w0) / (2 * s->frequency / (s->width * 1000));
279 alpha = sin(w0) * sinh(log(2.) / 2 * s->width * w0 / sin(w0));
282 alpha = sin(w0) / (2 * s->width);
285 alpha = sin(w0) / 2 * sqrt((A + 1 / A) * (1 / s->width - 1) + 2);
293 switch (s->filter_type) {
297 s->a0 = 1 + alpha / A;
298 s->a1 = -2 * cos(w0);
299 s->a2 = 1 - alpha / A;
300 s->b0 = 1 + alpha * A;
301 s->b1 = -2 * cos(w0);
302 s->b2 = 1 - alpha * A;
305 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
307 s->a0 = (A + 1) + (A - 1) * cos(w0) + beta * alpha;
308 s->a1 = -2 * ((A - 1) + (A + 1) * cos(w0));
309 s->a2 = (A + 1) + (A - 1) * cos(w0) - beta * alpha;
310 s->b0 = A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
311 s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
312 s->b2 = A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
315 beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
317 s->a0 = (A + 1) - (A - 1) * cos(w0) + beta * alpha;
318 s->a1 = 2 * ((A - 1) - (A + 1) * cos(w0));
319 s->a2 = (A + 1) - (A - 1) * cos(w0) - beta * alpha;
320 s->b0 = A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
321 s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
322 s->b2 = A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
327 s->a1 = -2 * cos(w0);
331 s->b2 = -sin(w0) / 2;
334 s->a1 = -2 * cos(w0);
343 s->a1 = -2 * cos(w0);
346 s->b1 = -2 * cos(w0);
359 s->a1 = -2 * cos(w0);
361 s->b0 = (1 - cos(w0)) / 2;
363 s->b2 = (1 - cos(w0)) / 2;
371 s->b0 = (1 - s->a1) / 2;
376 s->a1 = -2 * cos(w0);
378 s->b0 = (1 + cos(w0)) / 2;
379 s->b1 = -(1 + cos(w0));
380 s->b2 = (1 + cos(w0)) / 2;
385 s->a1 = -2 * cos(w0);
388 s->b1 = -2 * cos(w0);
395 av_log(ctx, AV_LOG_VERBOSE, "a=%f %f %f:b=%f %f %f\n", s->a0, s->a1, s->a2, s->b0, s->b1, s->b2);
404 s->cache = av_realloc_f(s->cache, sizeof(ChanCache), inlink->channels);
406 return AVERROR(ENOMEM);
408 memset(s->cache, 0, sizeof(ChanCache) * inlink->channels);
410 switch (inlink->format) {
411 case AV_SAMPLE_FMT_S16P: s->filter = biquad_s16; break;
412 case AV_SAMPLE_FMT_S32P: s->filter = biquad_s32; break;
413 case AV_SAMPLE_FMT_FLTP: s->filter = biquad_flt; break;
414 case AV_SAMPLE_FMT_DBLP: s->filter = biquad_dbl; break;
415 default: av_assert0(0);
418 s->block_align = av_get_bytes_per_sample(inlink->format);
423 static int config_output(AVFilterLink *outlink)
425 return config_filter(outlink, 1);
428 typedef struct ThreadData {
432 static int filter_channel(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
434 AVFilterLink *inlink = ctx->inputs[0];
435 ThreadData *td = arg;
436 AVFrame *buf = td->in;
437 AVFrame *out_buf = td->out;
438 BiquadsContext *s = ctx->priv;
439 const int start = (buf->channels * jobnr) / nb_jobs;
440 const int end = (buf->channels * (jobnr+1)) / nb_jobs;
443 for (ch = start; ch < end; ch++) {
444 if (!((av_channel_layout_extract_channel(inlink->channel_layout, ch) & s->channels))) {
446 memcpy(out_buf->extended_data[ch], buf->extended_data[ch],
447 buf->nb_samples * s->block_align);
451 s->filter(s, buf->extended_data[ch], out_buf->extended_data[ch], buf->nb_samples,
452 &s->cache[ch].i1, &s->cache[ch].i2, &s->cache[ch].o1, &s->cache[ch].o2,
453 s->b0, s->b1, s->b2, s->a1, s->a2, &s->cache[ch].clippings, ctx->is_disabled);
459 static int filter_frame(AVFilterLink *inlink, AVFrame *buf)
461 AVFilterContext *ctx = inlink->dst;
462 BiquadsContext *s = ctx->priv;
463 AVFilterLink *outlink = ctx->outputs[0];
468 if (av_frame_is_writable(buf)) {
471 out_buf = ff_get_audio_buffer(outlink, buf->nb_samples);
474 return AVERROR(ENOMEM);
476 av_frame_copy_props(out_buf, buf);
481 ctx->internal->execute(ctx, filter_channel, &td, NULL, FFMIN(outlink->channels, ff_filter_get_nb_threads(ctx)));
483 for (ch = 0; ch < outlink->channels; ch++) {
484 if (s->cache[ch].clippings > 0)
485 av_log(ctx, AV_LOG_WARNING, "Channel %d clipping %d times. Please reduce gain.\n",
486 ch, s->cache[ch].clippings);
487 s->cache[ch].clippings = 0;
493 return ff_filter_frame(outlink, out_buf);
496 static int process_command(AVFilterContext *ctx, const char *cmd, const char *args,
497 char *res, int res_len, int flags)
499 BiquadsContext *s = ctx->priv;
500 AVFilterLink *outlink = ctx->outputs[0];
502 if ((!strcmp(cmd, "frequency") || !strcmp(cmd, "f")) &&
503 (s->filter_type == equalizer ||
504 s->filter_type == lowshelf ||
505 s->filter_type == highshelf ||
506 s->filter_type == bass ||
507 s->filter_type == treble ||
508 s->filter_type == bandpass ||
509 s->filter_type == bandreject||
510 s->filter_type == lowpass ||
511 s->filter_type == highpass ||
512 s->filter_type == allpass)) {
515 if (sscanf(args, "%lf", &freq) != 1) {
516 av_log(ctx, AV_LOG_ERROR, "Invalid frequency value.\n");
517 return AVERROR(EINVAL);
521 } else if ((!strcmp(cmd, "gain") || !strcmp(cmd, "g")) &&
522 (s->filter_type == equalizer ||
523 s->filter_type == lowshelf ||
524 s->filter_type == highshelf ||
525 s->filter_type == bass ||
526 s->filter_type == treble)) {
529 if (sscanf(args, "%lf", &gain) != 1) {
530 av_log(ctx, AV_LOG_ERROR, "Invalid gain value.\n");
531 return AVERROR(EINVAL);
535 } else if ((!strcmp(cmd, "width") || !strcmp(cmd, "w")) &&
536 (s->filter_type == equalizer ||
537 s->filter_type == lowshelf ||
538 s->filter_type == highshelf ||
539 s->filter_type == bass ||
540 s->filter_type == treble ||
541 s->filter_type == bandpass ||
542 s->filter_type == bandreject||
543 s->filter_type == lowpass ||
544 s->filter_type == highpass ||
545 s->filter_type == allpass)) {
548 if (sscanf(args, "%lf", &width) != 1) {
549 av_log(ctx, AV_LOG_ERROR, "Invalid width value.\n");
550 return AVERROR(EINVAL);
554 } else if ((!strcmp(cmd, "width_type") || !strcmp(cmd, "t")) &&
555 (s->filter_type == equalizer ||
556 s->filter_type == lowshelf ||
557 s->filter_type == highshelf ||
558 s->filter_type == bass ||
559 s->filter_type == treble ||
560 s->filter_type == bandpass ||
561 s->filter_type == bandreject||
562 s->filter_type == lowpass ||
563 s->filter_type == highpass ||
564 s->filter_type == allpass)) {
567 if (sscanf(args, "%c", &width_type) != 1) {
568 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value.\n");
569 return AVERROR(EINVAL);
572 switch (width_type) {
573 case 'h': width_type = HERTZ; break;
574 case 'q': width_type = QFACTOR; break;
575 case 'o': width_type = OCTAVE; break;
576 case 's': width_type = SLOPE; break;
577 case 'k': width_type = KHERTZ; break;
579 av_log(ctx, AV_LOG_ERROR, "Invalid width_type value: %c\n", width_type);
580 return AVERROR(EINVAL);
583 s->width_type = width_type;
584 } else if ((!strcmp(cmd, "a0") ||
585 !strcmp(cmd, "a1") ||
586 !strcmp(cmd, "a2") ||
587 !strcmp(cmd, "b0") ||
588 !strcmp(cmd, "b1") ||
589 !strcmp(cmd, "b2")) &&
590 s->filter_type == biquad) {
593 if (sscanf(args, "%lf", &value) != 1) {
594 av_log(ctx, AV_LOG_ERROR, "Invalid biquad value.\n");
595 return AVERROR(EINVAL);
598 if (!strcmp(cmd, "a0"))
600 else if (!strcmp(cmd, "a1"))
602 else if (!strcmp(cmd, "a2"))
604 else if (!strcmp(cmd, "b0"))
606 else if (!strcmp(cmd, "b1"))
608 else if (!strcmp(cmd, "b2"))
612 return config_filter(outlink, 0);
615 static av_cold void uninit(AVFilterContext *ctx)
617 BiquadsContext *s = ctx->priv;
622 static const AVFilterPad inputs[] = {
625 .type = AVMEDIA_TYPE_AUDIO,
626 .filter_frame = filter_frame,
631 static const AVFilterPad outputs[] = {
634 .type = AVMEDIA_TYPE_AUDIO,
635 .config_props = config_output,
640 #define OFFSET(x) offsetof(BiquadsContext, x)
641 #define FLAGS AV_OPT_FLAG_AUDIO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
643 #define DEFINE_BIQUAD_FILTER(name_, description_) \
644 AVFILTER_DEFINE_CLASS(name_); \
645 static av_cold int name_##_init(AVFilterContext *ctx) \
647 BiquadsContext *s = ctx->priv; \
648 s->class = &name_##_class; \
649 s->filter_type = name_; \
653 AVFilter ff_af_##name_ = { \
655 .description = NULL_IF_CONFIG_SMALL(description_), \
656 .priv_size = sizeof(BiquadsContext), \
657 .init = name_##_init, \
659 .query_formats = query_formats, \
661 .outputs = outputs, \
662 .priv_class = &name_##_class, \
663 .process_command = process_command, \
664 .flags = AVFILTER_FLAG_SLICE_THREADS | AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, \
667 #if CONFIG_EQUALIZER_FILTER
668 static const AVOption equalizer_options[] = {
669 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
670 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=0}, 0, 999999, FLAGS},
671 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
672 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
673 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
674 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
675 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
676 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
677 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
678 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
679 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 99999, FLAGS},
680 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
681 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
682 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
683 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
687 DEFINE_BIQUAD_FILTER(equalizer, "Apply two-pole peaking equalization (EQ) filter.");
688 #endif /* CONFIG_EQUALIZER_FILTER */
689 #if CONFIG_BASS_FILTER
690 static const AVOption bass_options[] = {
691 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
692 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
693 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
694 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
695 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
696 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
697 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
698 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
699 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
700 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
701 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
702 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
703 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
704 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
705 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
709 DEFINE_BIQUAD_FILTER(bass, "Boost or cut lower frequencies.");
710 #endif /* CONFIG_BASS_FILTER */
711 #if CONFIG_TREBLE_FILTER
712 static const AVOption treble_options[] = {
713 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
714 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
715 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
716 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
717 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
718 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
719 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
720 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
721 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
722 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
723 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
724 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
725 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
726 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
727 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
731 DEFINE_BIQUAD_FILTER(treble, "Boost or cut upper frequencies.");
732 #endif /* CONFIG_TREBLE_FILTER */
733 #if CONFIG_BANDPASS_FILTER
734 static const AVOption bandpass_options[] = {
735 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
736 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
737 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
738 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
739 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
740 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
741 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
742 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
743 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
744 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
745 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
746 {"csg", "use constant skirt gain", OFFSET(csg), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS},
747 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
748 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
752 DEFINE_BIQUAD_FILTER(bandpass, "Apply a two-pole Butterworth band-pass filter.");
753 #endif /* CONFIG_BANDPASS_FILTER */
754 #if CONFIG_BANDREJECT_FILTER
755 static const AVOption bandreject_options[] = {
756 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
757 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
758 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
759 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
760 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
761 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
762 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
763 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
764 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
765 {"width", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
766 {"w", "set band-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
767 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
768 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
772 DEFINE_BIQUAD_FILTER(bandreject, "Apply a two-pole Butterworth band-reject filter.");
773 #endif /* CONFIG_BANDREJECT_FILTER */
774 #if CONFIG_LOWPASS_FILTER
775 static const AVOption lowpass_options[] = {
776 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
777 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=500}, 0, 999999, FLAGS},
778 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
779 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
780 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
781 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
782 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
783 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
784 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
785 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
786 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
787 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
788 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
789 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
790 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
794 DEFINE_BIQUAD_FILTER(lowpass, "Apply a low-pass filter with 3dB point frequency.");
795 #endif /* CONFIG_LOWPASS_FILTER */
796 #if CONFIG_HIGHPASS_FILTER
797 static const AVOption highpass_options[] = {
798 {"frequency", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
799 {"f", "set frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
800 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
801 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
802 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
803 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
804 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
805 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
806 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
807 {"width", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
808 {"w", "set width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.707}, 0, 99999, FLAGS},
809 {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
810 {"p", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS},
811 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
812 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
816 DEFINE_BIQUAD_FILTER(highpass, "Apply a high-pass filter with 3dB point frequency.");
817 #endif /* CONFIG_HIGHPASS_FILTER */
818 #if CONFIG_ALLPASS_FILTER
819 static const AVOption allpass_options[] = {
820 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
821 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
822 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
823 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=HERTZ}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
824 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
825 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
826 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
827 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
828 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
829 {"width", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
830 {"w", "set filter-width", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=707.1}, 0, 99999, FLAGS},
831 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
832 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
836 DEFINE_BIQUAD_FILTER(allpass, "Apply a two-pole all-pass filter.");
837 #endif /* CONFIG_ALLPASS_FILTER */
838 #if CONFIG_LOWSHELF_FILTER
839 static const AVOption lowshelf_options[] = {
840 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
841 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=100}, 0, 999999, FLAGS},
842 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
843 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
844 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
845 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
846 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
847 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
848 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
849 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
850 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
851 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
852 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
853 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
854 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
858 DEFINE_BIQUAD_FILTER(lowshelf, "Apply a low shelf filter.");
859 #endif /* CONFIG_LOWSHELF_FILTER */
860 #if CONFIG_HIGHSHELF_FILTER
861 static const AVOption highshelf_options[] = {
862 {"frequency", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
863 {"f", "set central frequency", OFFSET(frequency), AV_OPT_TYPE_DOUBLE, {.dbl=3000}, 0, 999999, FLAGS},
864 {"width_type", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
865 {"t", "set filter-width type", OFFSET(width_type), AV_OPT_TYPE_INT, {.i64=QFACTOR}, HERTZ, NB_WTYPE-1, FLAGS, "width_type"},
866 {"h", "Hz", 0, AV_OPT_TYPE_CONST, {.i64=HERTZ}, 0, 0, FLAGS, "width_type"},
867 {"q", "Q-Factor", 0, AV_OPT_TYPE_CONST, {.i64=QFACTOR}, 0, 0, FLAGS, "width_type"},
868 {"o", "octave", 0, AV_OPT_TYPE_CONST, {.i64=OCTAVE}, 0, 0, FLAGS, "width_type"},
869 {"s", "slope", 0, AV_OPT_TYPE_CONST, {.i64=SLOPE}, 0, 0, FLAGS, "width_type"},
870 {"k", "kHz", 0, AV_OPT_TYPE_CONST, {.i64=KHERTZ}, 0, 0, FLAGS, "width_type"},
871 {"width", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
872 {"w", "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
873 {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
874 {"g", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
875 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
876 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
880 DEFINE_BIQUAD_FILTER(highshelf, "Apply a high shelf filter.");
881 #endif /* CONFIG_HIGHSHELF_FILTER */
882 #if CONFIG_BIQUAD_FILTER
883 static const AVOption biquad_options[] = {
884 {"a0", NULL, OFFSET(a0), AV_OPT_TYPE_DOUBLE, {.dbl=1}, INT32_MIN, INT32_MAX, FLAGS},
885 {"a1", NULL, OFFSET(a1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
886 {"a2", NULL, OFFSET(a2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
887 {"b0", NULL, OFFSET(b0), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
888 {"b1", NULL, OFFSET(b1), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
889 {"b2", NULL, OFFSET(b2), AV_OPT_TYPE_DOUBLE, {.dbl=0}, INT32_MIN, INT32_MAX, FLAGS},
890 {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
891 {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
895 DEFINE_BIQUAD_FILTER(biquad, "Apply a biquad IIR filter with the given coefficients.");
896 #endif /* CONFIG_BIQUAD_FILTER */