ffmpeg中aneuqalizer的FILTER_ORDER解释

博客详细解释了ffmpeg的aneuqalizer模块中FILTER_ORDER宏的含义,它并不直接表示滤波器的阶数,而是指双一阶IIR滤波器的级联数量。FILTER_ORDER乘以2再除以4等效于双四阶IIR滤波器的数量,实际实现中用于构建更复杂的滤波器结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 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^-4
H(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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值