【问题标题】:Butterworth BP filtering in C/C++, strange spectrumC/C++ 中的巴特沃斯 BP 滤波,奇怪的频谱
【发布时间】:2019-01-08 09:52:22
【问题描述】:

我从这里得到了一个 Bw BP C 代码 https://www-users.cs.york.ac.uk/~fisher/mkfilter,正如其他操作系统主题中所评论的那样,并进行了 250Hz,4 阶,从 10 到 20Hz。

以下是此滤波器的代码,改编自本网站提供的代码,并添加了将输入信号的实部和虚部相乘的行(来自 fw FFT R2C):

const unsigned char NZEROS = 8,
                    NPOLES = 8;
double              GAIN = 1.121655430e+02,
                    xv[NZEROS + 2] = {},        // NZEROS + 1 for real and + 1 for imag
                    yv[NPOLES + 2] = {};        // NPOLES + 1 for real and + 1 for imag

for (size_t i = 0; i < array_length_fft_1D; i++)
    {
    xv[0] = xv[1];  xv[1] = xv[2];
    xv[2] = xv[3];  xv[3] = xv[4];
    xv[4] = xv[5];  xv[5] = xv[6];
    xv[6] = xv[7];  xv[7] = xv[8];
    xv[8] = fft_complex_1D[0][i] / GAIN;        // Real part, input
    xv[9] = fft_complex_1D[1][i] / GAIN;        // Imaginary part, input

    yv[0] = yv[1];  yv[1] = yv[2];
    yv[2] = yv[3];  yv[3] = yv[4];
    yv[4] = yv[5];  yv[5] = yv[6];
    yv[6] = yv[7];  yv[7] = yv[8];

    // Multiplying the real part
    yv[8] = (xv[0] + xv[8]) - 4 * (xv[2] + xv[6]) + 6 * xv[4]
        + (-0.1316807150 * yv[0]) + (1.2338753102 * yv[1])
        + (-5.2054087885 * yv[2]) + (12.8890751850 * yv[3])
        + (-20.5097097890 * yv[4]) + (21.4961146820 * yv[5])
        + (-14.4728919700 * yv[6]) + (5.7005626010 * yv[7]);

    // Multiplying the imaginary part
    yv[9] = (xv[0] + xv[9]) - 4 * (xv[2] + xv[6]) + 6 * xv[4]
        + (-0.1316807150 * yv[0]) + (1.2338753102 * yv[1])
        + (-5.2054087885 * yv[2]) + (12.8890751850 * yv[3])
        + (-20.5097097890 * yv[4]) + (21.4961146820 * yv[5])
        + (-14.4728919700 * yv[6]) + (5.7005626010 * yv[7]);

    fft_complex_1D[0][i] = static_cast<float>(yv[8]);       // At this point the real part of the complex array is overwritten
    fft_complex_1D[1][i] = static_cast<float>(yv[9]);       // At this point the imaginary part of the complex array is overwritten
    }

fft_complex_1D 是来自 fw FFT 的输入数组,在每次迭代结束时,实部和虚部乘以系数。稍后将其发送到逆 FFT C2R 并输出一个浮点数组。

然后,当我去 Octave 绘制频谱并查看是否真的被过滤时,10Hz 之前和 20Hz 之后的频率被衰减,但其他一切似乎都没有受到影响,这是我预期的衰减。请参见下图,该图显示了标记为绿色的 10-20Hz 区域。蓝色是输入的未过滤数据(实数从 -5 到 +5)。红色是过滤后的数据。没有对任何数据应用缩放。

此过滤器代码有问题或缺失。你们能提供一些反馈吗(不是双关语)?

【问题讨论】:

  • 我将引导您到不同的堆栈交换。 dsp.stackexchange.com
  • 您是否将过滤器应用于频域数据?过滤器旨在应用于时域数据,不是吗?
  • @mtrw 我不确定。由于我没有看到它的任何应用程序公开,也没有关于“如何”使用它的明确说明,所以我不得不尝试看看。
  • 您的代码不完整;特别是,它似乎缺少一个main() 函数和至少一个#include。请edit您的代码,以便它是您问题的minimal reproducible example(包括任何必要的输入,但最好不需要任何输入),然后我们可以尝试重现并解决它。您还应该阅读How to Ask
  • @TobySpeight 抱歉,如果我没有在原帖中解释。我包括的只是过滤部分。程序的其余部分被省略了,因为正是在这部分中,事情提供了不正确的结果。由于我的错误实现或使用不当,因为 Mtrw 和 User268396 怀疑此实现是针对时域的,而不是频率(这是我正在使用的)。

标签: c filtering signal-processing fft octave


【解决方案1】:

生成的 C 代码是描述时域中过滤器行为的递归关系。每个索引指的是经过滤波的输入信号的样本(您可能从 ADC 获得的信号)。

您通过以下方式“破解”了代码:

  1. 在应该没有的地方添加第 9 个样本。
  2. 以某种方式将数据拆分为实数/虚数部分 (Q/I ?),这不是代码的用途。

【讨论】:

  • 就像 mtrw 一样,您建议过滤器用于时域使用。我理解的方式是作者(RIP)提供了一个构建过滤器的工具,用户负责调整它以适应特定情况。也许我只是为这个问题选择了错误的工具。第二段:aip.de/groups/soe/local/numres/bookfpdf/f13-5.pdf
  • 你当然可以随心所欲地调整它,但那些adjustments 会根据定义改变频率响应。您应该阅读关于 IIR 滤波器的递归关系定义的下一部分。生成的示例 C 代码就是从中派生的。现在,当您将数据分解为单独的实部和虚部(Q/I?)时,您正在从一个域中获取数字,并假装它们在另一个域中是有效/有意义的。在数学中,这很少奏效。
  • 当你研究递归关系时,要意识到的一件重要事情是它描述了一个 IIR 滤波器。您当然可以通过从输入 x 计算 X(z) 然后应用传递函数 H(z) 并最终从 Y(z) 重建时域中的等效 y 信号来在 z 域中进行过滤。但请注意:无论如何,它最终必须等效于时域中的 IIR 滤波器。因此,您也可以跳过整个 z 变换并在时域中进行过滤。 IIR 滤波器的项通常很少,因此更方便且易于实现。
  • 我不知道为什么它不允许我用 @... 引用你的名字...但我当然理解你的考虑,因为我并不真正意识到过滤器来自被引用的工具应该及时使用。由于我也将使用 Phase 进行工作,并且 fwFFT 已经存在,那么如果我只使用这些已经可用的 C++ 实现之一而不是重新发明轮子,也许会更好。由于您在 cmets 中所做的考虑,我将接受您的评论作为答案。
猜你喜欢
  • 1970-01-01
  • 2012-05-09
  • 1970-01-01
  • 2014-03-18
  • 2019-10-09
  • 2020-08-24
  • 1970-01-01
  • 1970-01-01
  • 2017-04-26
相关资源
最近更新 更多