lavfi/atempo: fix tempo range limit inconsistency
[ffmpeg.git] / libavfilter / af_anequalizer.c
index a437e2b..03d939f 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
-#include <complex.h>
-
 #include "libavutil/intreadwrite.h"
 #include "libavutil/avstring.h"
+#include "libavutil/ffmath.h"
 #include "libavutil/opt.h"
 #include "libavutil/parseutils.h"
 #include "avfilter.h"
@@ -114,13 +113,17 @@ static void draw_curves(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *out
             av_parse_color(fg, color, -1, ctx);
 
         for (f = 0; f < s->w; f++) {
-            double complex z;
-            double complex H = 1;
+            double zr, zi, zr2, zi2;
+            double Hr, Hi;
+            double Hmag = 1;
             double w;
             int v, y, x;
 
             w = M_PI * (s->fscale ? pow(s->w - 1, f / s->w) : f) / (s->w - 1);
-            z = 1. / cexp(I * w);
+            zr = cos(w);
+            zr2 = zr * zr;
+            zi = -sin(w);
+            zi2 = zi * zi;
 
             for (n = 0; n < s->nb_filters; n++) {
                 if (s->filters[n].channel != ch ||
@@ -130,12 +133,19 @@ static void draw_curves(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *out
                 for (i = 0; i < FILTER_ORDER / 2; i++) {
                     FoSection *S = &s->filters[n].section[i];
 
-                    H *= (((((S->b4 * z + S->b3) * z + S->b2) * z + S->b1) * z + S->b0) /
-                          ((((S->a4 * z + S->a3) * z + S->a2) * z + S->a1) * z + S->a0));
+                    /* H *= (((((S->b4 * z + S->b3) * z + S->b2) * z + S->b1) * z + S->b0) /
+                          ((((S->a4 * z + S->a3) * z + S->a2) * z + S->a1) * z + S->a0)); */
+
+                    Hr = S->b4*(1-8*zr2*zi2) + S->b2*(zr2-zi2) + zr*(S->b1+S->b3*(zr2-3*zi2))+ S->b0;
+                    Hi = zi*(S->b3*(3*zr2-zi2) + S->b1 + 2*zr*(2*S->b4*(zr2-zi2) + S->b2));
+                    Hmag *= hypot(Hr, Hi);
+                    Hr = S->a4*(1-8*zr2*zi2) + S->a2*(zr2-zi2) + zr*(S->a1+S->a3*(zr2-3*zi2))+ S->a0;
+                    Hi = zi*(S->a3*(3*zr2-zi2) + S->a1 + 2*zr*(2*S->a4*(zr2-zi2) + S->a2));
+                    Hmag /= hypot(Hr, Hi);
                 }
             }
 
-            v = av_clip((1. + -20 * log10(cabs(H)) / s->mag) * s->h / 2, 0, s->h - 1);
+            v = av_clip((1. + -20 * log10(Hmag) / s->mag) * s->h / 2, 0, s->h - 1);
             x = lrint(f);
             if (prev_v == -1)
                 prev_v = v;
@@ -179,6 +189,7 @@ static av_cold int init(AVFilterContext *ctx)
 {
     AudioNEqualizerContext *s = ctx->priv;
     AVFilterPad pad, vpad;
+    int ret;
 
     pad = (AVFilterPad){
         .name         = av_strdup("out0"),
@@ -198,10 +209,19 @@ static av_cold int init(AVFilterContext *ctx)
             return AVERROR(ENOMEM);
     }
 
-    ff_insert_outpad(ctx, 0, &pad);
+    ret = ff_insert_outpad(ctx, 0, &pad);
+    if (ret < 0) {
+        av_freep(&pad.name);
+        return ret;
+    }
 
-    if (s->draw_curves)
-        ff_insert_outpad(ctx, 1, &vpad);
+    if (s->draw_curves) {
+        ret = ff_insert_outpad(ctx, 1, &vpad);
+        if (ret < 0) {
+            av_freep(&vpad.name);
+            return ret;
+        }
+    }
 
     return 0;
 }
@@ -249,9 +269,8 @@ static av_cold void uninit(AVFilterContext *ctx)
 {
     AudioNEqualizerContext *s = ctx->priv;
 
-    av_freep(&ctx->output_pads[0].name);
-    if (s->draw_curves)
-        av_freep(&ctx->output_pads[1].name);
+    for (int i = 0; i < ctx->nb_outputs; i++)
+        av_freep(&ctx->output_pads[i].name);
     av_frame_free(&s->video);
     av_freep(&s->filters);
     s->nb_filters = 0;
@@ -307,9 +326,9 @@ static void butterworth_bp_filter(EqualizatorFilter *f,
         return;
     }
 
-    G  = exp10( G/20);
-    Gb = exp10(Gb/20);
-    G0 = exp10(G0/20);
+    G  = ff_exp10(G/20);
+    Gb = ff_exp10(Gb/20);
+    G0 = ff_exp10(G0/20);
 
     epsilon = sqrt((G * G - Gb * Gb) / (Gb * Gb - G0 * G0));
     g  = pow(G,  1.0 / N);
@@ -376,14 +395,14 @@ static void chebyshev1_bp_filter(EqualizatorFilter *f,
         return;
     }
 
-    G  = exp10( G/20);
-    Gb = exp10(Gb/20);
-    G0 = exp10(G0/20);
+    G  = ff_exp10(G/20);
+    Gb = ff_exp10(Gb/20);
+    G0 = ff_exp10(G0/20);
 
     epsilon = sqrt((G*G - Gb*Gb) / (Gb*Gb - G0*G0));
     g0 = pow(G0,1.0/N);
-    alfa = pow(1.0/epsilon    + sqrt(1 + pow(epsilon,-2.0)), 1.0/N);
-    beta = pow(G/epsilon + Gb * sqrt(1 + pow(epsilon,-2.0)), 1.0/N);
+    alfa = pow(1.0/epsilon    + sqrt(1 + 1/(epsilon*epsilon)), 1.0/N);
+    beta = pow(G/epsilon + Gb * sqrt(1 + 1/(epsilon*epsilon)), 1.0/N);
     a = 0.5 * (alfa - 1.0/alfa);
     b = 0.5 * (beta - g0*g0*(1/beta));
     tetta_b = tan(wb/2);
@@ -449,9 +468,9 @@ static void chebyshev2_bp_filter(EqualizatorFilter *f,
         return;
     }
 
-    G  = exp10( G/20);
-    Gb = exp10(Gb/20);
-    G0 = exp10(G0/20);
+    G  = ff_exp10(G/20);
+    Gb = ff_exp10(Gb/20);
+    G0 = ff_exp10(G0/20);
 
     epsilon = sqrt((G*G - Gb*Gb) / (Gb*Gb - G0*G0));
     g  = pow(G, 1.0 / N);
@@ -576,6 +595,7 @@ static int config_input(AVFilterLink *inlink)
     s->filters = av_calloc(inlink->channels, 32 * sizeof(*s->filters));
     if (!s->filters) {
         s->nb_allocated = 0;
+        av_free(args);
         return AVERROR(ENOMEM);
     }
 
@@ -600,14 +620,14 @@ static int config_input(AVFilterLink *inlink)
         }
 
         if (s->filters[s->nb_filters].freq < 0 ||
-            s->filters[s->nb_filters].freq > inlink->sample_rate / 2)
+            s->filters[s->nb_filters].freq > inlink->sample_rate / 2.0)
             s->filters[s->nb_filters].ignore = 1;
 
         if (s->filters[s->nb_filters].channel < 0 ||
             s->filters[s->nb_filters].channel >= inlink->channels)
             s->filters[s->nb_filters].ignore = 1;
 
-        av_clip(s->filters[s->nb_filters].type, 0, NB_TYPES - 1);
+        s->filters[s->nb_filters].type = av_clip(s->filters[s->nb_filters].type, 0, NB_TYPES - 1);
         ret = add_filter(s, inlink);
         if (ret < 0)
             break;
@@ -635,7 +655,7 @@ static int process_command(AVFilterContext *ctx, const char *cmd, const char *ar
         if (filter < 0 || filter >= s->nb_filters)
             return AVERROR(EINVAL);
 
-        if (freq < 0 || freq > inlink->sample_rate / 2)
+        if (freq < 0 || freq > inlink->sample_rate / 2.0)
             return AVERROR(EINVAL);
 
         s->filters[filter].freq  = freq;