[FFmpeg-cvslog] avfilter/af_aiir: add polar zeros/poles format variant

Paul B Mahol git at videolan.org
Wed Jan 10 21:30:48 EET 2018


ffmpeg | branch: master | Paul B Mahol <onemda at gmail.com> | Wed Jan 10 20:25:50 2018 +0100| [de8a1d8d4d0bbcb4c8500965ea8611bf754c4321] | committer: Paul B Mahol

avfilter/af_aiir: add polar zeros/poles format variant

Signed-off-by: Paul B Mahol <onemda at gmail.com>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=de8a1d8d4d0bbcb4c8500965ea8611bf754c4321
---

 doc/filters.texi      | 15 ++++++++--
 libavfilter/af_aiir.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 83 insertions(+), 10 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index a52f6ff578..618eb28e28 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -1084,8 +1084,17 @@ Set output gain.
 
 @item f
 Set coefficients format.
-Can be @code{tf} - transfer function or @code{zp} - Z-plane zeros/poles.
-Default is @code{zp}.
+
+ at table @samp
+ at item tf
+transfer function
+ at item zp
+Z-plane zeros/poles, cartesian (default)
+ at item zpr
+Z-plane zeros/poles, polar radians
+ at item zpd
+Z-plane zeros/poles, polar degrees
+ at end table
 
 @item r
 Set kind of processing.
@@ -1094,7 +1103,7 @@ Can be @code{d} - direct or @code{s} - serial cascading. Defauls is @code{s}.
 @item e
 Set filtering precision.
 
- at table @option
+ at table @samp
 @item dbl
 double-precision floating-point (default)
 @item flt
diff --git a/libavfilter/af_aiir.c b/libavfilter/af_aiir.c
index 46b1c7e698..1f2a568c1d 100644
--- a/libavfilter/af_aiir.c
+++ b/libavfilter/af_aiir.c
@@ -283,7 +283,7 @@ static int read_tf_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite
     return 0;
 }
 
-static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst)
+static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_items, double *dst, const char *format)
 {
     char *p, *arg, *old_str, *saveptr = NULL;
     int i;
@@ -296,7 +296,7 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite
             break;
 
         p = NULL;
-        if (sscanf(arg, "%lf %lfi", &dst[i*2], &dst[i*2+1]) != 2) {
+        if (sscanf(arg, format, &dst[i*2], &dst[i*2+1]) != 2) {
             av_log(ctx, AV_LOG_ERROR, "Invalid coefficients supplied: %s\n", arg);
             av_freep(&old_str);
             return AVERROR(EINVAL);
@@ -308,6 +308,8 @@ static int read_zp_coefficients(AVFilterContext *ctx, char *item_str, int nb_ite
     return 0;
 }
 
+static const char *format[] = { "%lf", "%lf %lfi", "%lf %lfr", "%lf %lfd" };
+
 static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str, int ab)
 {
     AudioIIRContext *s = ctx->priv;
@@ -332,14 +334,14 @@ static int read_channels(AVFilterContext *ctx, int channels, uint8_t *item_str,
 
         p = NULL;
         iir->cache[ab] = av_calloc(iir->nb_ab[ab] + 1, sizeof(double));
-        iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (s->format + 1), sizeof(double));
+        iir->ab[ab] = av_calloc(iir->nb_ab[ab] * (!!s->format + 1), sizeof(double));
         if (!iir->ab[ab] || !iir->cache[ab]) {
             av_freep(&old_str);
             return AVERROR(ENOMEM);
         }
 
         if (s->format) {
-            ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]);
+            ret = read_zp_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab], format[s->format]);
         } else {
             ret = read_tf_coefficients(ctx, arg, iir->nb_ab[ab], iir->ab[ab]);
         }
@@ -586,6 +588,60 @@ static int decompose_zp2biquads(AVFilterContext *ctx, int channels)
     return 0;
 }
 
