在 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);
}