[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