[FFmpeg-soc] [soc]: r3191 - in aacenc: aacpsy.c aacpsy.h lowpass.c lowpass.h

kostya subversion at mplayerhq.hu
Tue Aug 12 13:33:34 CEST 2008


Author: kostya
Date: Tue Aug 12 13:33:34 2008
New Revision: 3191

Log:
Move lowpass filter into separate module.
(and no, I don't think it's useful to use svn copy here)


Added:
   aacenc/lowpass.c
   aacenc/lowpass.h
Modified:
   aacenc/aacpsy.c
   aacenc/aacpsy.h

Modified: aacenc/aacpsy.c
==============================================================================
--- aacenc/aacpsy.c	(original)
+++ aacenc/aacpsy.c	Tue Aug 12 13:33:34 2008
@@ -854,51 +854,6 @@ static const AACPsyModel psy_models[AAC_
     },
 };
 
-// low-pass filter declarations and code
-#define IIR_ORDER 4
-
-/**
- * filter data for 4th order IIR lowpass Butterworth filter
- *
- * data format:
- * normalized cutoff frequency | inverse filter gain | coefficients
- */
-static const float lp_filter_data[][IIR_ORDER+2] = {
-    { 0.4535147392, 6.816645e-01, -0.4646665999, -2.2127207402, -3.9912017501, -3.2380429984 },
-    { 0.4166666667, 4.998150e-01, -0.2498216698, -1.3392807613, -2.7693097862, -2.6386277439 },
-    { 0.3628117914, 3.103469e-01, -0.0965076902, -0.5977763360, -1.4972580903, -1.7740085241 },
-    { 0.3333333333, 2.346995e-01, -0.0557639007, -0.3623690447, -1.0304538354, -1.3066051440 },
-    { 0.2916666667, 1.528432e-01, -0.0261686639, -0.1473794606, -0.6204721225, -0.6514716536 },
-    { 0.2267573696, 6.917529e-02, -0.0202414073,  0.0780167640, -0.5277442247,  0.3631641670 },
-    { 0.2187500000, 6.178391e-02, -0.0223681543,  0.1069446609, -0.5615167033,  0.4883976841 },
-    { 0.2083333333, 5.298685e-02, -0.0261686639,  0.1473794606, -0.6204721225,  0.6514716536 },
-    { 0.1587301587, 2.229030e-02, -0.0647354087,  0.4172275190, -1.1412129810,  1.4320761385 },
-    { 0.1458333333, 1.693903e-02, -0.0823177861,  0.5192354923, -1.3444768251,  1.6365345642 },
-    { 0.1133786848, 7.374053e-03, -0.1481421788,  0.8650973862, -1.9894244796,  2.1544844308 },
-    { 0.1041666667, 5.541768e-03, -0.1742301048,  0.9921936565, -2.2090801108,  2.3024482658 },
-};
-
-/**
- * IIR filter state
- */
-typedef struct LPFilterState{
-    float x[IIR_ORDER + 1];
-    float y[IIR_ORDER + 1];
-}LPFilterState;
-
-static av_always_inline float lowpass_iir_filter(LPFilterState *s, const float *coeffs, float in)
-{
-    memmove(s->x, s->x + 1, sizeof(s->x) - sizeof(s->x[0]));
-    memmove(s->y, s->y + 1, sizeof(s->y) - sizeof(s->y[0]));
-    s->x[IIR_ORDER] = in * coeffs[1];
-    //FIXME: made only for 4th order filter
-    s->y[IIR_ORDER] = (s->x[0] + s->x[4])*1 + (s->x[1] + s->x[3])*4 + s->x[2]*6
-                    + coeffs[2]*s->y[0] + coeffs[3]*s->y[1] + coeffs[4]*s->y[2] + coeffs[5]*s->y[3];
-    return s->y[IIR_ORDER];
-}
-
-// low-pass filter code ends here
-
 int av_cold ff_aac_psy_init(AACPsyContext *ctx, AVCodecContext *avctx,
                             enum AACPsyModelType model, int elements, int flags,
                             const uint8_t *bands1024, int num_bands1024,
@@ -930,23 +885,13 @@ int av_cold ff_aac_psy_init(AACPsyContex
     }
     if(ctx->flags & PSY_MODEL_NO_LOWPASS || PSY_MODEL_MODE(ctx->flags) == PSY_MODE_QUALITY){
         ctx->flags |= PSY_MODEL_NO_LOWPASS;
-        ctx->cutoff = 0;
     }else{
-        float cutoff_ratio;
-        cutoff_ratio = avctx->bit_rate / elements / 8.0 / avctx->sample_rate;
-        ctx->cutoff = -1;
-        if(cutoff_ratio >= 0.5f){
+        int cutoff;
+        cutoff = avctx->bit_rate / elements / 8;
+        if(ff_lowpass_filter_init_coeffs(&ctx->lp_coeffs, avctx->sample_rate/2, cutoff) < 0){
             ctx->flags |= PSY_MODEL_NO_LOWPASS;
         }else{
             ctx->lp_state = av_mallocz(sizeof(LPFilterState) * elements * 2);
-            for(i = 0; i < sizeof(lp_filter_data)/sizeof(lp_filter_data[0]); i++){
-                if(lp_filter_data[i][0] <= cutoff_ratio){
-                    ctx->cutoff = i;
-                    break;
-                }
-            }
-            if(ctx->cutoff == -1)
-                ctx->cutoff = i-1;
         }
     }
     if(ctx->model->init)
@@ -996,7 +941,7 @@ void ff_aac_psy_preprocess(AACPsyContext
             if(!(ctx->flags & PSY_MODEL_NO_LOWPASS)){
                 LPFilterState *is = (LPFilterState*)ctx->lp_state + tag*2;
                 for(ch = 0; ch < 2; ch++)
-                    t[ch] = lowpass_iir_filter(is + ch, lp_filter_data[ctx->cutoff], t[ch]);
+                    t[ch] = ff_lowpass_filter(&ctx->lp_coeffs, is + ch, t[ch]);
             }
             for(ch = 0; ch < 2; ch++)
                 dest[i * chstride + ch] = av_clip_int16(t[ch]);

Modified: aacenc/aacpsy.h
==============================================================================
--- aacenc/aacpsy.h	(original)
+++ aacenc/aacpsy.h	Tue Aug 12 13:33:34 2008
@@ -24,6 +24,7 @@
 
 #include "avcodec.h"
 #include "aac.h"
+#include "lowpass.h"
 
 enum AACPsyModelType{
     AAC_PSY_NULL,              ///< do nothing with frequencies
@@ -65,8 +66,8 @@ typedef struct AACPsyContext {
     void* model_priv_data;            ///< psychoacoustic model implementation private data
 
     float stereo_att;                 ///< stereo attenuation factor
-    int   cutoff;                     ///< cutoff frequency index used for lowpass filtering
-    void* lp_state;                   ///< lowpass filter state
+    LPFilterCoeffs lp_coeffs;         ///< lowpass filter coefficients
+    LPFilterState *lp_state;          ///< lowpass filter state
 }AACPsyContext;
 
 typedef struct AACPsyModel {

Added: aacenc/lowpass.c
==============================================================================
--- (empty file)
+++ aacenc/lowpass.c	Tue Aug 12 13:33:34 2008
@@ -0,0 +1,73 @@
+/*
+ * Lowpass IIR filter
+ * Copyright (c) 2008 Konstantin Shishkov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file lowpass.c
+ * lowpass filter implementation
+ */
+
+#include "lowpass.h"
+
+/**
+ * filter data for 4th order IIR lowpass Butterworth filter
+ *
+ * data format:
+ * normalized cutoff frequency | inverse filter gain | coefficients
+ */
+static const float lp_filter_data[][LOWPASS_FILTER_ORDER+2] = {
+    { 0.5000000000, 9.398085e-01, -0.0176648009,  0.0000000000, -0.4860288221,  0.0000000000 },
+    { 0.4535147392, 6.816645e-01, -0.4646665999, -2.2127207402, -3.9912017501, -3.2380429984 },
+    { 0.4166666667, 4.998150e-01, -0.2498216698, -1.3392807613, -2.7693097862, -2.6386277439 },
+    { 0.3628117914, 3.103469e-01, -0.0965076902, -0.5977763360, -1.4972580903, -1.7740085241 },
+    { 0.3333333333, 2.346995e-01, -0.0557639007, -0.3623690447, -1.0304538354, -1.3066051440 },
+    { 0.2916666667, 1.528432e-01, -0.0261686639, -0.1473794606, -0.6204721225, -0.6514716536 },
+    { 0.2267573696, 6.917529e-02, -0.0202414073,  0.0780167640, -0.5277442247,  0.3631641670 },
+    { 0.2187500000, 6.178391e-02, -0.0223681543,  0.1069446609, -0.5615167033,  0.4883976841 },
+    { 0.2083333333, 5.298685e-02, -0.0261686639,  0.1473794606, -0.6204721225,  0.6514716536 },
+    { 0.1587301587, 2.229030e-02, -0.0647354087,  0.4172275190, -1.1412129810,  1.4320761385 },
+    { 0.1458333333, 1.693903e-02, -0.0823177861,  0.5192354923, -1.3444768251,  1.6365345642 },
+    { 0.1133786848, 7.374053e-03, -0.1481421788,  0.8650973862, -1.9894244796,  2.1544844308 },
+    { 0.1041666667, 5.541768e-03, -0.1742301048,  0.9921936565, -2.2090801108,  2.3024482658 },
+};
+
+int ff_lowpass_filter_init_coeffs(LPFilterCoeffs *coeffs, int freq, int cutoff)
+{
+    int i, j, size;
+    float cutoff_ratio;
+
+    //since I'm too lazy to calculate coefficients, I take more or less matching ones from the table
+    //TODO: generic version
+    size = sizeof(lp_filter_data) / sizeof(lp_filter_data[0]);
+    cutoff_ratio = (float)cutoff / freq;
+    if(cutoff_ratio > lp_filter_data[0][0])
+        return -1;
+    for(i = 0; i < size; i++){
+        if(cutoff_ratio >= lp_filter_data[i][0])
+            break;
+    }
+    if(i == size)
+        i = size - 1;
+    coeffs->gain     = lp_filter_data[i][1];
+    for(j = 0; j < 4; j++)
+        coeffs->c[j] = lp_filter_data[i][j+2];
+    return 0;
+}
+

Added: aacenc/lowpass.h
==============================================================================
--- (empty file)
+++ aacenc/lowpass.h	Tue Aug 12 13:33:34 2008
@@ -0,0 +1,89 @@
+/*
+ * Lowpass IIR filter
+ * Copyright (c) 2008 Konstantin Shishkov
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file lowpass.h
+ * lowpass filter interface
+ */
+
+#ifndef FFMPEG_LOWPASS_H
+#define FFMPEG_LOWPASS_H
+
+#include "avcodec.h"
+
+/** filter order */
+#define LOWPASS_FILTER_ORDER 4
+
+/**
+ * IIR filter global parameters
+ */
+typedef struct LPFilterCoeffs{
+    float gain;
+    float c[LOWPASS_FILTER_ORDER];
+}LPFilterCoeffs;
+
+/**
+ * IIR filter state
+ */
+typedef struct LPFilterState{
+    float x[LOWPASS_FILTER_ORDER + 1];
+    float y[LOWPASS_FILTER_ORDER + 1];
+}LPFilterState;
+
+/**
+ * Initialize filter coefficients.
+ *
+ * @param coeffs filter coefficients
+ * @param freq   input frequency (sample rate/2)
+ * @param cutoff cutoff frequency
+ *
+ * @return zero if filter creation succeeded, a negative value if filter could not be created
+ */
+int ff_lowpass_filter_init_coeffs(LPFilterCoeffs *coeffs, int freq, int cutoff);
+
+/**
+ * Filter input value.
+ *
+ * @param coeffs filter coefficients
+ * @param s      filter state
+ * @param in     input value
+ *
+ * @return filtered value
+ */
+static av_always_inline float ff_lowpass_filter(LPFilterCoeffs *coeffs, LPFilterState *s, float in)
+{
+    int i;
+    for(i = 0; i < LOWPASS_FILTER_ORDER; i++){
+        s->x[i] = s->x[i+1];
+        s->y[i] = s->y[i+1];
+    }
+    s->x[LOWPASS_FILTER_ORDER] = in * coeffs->gain;
+    //FIXME: made only for 4th order filter
+    s->y[LOWPASS_FILTER_ORDER] = (s->x[0] + s->x[4])*1
+                               + (s->x[1] + s->x[3])*4
+                               +  s->x[2]           *6
+                               + coeffs->c[0]*s->y[0] + coeffs->c[1]*s->y[1]
+                               + coeffs->c[2]*s->y[2] + coeffs->c[3]*s->y[3];
+    return s->y[LOWPASS_FILTER_ORDER];
+}
+
+#endif /* FFMPEG_LOWPASS_H */
+



More information about the FFmpeg-soc mailing list