Add function ff_iir_filter_flt() to accept floating-point input and output.
authorJustin Ruggles <justin.ruggles@gmail.com>
Thu, 20 Jan 2011 17:24:06 +0000 (17:24 +0000)
committerMichael Niedermayer <michaelni@gmx.at>
Fri, 21 Jan 2011 19:36:00 +0000 (20:36 +0100)
Signed-off-by: Mans Rullgard <mans@mansr.com>
(cherry picked from commit 0a3d7697b4fcb62305cd4a893b621a406a029ff0)

libavcodec/iirfilter.c
libavcodec/iirfilter.h

index 65d9f89..e37fd81 100644 (file)
@@ -118,48 +118,74 @@ av_cold struct FFIIRFilterState* ff_iir_filter_init_state(int order)
     return s;
 }
 
-#define FILTER(i0, i1, i2, i3)                    \
-    in =   *src * c->gain                         \
-         + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1]  \
-         + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3]; \
-    res =  (s->x[i0] + in      )*1                \
-         + (s->x[i1] + s->x[i3])*4                \
-         +  s->x[i2]            *6;               \
-    *dst = av_clip_int16(lrintf(res));            \
-    s->x[i0] = in;                                \
-    src += sstep;                                 \
-    dst += dstep;                                 \
+#define CONV_S16(dest, source) dest = av_clip_int16(lrintf(source));
+
+#define CONV_FLT(dest, source) dest = source;
+
+#define FILTER_BW_O4_1(i0, i1, i2, i3, fmt)         \
+    in = *src0 * c->gain                            \
+         + c->cy[0]*s->x[i0] + c->cy[1]*s->x[i1]    \
+         + c->cy[2]*s->x[i2] + c->cy[3]*s->x[i3];   \
+    res =  (s->x[i0] + in      )*1                  \
+         + (s->x[i1] + s->x[i3])*4                  \
+         +  s->x[i2]            *6;                 \
+    CONV_##fmt(*dst0, res)                          \
+    s->x[i0] = in;                                  \
+    src0 += sstep;                                  \
+    dst0 += dstep;
+
+#define FILTER_BW_O4(type, fmt) {           \
+    int i;                                  \
+    const type *src0 = src;                 \
+    type       *dst0 = dst;                 \
+    for (i = 0; i < size; i += 4) {         \
+        float in, res;                      \
+        FILTER_BW_O4_1(0, 1, 2, 3, fmt);    \
+        FILTER_BW_O4_1(1, 2, 3, 0, fmt);    \
+        FILTER_BW_O4_1(2, 3, 0, 1, fmt);    \
+        FILTER_BW_O4_1(3, 0, 1, 2, fmt);    \
+    }                                       \
+}
+
+#define FILTER_DIRECT_FORM_II(type, fmt) {                                  \
+    int i;                                                                  \
+    const type *src0 = src;                                                 \
+    type       *dst0 = dst;                                                 \
+    for (i = 0; i < size; i++) {                                            \
+        int j;                                                              \
+        float in, res;                                                      \
+        in = *src0 * c->gain;                                               \
+        for(j = 0; j < c->order; j++)                                       \
+            in += c->cy[j] * s->x[j];                                       \
+        res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1];    \
+        for(j = 1; j < c->order >> 1; j++)                                  \
+            res += (s->x[j] + s->x[c->order - j]) * c->cx[j];               \
+        for(j = 0; j < c->order - 1; j++)                                   \
+            s->x[j] = s->x[j + 1];                                          \
+        CONV_##fmt(*dst0, res)                                              \
+        s->x[c->order - 1] = in;                                            \
+        src0 += sstep;                                                      \
+        dst0 += dstep;                                                      \
+    }                                                                       \
+}
 
 void ff_iir_filter(const struct FFIIRFilterCoeffs *c, struct FFIIRFilterState *s, int size, const int16_t *src, int sstep, int16_t *dst, int dstep)
 {
-    int i;
-
-    if(c->order == 4){
-        for(i = 0; i < size; i += 4){
-            float in, res;
+    if (c->order == 4) {
+        FILTER_BW_O4(int16_t, S16)
+    } else {
+        FILTER_DIRECT_FORM_II(int16_t, S16)
+    }
+}
 
-            FILTER(0, 1, 2, 3);
-            FILTER(1, 2, 3, 0);
-            FILTER(2, 3, 0, 1);
-            FILTER(3, 0, 1, 2);
-        }
-    }else{
-        for(i = 0; i < size; i++){
-            int j;
-            float in, res;
-            in = *src * c->gain;
-            for(j = 0; j < c->order; j++)
-                in += c->cy[j] * s->x[j];
-            res = s->x[0] + in + s->x[c->order >> 1] * c->cx[c->order >> 1];
-            for(j = 1; j < c->order >> 1; j++)
-                res += (s->x[j] + s->x[c->order - j]) * c->cx[j];
-            for(j = 0; j < c->order - 1; j++)
-                s->x[j] = s->x[j + 1];
-            *dst = av_clip_int16(lrintf(res));
-            s->x[c->order - 1] = in;
-            src += sstep;
-            dst += dstep;
-        }
+void ff_iir_filter_flt(const struct FFIIRFilterCoeffs *c,
+                       struct FFIIRFilterState *s, int size,
+                       const float *src, int sstep, void *dst, int dstep)
+{
+    if (c->order == 4) {
+        FILTER_BW_O4(float, FLT)
+    } else {
+        FILTER_DIRECT_FORM_II(float, FLT)
     }
 }
 
index f660955..fd26166 100644 (file)
@@ -87,7 +87,7 @@ void ff_iir_filter_free_coeffs(struct FFIIRFilterCoeffs *coeffs);
 void ff_iir_filter_free_state(struct FFIIRFilterState *state);
 
 /**
- * Perform lowpass filtering on input samples.
+ * Perform IIR filtering on signed 16-bit input samples.
  *
  * @param coeffs pointer to filter coefficients
  * @param state  pointer to filter state
@@ -100,4 +100,19 @@ void ff_iir_filter_free_state(struct FFIIRFilterState *state);
 void ff_iir_filter(const struct FFIIRFilterCoeffs *coeffs, struct FFIIRFilterState *state,
                    int size, const int16_t *src, int sstep, int16_t *dst, int dstep);
 
+/**
+ * Perform IIR filtering on floating-point input samples.
+ *
+ * @param coeffs pointer to filter coefficients
+ * @param state  pointer to filter state
+ * @param size   input length
+ * @param src    source samples
+ * @param sstep  source stride
+ * @param dst    filtered samples (destination may be the same as input)
+ * @param dstep  destination stride
+ */
+void ff_iir_filter_flt(const struct FFIIRFilterCoeffs *coeffs,
+                       struct FFIIRFilterState *state, int size,
+                       const float *src, int sstep, void *dst, int dstep);
+
 #endif /* AVCODEC_IIRFILTER_H */