[FFmpeg-soc] [soc]: r3610 - in aacenc: aacpsy.c aacpsy.h lowpass.c lowpass.h
kostya
subversion at mplayerhq.hu
Mon Aug 25 16:14:54 CEST 2008
Author: kostya
Date: Mon Aug 25 16:14:54 2008
New Revision: 3610
Log:
Update lowpass filter to my newest code and change psy models to follow new filter API
Modified:
aacenc/aacpsy.c
aacenc/aacpsy.h
aacenc/lowpass.c
aacenc/lowpass.h
Modified: aacenc/aacpsy.c
==============================================================================
--- aacenc/aacpsy.c (original)
+++ aacenc/aacpsy.c Mon Aug 25 16:14:54 2008
@@ -763,14 +763,17 @@ 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;
}else{
- int cutoff;
- cutoff = avctx->bit_rate / elements / 8;
- if(ff_lowpass_filter_init_coeffs(&ctx->lp_coeffs, avctx->sample_rate/2, cutoff) < 0){
+ float cutoff = (float)avctx->bit_rate / elements / 8 / avctx->sample_rate;
+ ctx->lp_coeffs = ff_lowpass_filter_init_coeffs(4, cutoff);
+ if(!ctx->lp_coeffs){
ctx->flags |= PSY_MODEL_NO_LOWPASS;
}else{
- ctx->lp_state = av_mallocz(sizeof(LPFilterState) * elements * 2);
+ ctx->lp_state = av_malloc(sizeof(struct FFLPFilterState*) * elements * 2);
+ for(i = 0; i < elements*2; i++)
+ ctx->lp_state[i] = ff_lowpass_filter_init_state(4);
}
}
+ ctx->elements = elements;
if(ctx->model->init)
return ctx->model->init(ctx, elements);
return 0;
@@ -789,7 +792,13 @@ void ff_aac_psy_analyze(AACPsyContext *c
void av_cold ff_aac_psy_end(AACPsyContext *ctx)
{
- av_freep(&ctx->lp_state);
+ if(!(ctx->flags & PSY_MODEL_NO_LOWPASS)){
+ int i;
+ ff_lowpass_filter_free_coeffs(ctx->lp_coeffs);
+ for(i = 0; i < ctx->elements; i++)
+ ff_lowpass_filter_free_state(ctx->lp_state[i]);
+ av_freep(&ctx->lp_state);
+ }
if(ctx->model->end)
return ctx->model->end(ctx);
}
@@ -801,28 +810,24 @@ void ff_aac_psy_preprocess(AACPsyContext
int i, ch;
float t[2];
- if(chans == 1){
- for(ch = 0; ch < chans; ch++){
+ for(ch = 0; ch < chans; ch++){
+ if(!(ctx->flags & PSY_MODEL_NO_LOWPASS)){
+ ff_lowpass_filter(ctx->lp_coeffs, ctx->lp_state[tag*2 + ch], 1024,
+ audio + ch, chstride,
+ dest + ch, chstride);
+ }else{
for(i = 0; i < 1024; i++){
dest[i * chstride + ch] = audio[i * chstride + ch];
}
}
- }else{
+ }
+ if(chans == 2 && !(ctx->flags & PSY_MODEL_NO_ST_ATT)){
for(i = 0; i < 1024; i++){
- if(ctx->flags & PSY_MODEL_NO_ST_ATT){
- for(ch = 0; ch < 2; ch++)
- t[ch] = audio[i * chstride + ch];
- }else{
- t[0] = audio[i * chstride + 0] * (0.5 + ctx->stereo_att) + audio[i * chstride + 1] * (0.5 - ctx->stereo_att);
- t[1] = audio[i * chstride + 0] * (0.5 - ctx->stereo_att) + audio[i * chstride + 1] * (0.5 + ctx->stereo_att);
- }
- if(!(ctx->flags & PSY_MODEL_NO_LOWPASS)){
- LPFilterState *is = (LPFilterState*)ctx->lp_state + tag*2;
- for(ch = 0; ch < 2; 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]);
+ t[0] = dest[0] * (0.5 + ctx->stereo_att) + dest[1] * (0.5 - ctx->stereo_att);
+ t[1] = dest[0] * (0.5 - ctx->stereo_att) + dest[1] * (0.5 + ctx->stereo_att);
+ dest[0] = t[0];
+ dest[1] = t[1];
+ dest += chstride;
}
}
}
Modified: aacenc/aacpsy.h
==============================================================================
--- aacenc/aacpsy.h (original)
+++ aacenc/aacpsy.h Mon Aug 25 16:14:54 2008
@@ -62,9 +62,10 @@ typedef struct AACPsyContext {
const struct AACPsyModel *model; ///< pointer to the psychoacoustic model implementation
void* model_priv_data; ///< psychoacoustic model implementation private data
+ int elements; ///< number of channel elements to be handled by model
float stereo_att; ///< stereo attenuation factor
- LPFilterCoeffs lp_coeffs; ///< lowpass filter coefficients
- LPFilterState *lp_state; ///< lowpass filter state
+ struct FFLPFilterCoeffs* lp_coeffs; ///< lowpass filter coefficients
+ struct FFLPFilterState** lp_state; ///< lowpass filter state
}AACPsyContext;
typedef struct AACPsyModel {
Modified: aacenc/lowpass.c
==============================================================================
--- aacenc/lowpass.c (original)
+++ aacenc/lowpass.c Mon Aug 25 16:14:54 2008
@@ -25,49 +25,146 @@
*/
#include "lowpass.h"
+#include <complex.h>
+#include <math.h>
/**
- * filter data for 4th order IIR lowpass Butterworth filter
- *
- * data format:
- * normalized cutoff frequency | inverse filter gain | coefficients
+ * IIR filter global parameters
*/
-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 },
-};
+typedef struct FFLPFilterCoeffs{
+ int order;
+ float gain;
+ int *cx;
+ float *cy;
+}FFLPFilterCoeffs;
-int ff_lowpass_filter_init_coeffs(LPFilterCoeffs *coeffs, int freq, int cutoff)
+/**
+ * IIR filter state
+ */
+typedef struct FFLPFilterState{
+ float *x;
+}FFLPFilterState;
+
+struct FFLPFilterCoeffs* ff_lowpass_filter_init_coeffs(int order, float cutoff_ratio)
{
int i, j, size;
- float cutoff_ratio;
+ FFLPFilterCoeffs *c;
+ double wa;
+ complex *p, *zp;
- //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(order <= 1 || (order & 1) || cutoff_ratio >= 1.0)
+ return NULL;
+
+ c = av_malloc(sizeof(FFLPFilterCoeffs));
+ c->cx = av_mallocz(sizeof(c->cx[0]) * (order + 1));
+ c->cy = av_malloc (sizeof(c->cy[0]) * order);
+ c->order = order;
+
+ p = av_malloc(sizeof(p[0]) * (order + 1));
+ zp = av_malloc(sizeof(zp[0]) * (order + 1));
+
+ wa = 2 * tan(M_PI * cutoff_ratio / 2.0);
+
+ for(i = 0; i <= order; i++){
+ complex t;
+ double th = (i + order/2 + 0.5) * M_PI / order;
+
+ t = (cos(th) + I*sin(th)) * wa;
+ zp[i] = (2.0 + t) / (2.0 - t);
}
- 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;
+
+ c->cx[0] = 1;
+ for(i = 0; i <= order; i++)
+ for(j = i; j >= 1; j--)
+ c->cx[j] += c->cx[j - 1];
+
+ p[0] = 1.0;
+ for(i = 1; i <= order; i++)
+ p[i] = 0.0;
+ for(i = 0; i < order; i++){
+ for(j = order; j >= 1; j--)
+ p[j] = -zp[i]*p[j] + p[j - 1];
+ p[0] *= -zp[i];
+ }
+ c->gain = creal(p[order]);
+ for(i = 0; i < order; i++){
+ complex t = -p[i] / p[order];
+ c->gain += creal(p[i]);
+ c->cy[i] = creal(t);
+ }
+ c->gain /= 1 << order;
+
+ av_free(p);
+ av_free(zp);
+
+ return c;
+}
+
+struct FFLPFilterState* ff_lowpass_filter_init_state(int order)
+{
+ FFLPFilterState *s = av_mallocz(sizeof(FFLPFilterState));
+ s->x = av_mallocz(sizeof(s->x[0]) * 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; \
+
+void ff_lowpass_filter(const struct FFLPFilterCoeffs *c, struct FFLPFilterState *s, int size, 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;
+
+ 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/2] * c->cx[c->order/2];
+ for(j = 1; j < (c->order / 2); 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 += sstep;
+ }
+ }
+}
+
+void ff_lowpass_filter_free_state(struct FFLPFilterState *state)
+{
+ if(state)
+ av_free(state->x);
+ av_free(state);
+}
+
+void ff_lowpass_filter_free_coeffs(struct FFLPFilterCoeffs *coeffs)
+{
+ if(coeffs){
+ av_free(coeffs->cx);
+ av_free(coeffs->cy);
+ }
+ av_free(coeffs);
}
Modified: aacenc/lowpass.h
==============================================================================
--- aacenc/lowpass.h (original)
+++ aacenc/lowpass.h Mon Aug 25 16:14:54 2008
@@ -29,61 +29,53 @@
#include "avcodec.h"
-/** filter order */
-#define LOWPASS_FILTER_ORDER 4
+struct FFLPFilterCoeffs;
+struct FFLPFilterState;
/**
- * IIR filter global parameters
+ * Initialize filter coefficients.
+ *
+ * @param order filter order
+ * @param cutoff_ratio cutoff to input frequency ratio
+ *
+ * @return pointer to filter coefficients structure or NULL if filter cannot be created
*/
-typedef struct LPFilterCoeffs{
- float gain;
- float c[LOWPASS_FILTER_ORDER];
-}LPFilterCoeffs;
+struct FFLPFilterCoeffs* ff_lowpass_filter_init_coeffs(int order, float cutoff_ratio);
/**
- * IIR filter state
+ * Create new filter state.
+ *
+ * @param order filter order
+ *
+ * @return pointer to new filter state or NULL if state creation fails
*/
-typedef struct LPFilterState{
- float x[LOWPASS_FILTER_ORDER + 1];
- float y[LOWPASS_FILTER_ORDER + 1];
-}LPFilterState;
+struct FFLPFilterState* ff_lowpass_filter_init_state(int order);
/**
- * Initialize filter coefficients.
- *
- * @param coeffs filter coefficients
- * @param freq input frequency (sample rate/2)
- * @param cutoff cutoff frequency
+ * Free filter coefficients.
*
- * @return zero if filter creation succeeded, a negative value if filter could not be created
+ * @param coeffs pointer allocated with ff_lowpass_filter_init_coeffs()
*/
-int ff_lowpass_filter_init_coeffs(LPFilterCoeffs *coeffs, int freq, int cutoff);
+void ff_lowpass_filter_free_coeffs(struct FFLPFilterCoeffs *coeffs);
/**
- * Filter input value.
+ * Free filter state.
*
- * @param coeffs filter coefficients
- * @param s filter state
- * @param in input value
+ * @param state pointer allocated with ff_lowpass_filter_init_state()
+ */
+void ff_lowpass_filter_free_state(struct FFLPFilterState *state);
+
+/**
+ * Perform lowpass filtering on input samples.
*
- * @return filtered value
+ * @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
*/
-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];
-}
+void ff_lowpass_filter(const struct FFLPFilterCoeffs *coeffs, struct FFLPFilterState *state, int size, int16_t *src, int sstep, int16_t *dst, int dstep);
#endif /* FFMPEG_LOWPASS_H */
-
More information about the FFmpeg-soc
mailing list