diff --git a/doc/filters.texi b/doc/filters.texi index 85a511b2056ffeb7645d241cff79ddcbbf968194..5af4797b7ec6f0a57afd12bf908e87feba1b1525 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -1568,6 +1568,9 @@ Specify which channels to filter, by default all available are filtered. @item normalize, n Normalize biquad coefficients, by default is disabled. Enabling it will normalize magnitude response at DC to 0dB. + +@item order, o +Set the filter order, can be 1 or 2. Default is 2. @end table @subsection Commands diff --git a/libavfilter/af_biquads.c b/libavfilter/af_biquads.c index a2f7e3f0610392a84f635e5a52375f09fb72e7c5..81cdb0c10e9039b3f800e39684fc1f340827c01c 100644 --- a/libavfilter/af_biquads.c +++ b/libavfilter/af_biquads.c @@ -113,6 +113,7 @@ typedef struct BiquadsContext { double mix; uint64_t channels; int normalize; + int order; double a0, a1, a2; double b0, b1, b2; @@ -264,6 +265,7 @@ static int config_filter(AVFilterLink *outlink, int reset) AVFilterLink *inlink = ctx->inputs[0]; double A = ff_exp10(s->gain / 40); double w0 = 2 * M_PI * s->frequency / inlink->sample_rate; + double K = tan(w0 / 2.); double alpha, beta; if (w0 > M_PI) { @@ -389,12 +391,24 @@ static int config_filter(AVFilterLink *outlink, int reset) } break; case allpass: - s->a0 = 1 + alpha; - s->a1 = -2 * cos(w0); - s->a2 = 1 - alpha; - s->b0 = 1 - alpha; - s->b1 = -2 * cos(w0); - s->b2 = 1 + alpha; + switch (s->order) { + case 1: + s->a0 = 1.; + s->a1 = -(1. - K) / (1. + K); + s->a2 = 0.; + s->b0 = s->a1; + s->b1 = s->a0; + s->b2 = 0.; + break; + case 2: + s->a0 = 1 + alpha; + s->a1 = -2 * cos(w0); + s->a2 = 1 - alpha; + s->b0 = 1 - alpha; + s->b1 = -2 * cos(w0); + s->b2 = 1 + alpha; + break; + } break; default: av_assert0(0); @@ -773,6 +787,8 @@ static const AVOption allpass_options[] = { {"c", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS}, {"normalize", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, {"n", "normalize coefficients", OFFSET(normalize), AV_OPT_TYPE_BOOL, {.i64=0}, 0, 1, FLAGS}, + {"order", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, + {"o", "set filter order", OFFSET(order), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, FLAGS}, {NULL} };