ffmpeg中aneuqalizer的FILTER_ORDER解释

来源:互联网 发布:网站源码可以干什么 编辑:程序博客网 时间:2024/06/03 22:42

在 af_aneuqalizer.c 这个模块中用到这个宏定义 FILTER_ORDER,按照字面理解,可能会被认为是滤波器的阶数,一个滤波器:

        b0 + b1*z^-1 + b2*z^-2 + b3*z^-3 + ......H(z) = --------------------------------------------                                  (Eq 1)        a0 + a1*z^-1 + a2*z^-2 + a3*z^-3 ......

一般说滤波器的阶数,指的是 b1, b2, ….. 的个数。但是,在这个模块中,含义有些不同,下面逐步说明一下。

这个模块用的最基本的滤波器,是一个双四阶IIR滤波器,即:

        b0 + b1*z^-1 + b2*z^-2 + b3*z^-3 + b4*z^-4H(z) = --------------------------------------------                                  (Eq 2)        a0 + a1*z^-1 + a2*z^-2 + a3*z^-3+ a4*z^-4

而数字滤波器中,最小的一个IIR滤波器,可以认为是双一阶滤波器,即如下公式:

        b0 + b1*z^-1 H(z) = -------------                                    (Eq 3)        a0 + a1*z^-1

其它双 N 阶滤波器(这里N为偶数),都可以用 N/2个双一阶滤波器级联得到。

所以,FILTER_ORDER 这个宏定义,指的是多少个双一阶IIR滤波器级联。最终等效的滤波器是 ( FILTER_ORDER * 2 ) 阶IIR滤波器。例如 FILTER_ORDER = 4, 则最终等效的是一个双八阶IIR滤波器。

但是,在实现中,这个模块用的最基本滤波器又是双四阶滤波器,所以,相当于用 ( FILTER_ORDER * 2 / 4 ) 个双四阶滤波器级联。,

最后 FILTER_ORDER * 2 / 4 = FILTER_ORDER / 2 , 也就是代码中用到 FILTER_ORDER / 2 .

static void draw_curves(AVFilterContext *ctx, AVFilterLink *inlink, AVFrame *out){    AudioNEqualizerContext *s = ctx->priv;    char *colors, *color, *saveptr = NULL;    int ch, i, n;    colors = av_strdup(s->colors);    if (!colors)        return;    memset(out->data[0], 0, s->h * out->linesize[0]);    for (ch = 0; ch < inlink->channels; ch++) {        uint8_t fg[4] = { 0xff, 0xff, 0xff, 0xff };        int prev_v = -1;        double f;        color = av_strtok(ch == 0 ? colors : NULL, " |", &saveptr);        if (color)            av_parse_color(fg, color, -1, ctx);        for (f = 0; f < s->w; f++) {            double zr, zi, zr2, zi2;            double Hr, Hi;            double Hmag = 1;            double w;            int v, y, x;            w = M_PI * (s->fscale ? pow(s->w - 1, f / s->w) : f) / (s->w - 1);            zr = cos(w);            zr2 = zr * zr;            zi = -sin(w);            zi2 = zi * zi;            for (n = 0; n < s->nb_filters; n++) {                if (s->filters[n].channel != ch ||                    s->filters[n].ignore)                    continue;                for (i = 0; i < FILTER_ORDER / 2; i++) {                    FoSection *S = &s->filters[n].section[i];                    /* H *= (((((S->b4 * z + S->b3) * z + S->b2) * z + S->b1) * z + S->b0) /                          ((((S->a4 * z + S->a3) * z + S->a2) * z + S->a1) * z + S->a0)); */                    Hr = S->b4*(1-8*zr2*zi2) + S->b2*(zr2-zi2) + zr*(S->b1+S->b3*(zr2-3*zi2))+ S->b0;                    Hi = zi*(S->b3*(3*zr2-zi2) + S->b1 + 2*zr*(2*S->b4*(zr2-zi2) + S->b2));                    Hmag *= hypot(Hr, Hi);                    Hr = S->a4*(1-8*zr2*zi2) + S->a2*(zr2-zi2) + zr*(S->a1+S->a3*(zr2-3*zi2))+ S->a0;                    Hi = zi*(S->a3*(3*zr2-zi2) + S->a1 + 2*zr*(2*S->a4*(zr2-zi2) + S->a2));                    Hmag /= hypot(Hr, Hi);                }            }            v = av_clip((1. + -20 * log10(Hmag) / s->mag) * s->h / 2, 0, s->h - 1);            x = lrint(f);            if (prev_v == -1)                prev_v = v;            if (v <= prev_v) {                for (y = v; y <= prev_v; y++)                    AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg));            } else {                for (y = prev_v; y <= v; y++)                    AV_WL32(out->data[0] + y * out->linesize[0] + x * 4, AV_RL32(fg));            }            prev_v = v;        }    }    av_free(colors);}
0 0
原创粉丝点击