]> git.sesse.net Git - ffmpeg/commitdiff
avfilter/af_biquads: add one-pole shelf filters by adding pole option
authorPaul B Mahol <onemda@gmail.com>
Wed, 16 Dec 2020 17:36:56 +0000 (18:36 +0100)
committerPaul B Mahol <onemda@gmail.com>
Wed, 16 Dec 2020 17:38:51 +0000 (18:38 +0100)
doc/filters.texi
libavfilter/af_biquads.c

index 62e34b99ee334ece748bee21c76814f5794863d0..8c291746bb3d11ae367abc058dc90be2743182cb 100644 (file)
@@ -3149,6 +3149,9 @@ kHz
 @item width, w
 Determine how steep is the filter's shelf transition.
 
+@item poles, p
+Set number of poles. Default is 2.
+
 @item mix, m
 How much to use filtered signal in output. Default is 1.
 Range is between 0 and 1.
@@ -6050,6 +6053,9 @@ kHz
 @item width, w
 Determine how steep is the filter's shelf transition.
 
+@item poles, p
+Set number of poles. Default is 2.
+
 @item mix, m
 How much to use filtered signal in output. Default is 1.
 Range is between 0 and 1.
index edefe15d052682605680ea2f7ac95666f04988aa..6e1da52fb3495ad8dfef6b4d81dda53ef03c87da 100644 (file)
@@ -514,22 +514,54 @@ static int config_filter(AVFilterLink *outlink, int reset)
     case bass:
         beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
     case lowshelf:
-        s->a0 =          (A + 1) + (A - 1) * cos(w0) + beta * alpha;
-        s->a1 =    -2 * ((A - 1) + (A + 1) * cos(w0));
-        s->a2 =          (A + 1) + (A - 1) * cos(w0) - beta * alpha;
-        s->b0 =     A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
-        s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
-        s->b2 =     A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
+        if (s->poles == 1) {
+            double A = ff_exp10(s->gain / 20);
+            double ro = -sin(w0 / 2. - M_PI_4 / (sin(w0 / 2. + M_PI_4)));
+            double n = (A + 1) / (A - 1);
+            double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1);
+            double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5;
+            double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5;
+
+            s->a0 = 1 + ro * alpha1;
+            s->a1 = -ro - alpha1;
+            s->a2 = 0;
+            s->b0 = beta0 + ro * beta1;
+            s->b1 = -beta1 - ro * beta0;
+            s->b2 = 0;
+        } else {
+            s->a0 =          (A + 1) + (A - 1) * cos(w0) + beta * alpha;
+            s->a1 =    -2 * ((A - 1) + (A + 1) * cos(w0));
+            s->a2 =          (A + 1) + (A - 1) * cos(w0) - beta * alpha;
+            s->b0 =     A * ((A + 1) - (A - 1) * cos(w0) + beta * alpha);
+            s->b1 = 2 * A * ((A - 1) - (A + 1) * cos(w0));
+            s->b2 =     A * ((A + 1) - (A - 1) * cos(w0) - beta * alpha);
+        }
         break;
     case treble:
         beta = sqrt((A * A + 1) - (A - 1) * (A - 1));
     case highshelf:
-        s->a0 =          (A + 1) - (A - 1) * cos(w0) + beta * alpha;
-        s->a1 =     2 * ((A - 1) - (A + 1) * cos(w0));
-        s->a2 =          (A + 1) - (A - 1) * cos(w0) - beta * alpha;
-        s->b0 =     A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
-        s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
-        s->b2 =     A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
+        if (s->poles == 1) {
+            double A = ff_exp10(s->gain / 20);
+            double ro = sin(w0 / 2. - M_PI_4 / (sin(w0 / 2. + M_PI_4)));
+            double n = (A + 1) / (A - 1);
+            double alpha1 = A == 1. ? 0. : n - FFSIGN(n) * sqrt(n * n - 1);
+            double beta0 = ((1 + A) + (1 - A) * alpha1) * 0.5;
+            double beta1 = ((1 - A) + (1 + A) * alpha1) * 0.5;
+
+            s->a0 = 1 + ro * alpha1;
+            s->a1 = ro + alpha1;
+            s->a2 = 0;
+            s->b0 = beta0 + ro * beta1;
+            s->b1 = beta1 + ro * beta0;
+            s->b2 = 0;
+        } else {
+            s->a0 =          (A + 1) - (A - 1) * cos(w0) + beta * alpha;
+            s->a1 =     2 * ((A - 1) - (A + 1) * cos(w0));
+            s->a2 =          (A + 1) - (A - 1) * cos(w0) - beta * alpha;
+            s->b0 =     A * ((A + 1) + (A - 1) * cos(w0) + beta * alpha);
+            s->b1 =-2 * A * ((A - 1) + (A + 1) * cos(w0));
+            s->b2 =     A * ((A + 1) + (A - 1) * cos(w0) - beta * alpha);
+        }
         break;
     case bandpass:
         if (s->csg) {
@@ -914,6 +946,8 @@ static const AVOption bass_options[] = {
     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
+    {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
+    {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
@@ -953,6 +987,8 @@ static const AVOption treble_options[] = {
     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
+    {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
+    {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
@@ -1184,6 +1220,8 @@ static const AVOption lowshelf_options[] = {
     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
+    {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
+    {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},
@@ -1223,6 +1261,8 @@ static const AVOption highshelf_options[] = {
     {"w",     "set shelf transition steep", OFFSET(width), AV_OPT_TYPE_DOUBLE, {.dbl=0.5}, 0, 99999, FLAGS},
     {"gain", "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
     {"g",    "set gain", OFFSET(gain), AV_OPT_TYPE_DOUBLE, {.dbl=0}, -900, 900, FLAGS},
+    {"poles", "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
+    {"p",     "set number of poles", OFFSET(poles), AV_OPT_TYPE_INT, {.i64=2}, 1, 2, AF},
     {"mix", "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"m",   "set mix", OFFSET(mix), AV_OPT_TYPE_DOUBLE, {.dbl=1}, 0, 1, FLAGS},
     {"channels", "set channels to filter", OFFSET(channels), AV_OPT_TYPE_CHANNEL_LAYOUT, {.i64=-1}, INT64_MIN, INT64_MAX, FLAGS},