C语言中的带通滤波器实现

信息处理 频率 带通 C
2022-02-06 12:16:54

我已经在谷歌上搜索了一段时间,偶然发现了音频食谱和 Bjorn 的博客进一步解释了链接这里

背景信息:我修改了 rtl-sdr 开源代码以调谐到 VOR 电台(传输航向,通常用于飞机)。我调到 113.1 MHz,这是附近 VOR 站传输数据的频率。在 113.1 MHz 频率内,有 3 个信号;

  1. 1020Hz 的摩尔斯电码
  2. 参考信号(9960Hz +- 480Hz)(FM这个信号,里面还有另一个30Hz信号)
  3. 可变信号 (30Hz)

我正在尝试隔离这些信号。现在,当我调到电台(113.1MHz)并进行幅度调制时,我​​可以听到扬声器发出的摩尔斯电码信号,背景中有很多噪音。我按照音频食谱指南以及 Bjorn 的实现编写了一个 BPF 函数(粘贴在下面)来隔离莫尔斯电码信号(1020Hz),以便只听到莫尔斯电码,背景中几乎没有噪音。然而,我几乎什么都听不见,就像有人真的把音量调低到几乎静音一样。我从这个开始是因为如果我真的能听到莫尔斯电码信号,那么就证明 BPF 有效,现在我可以使用该函数来隔离其他两个信号。

我用来计算 a0 到 b2 的值:我还对 a0 到 b2 值进行了标准化。

  1. 采样率:24KHz
  2. 中心频率:1020Hz
  3. BW(八度音阶):1(不太明白这个)
  4. 增益:1(假设 1 应该没问题,但又不太确定)

C语言中的BPF函数:

int band_pass_fir(struct morse *_m, int16_t *_signal, int _len)
{
  // _m->signal (int16 array) is my desired output
  // _signal (int16 array) contains the actual amplitude modulated data received from the signal
  // _len is the length of _signal

  int i = 2;

  const float b0 = 0.1205498139,
              b1 = 0,
              b2 = -0.1205498139,
              a1 = -1.7626236142,
              a2 = 0.8273910712;

  while (i < _len)
  {
    _m->signal[i] = (int16_t)(b0 * _signal[i]) +
                    (int16_t)(b1 * _signal[i-1]) +
                    (int16_t)(b2 * _signal[i-2]) -
                    (int16_t)(a1 * _m->signal[i-1]) -
                    (int16_t)(a2 * _m->signal[i-2]);

    _m->signal[i-2] = _m->signal[i-1];
    _m->signal[i-1] = _m->signal[i];

    i++;
  }
}

问题:

  1. 为了隔离这个 1020Hz 信号,假设我需要一个 BPF 是否安全?还是我需要其他类型的过滤器?
  2. 假设我需要隔离 1020Hz 的任何类型的滤波器与隔离 30Hz 信号(可变信号)所需的滤波器类型相同?那是对的吗?
  3. 你看我上面的方法有什么问题吗?
2个回答

有几个潜在的问题:

  1. 您的代码不会计算完整的输出向量,您只需保留最后三个样本(通常称为“状态变量”。您的输出应该是与输入长度相同的向量
  2. 这只是一个二阶滤波器。根据信号的确切属性,这可能不足以隔离您想要的组件。我建议使用巴特沃斯带通滤波器。在这种情况下,您可以独立控制带通的较低截止和较高截止以及斜坡的陡度。“Octave”中有巴特沃斯设计工具,见http://octave.sourceforge.net/signal/function/butter.html
  3. 如果您需要使用更高阶的过滤器,它们应该被实现为“级联双二阶”或“级联二阶部分”。通过 google 可以找到大量的代码示例

作为一个快速建议,尝试将两个 _m->signal[i-2] 和 _m->signal[i-1] 分配移到 _m->signal[i] 分配之上。在该例程结束时,您不太可能希望 _m->signal[i-1] 等于 _m->signal[i] 。