+static void convert_pr2zp(AVFilterContext *ctx, int channels)
+{
+    AudioIIRContext *s = ctx->priv;
+    int ch;
+
+    for (ch = 0; ch < channels; ch++) {
+        IIRChannel *iir = &s->iir[ch];
+        int n;
+
+        for (n = 0; n < iir->nb_ab[0]; n++) {
+            double r = iir->ab[0][2*n];
+            double angle = iir->ab[0][2*n+1];
+
+            iir->ab[0][2*n]   = r * cos(angle);
+            iir->ab[0][2*n+1] = r * sin(angle);
+        }
+
+        for (n = 0; n < iir->nb_ab[1]; n++) {
+            double r = iir->ab[1][2*n];
+            double angle = iir->ab[1][2*n+1];
+
+            iir->ab[1][2*n]   = r * cos(angle);
+            iir->ab[1][2*n+1] = r * sin(angle);
+        }
+    }
+}
+
+static void convert_pd2zp(AVFilterContext *ctx, int channels)
+{
+    AudioIIRContext *s = ctx->priv;
+    int ch;
+
+    for (ch = 0; ch < channels; ch++) {
+        IIRChannel *iir = &s->iir[ch];
+        int n;
+
+        for (n = 0; n < iir->nb_ab[0]; n++) {
+            double r = iir->ab[0][2*n];
+            double angle = M_PI*iir->ab[0][2*n+1]/180.;
+
+            iir->ab[0][2*n]   = r * cos(angle);
+            iir->ab[0][2*n+1] = r * sin(angle);
+        }
+
+        for (n = 0; n < iir->nb_ab[1]; n++) {
+            double r = iir->ab[1][2*n];
+            double angle = M_PI*iir->ab[1][2*n+1]/180.;
+
+            iir->ab[1][2*n]   = r * cos(angle);
+            iir->ab[1][2*n+1] = r * sin(angle);
+        }
+    }
+}
+
 static int config_output(AVFilterLink *outlink)
 {
     AVFilterContext *ctx = outlink->src;
@@ -610,10 +666,16 @@ static int config_output(AVFilterLink *outlink)
     if (ret < 0)
         return ret;
 
+    if (s->format == 2) {
+        convert_pr2zp(ctx, inlink->channels);
+    } else if (s->format == 3) {
+        convert_pd2zp(ctx, inlink->channels);
+    }
+
     if (s->format == 0)
         av_log(ctx, AV_LOG_WARNING, "tf coefficients format is not recommended for too high number of zeros/poles.\n");
 
-    if (s->format == 1 && s->process == 0) {
+    if (s->format > 0 && s->process == 0) {
         av_log(ctx, AV_LOG_WARNING, "Direct processsing is not recommended for zp coefficients format.\n");
 
         ret = convert_zp2tf(ctx, inlink->channels);
@@ -622,7 +684,7 @@ static int config_output(AVFilterLink *outlink)
     } else if (s->format == 0 && s->process == 1) {
         av_log(ctx, AV_LOG_ERROR, "Serial cascading is not implemented for transfer function.\n");
         return AVERROR_PATCHWELCOME;
-    } else if (s->format == 1 && s->process == 1) {
+    } else if (s->format > 0 && s->process == 1) {
         if (inlink->format == AV_SAMPLE_FMT_S16P)
             av_log(ctx, AV_LOG_WARNING, "Serial cascading is not recommended for i16 precision.\n");
 
@@ -755,9 +817,11 @@ static const AVOption aiir_options[] = {
     { "k", "set channels gains",                   OFFSET(g_str),    AV_OPT_TYPE_STRING, {.str="1|1"}, 0, 0, AF },
     { "dry", "set dry gain",                       OFFSET(dry_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1},     0, 1, AF },
     { "wet", "set wet gain",                       OFFSET(wet_gain), AV_OPT_TYPE_DOUBLE, {.dbl=1},     0, 1, AF },
-    { "f", "set coefficients format",              OFFSET(format),   AV_OPT_TYPE_INT,    {.i64=1},     0, 1, AF, "format" },
+    { "f", "set coefficients format",              OFFSET(format),   AV_OPT_TYPE_INT,    {.i64=1},     0, 3, AF, "format" },
     { "tf", "transfer function",                   0,                AV_OPT_TYPE_CONST,  {.i64=0},     0, 0, AF, "format" },
     { "zp", "Z-plane zeros/poles",                 0,                AV_OPT_TYPE_CONST,  {.i64=1},     0, 0, AF, "format" },
+    { "pr", "Z-plane zeros/poles (polar radians)", 0,                AV_OPT_TYPE_CONST,  {.i64=2},     0, 0, AF, "format" },
+    { "pd", "Z-plane zeros/poles (polar degrees)", 0,                AV_OPT_TYPE_CONST,  {.i64=3},     0, 0, AF, "format" },
     { "r", "set kind of processing",               OFFSET(process),  AV_OPT_TYPE_INT,    {.i64=1},     0, 1, AF, "process" },
     { "d", "direct",                               0,                AV_OPT_TYPE_CONST,  {.i64=0},     0, 0, AF, "process" },
     { "s", "serial cascading",                     0,                AV_OPT_TYPE_CONST,  {.i64=1},     0, 0, AF, "process" },



More information about the ffmpeg-cvslog mailing list