我一直在为应用中的<100 Hz计量工作一个简单的低通滤波器。但是到目前为止,我一直在努力寻找所有背后的理论。我知道它能正常工作很酷,但是如果我知道它为什么/为什么工作,我会非常喜欢它。

我发现了以下代码: />
计算系数。然后,在音频样本中,我以这种方式“低通”它们:

void getLPCoefficientsButterworth2Pole(const int samplerate, const double cutoff, double* const ax, double* const by)
{
    double PI = M_PI;
    double sqrt2 = sqrt(2);

    double QcRaw  = (2 * PI * cutoff) / samplerate; // Find cutoff frequency in [0..PI]
    double QcWarp = tan(QcRaw); // Warp cutoff frequency

    double gain = 1 / ( 1 + sqrt2 / QcWarp + 2 / ( QcWarp * QcWarp ) );

    by[2] = ( 1 - sqrt2 / QcWarp + 2 / ( QcWarp * QcWarp ) ) * gain;
    by[1] = ( 2 - 2 * 2 / ( QcWarp * QcWarp ) ) * gain;
    by[0] = 1;

    ax[0] = 1 * gain;
    ax[1] = 2 * gain;
    ax[2] = 1 * gain;
}


以获得低通设计。

我想知道一些事情:


我以简单的float *数组接收音频样本。那浮点数是多少?我唯一看到的是一个数字,声音如何?
代码在每个样本的新计算中使用了过去的计算(其中三个)。这是否意味着前2个数据样本未正确过滤? (这并不重要,因为它只有2个样本,但只是想知道)
试图学习所有内容,我发现了Butterworth(第二极)滤波器的两个公式。这些公式在代码中如何体现?我发现的公式都没有这些计算可以在“ getLPCoefficientsButterworth2Pole()”函数中看到。


评论

我并不是想在这里不恭敬,但是您的陈述“那是一种声音吗?”似乎表明您不了解时间离散处理的基本原理。如果不了解采样定理,量化,LTI系统等基础知识,将很难解决任何DSP问题。我建议您花些时间阅读一本好书。这是免费的dspguide.com/pdfbook.htm

#1 楼


数字float *数组是指向该数组的指针。它是一个数字,包含浮点值数组的第一个元素的地址。
通常,初始条件(即x和y的初始“过去”元素)为0,但是如果它们的值是不等于0也不是什么大问题,因为过一会儿,初始条件对任何稳定滤波器的输出信号都没有影响。并且您的滤波器显然是稳定的。
具有巴特沃斯特性和截止频率$ \ omega_a = 2 * \ pi * f_a $(其中$ f_a $以赫兹为单位)的二阶低通传递函数由

$$ H(s)= \ frac {\ omega_a ^ 2} {s ^ 2 + \ sqrt {2} \ omega_a s + \ omega_a ^ 2} \ tag {1} $$
这是标准结果,您可以在网上轻松找到。为了获得离散时间滤波器,您可以应用所谓的双线性变换:

$$ s = 2f_s \ frac {z-1} {z + 1} \ tag {2} $ $

其中$ f_s $是采样频率。
这是必需的,因为需要将模拟信号($ 0 \ le f \ le \ infty $)的频率轴映射到离散时间信号的允许频率范围($ 0 \ le f \ le f_s / 2 $)。由于此变换会扭曲频率,因此我们需要根据离散时间域中的给定截止频率$ f_d $计算所需的模拟截止频率:

$$ \ omega_a = 2f_s \ tan(\ frac {\ omega_d} {2})\ text {with} \ omega_d = 2 \ pi f_d / f_s $$

如果将(2)插入(1),则会得到

$$ H(z)= k \ frac {z ^ 2 + b_1z + b_2} {z ^ 2 + a_1z + a_2} \ tag {3} $$



$$ k = \ frac {\ alpha ^ 2} {1+ \ sqrt {2} \ alpha + \ alpha ^ 2} \ text {(gain)} $$
$$ a_1 = \ frac {2(\ alpha ^ 2-1)} {1+ \ sqrt {2} \ alpha + \ alpha ^ 2},\ quad
a_2 = \ frac {1- \ sqrt {2} \ alpha + \ alpha ^ 2} {1+ \ sqrt {2} \ alpha + \ alpha ^ 2},\ quad
b_1 = 2,\ quad b_2 = 1 $$

我在哪里已使用$ \ alpha = \ tan(\ frac {\ omega_d} {2})$。
$$ y(n )= kx(n)+ kb_1x(n-1)+ kb_2x(n-2)-a_1y(n-1)-a_2y(n-2)$$

如您所见,您的代码有很多相似之处。但是,也存在一些差异,您应该检查滤波器的频率响应。我认为上述方程式是正确的,但是您可以检查它们并决定哪个版本是正确的。

评论


$ \ begingroup $
谢谢。我明白第一个。但这仍然是一个浮点数数组。我的意思是:单个浮点值代表什么?
$ \ endgroup $
–尼克·范德斯汀(Niek van der Steen)
13年4月17日在9:13

$ \ begingroup $
一个浮点值是您的输入样本之一。
$ \ endgroup $
– Matt L.
13年4月17日在9:19

$ \ begingroup $
简而言之:声音是气压的变化,通过换能器(麦克风)将其转换为电信号,其信号变化与气压相同。每秒测量N次(=采样率)电信号的幅度,以产生在float *数组中看到的数字序列。关于(音频)数字处理的在线演示有数十个,以更详细的方式解释了此过程。
$ \ endgroup $
–小食
13年4月17日在9:24

$ \ begingroup $
我已经编辑了答案,以解决您问题的最后一部分。
$ \ endgroup $
– Matt L.
13年4月17日在12:24

$ \ begingroup $
您正在使用x(n-something),x是什么?我假设输入样本为“ n”?好答案!
$ \ endgroup $
–尼克·范德斯汀(Niek van der Steen)
13年4月17日在13:49

#2 楼

您询问了低通滤波器的工作原理,并提到该滤波器使用的是您数据的过去值。这是关于低通滤波器发生情况的非技术性讨论。

低通滤波器可以对信号进行不同的观察(随时间变化),缩放比例并将它们相加。您可以想象绘制3次信号,一次是电流,第二次是一个采样时间偏移,第三次是2个采样时间偏移。

在低频下,所有视图看起来都非常相似(单个样本的偏移几乎不会随时改变您在信号上的位置)。在这种情况下,这三个版本将以建设性(或至少非破坏性)的方式加在一起,因此信号将通过滤波器。

现在移动到更高的频率,信号的每个偏移版本在任何给定的瞬间(采样点)都变得更加清晰,实际上甚至可能反转符号。在这些较高的频率下,信号的三个版本趋向于抵消(相消地增加),从而使信号衰减。

不同类型的滤波器会导致这种相长/相消干扰发生。适当的频带以创建低通,带通或高通滤波器。

#3 楼

这取决于您想要的方式。对我来说,我已经在C中实现了。所以,我所做的是我使用matlabfirls中生成了滤波器系数。然后,我将该滤波器系数存储在数组中,然后将这些滤波器系数传递给C中的滤波器函数。在matlab中,很容易生成滤波器系数,然后使用卷积运算或使用特定的滤波器。但是在C中,您还必须实现过滤器。就我而言,我必须对DSP进行处理,因此在C中实现,并使用mex函数在matlab中得到了结果。要计算系数,请在matlab中使用此命令:

n=17                  %filter order
f=[0 0.167 0.333 1]   %Frequency band edges
a=[1 1 0 0]           %Desired amplitudes
fir= firls (n, f,a )