avfilter/af_anlmdn: use lut table to calculate weights
authorPaul B Mahol <onemda@gmail.com>
Thu, 10 Jan 2019 11:00:56 +0000 (12:00 +0100)
committerPaul B Mahol <onemda@gmail.com>
Thu, 10 Jan 2019 20:49:47 +0000 (21:49 +0100)
libavfilter/af_anlmdn.c

index 79c5ce0..6d9e89f 100644 (file)
 
 #include "af_anlmdndsp.h"
 
+#define MAX_DIFF         11.f
+#define WEIGHT_LUT_NBITS 20
+#define WEIGHT_LUT_SIZE  (1<<WEIGHT_LUT_NBITS)
+
 #define SQR(x) ((x) * (x))
 
 typedef struct AudioNLMeansContext {
@@ -38,6 +42,9 @@ typedef struct AudioNLMeansContext {
     int64_t pd;
     int64_t rd;
 
+    float pdiff_lut_scale;
+    float weight_lut[WEIGHT_LUT_SIZE];
+
     int K;
     int S;
     int N;
@@ -150,6 +157,13 @@ static int config_output(AVFilterLink *outlink)
     if (!s->fifo)
         return AVERROR(ENOMEM);
 
+    s->pdiff_lut_scale = 1.f / MAX_DIFF * WEIGHT_LUT_SIZE;
+    for (int i = 0; i < WEIGHT_LUT_SIZE; i++) {
+        float w = -i / s->pdiff_lut_scale;
+
+        s->weight_lut[i] = expf(w);
+    }
+
     ff_anlmdn_init(&s->dsp);
 
     return 0;
@@ -183,13 +197,16 @@ static int filter_channel(AVFilterContext *ctx, void *arg, int ch, int nb_jobs)
 
         for (int j = 0; j < 2 * S; j++) {
             const float distance = cache[j];
+            unsigned weight_lut_idx;
             float w;
 
-            av_assert0(distance >= 0.f);
-            w = -distance * sw;
-            if (w < -11.f)
+            av_assert2(distance >= 0.f);
+            w = distance * sw;
+            if (w >= MAX_DIFF)
                 continue;
-            w = expf(w);
+            weight_lut_idx = w * s->pdiff_lut_scale;
+            av_assert2(weight_lut_idx < WEIGHT_LUT_SIZE);
+            w = s->weight_lut[weight_lut_idx];
             P += w * f[i - S + j + (j >= S)];
             Q += w;
         }