使用 C++ 中的音频缓冲区进行基本 FIR 滤波

信息处理 过滤器 有限脉冲响应 C++
2022-02-07 06:19:48

我愿意使用 C++ 和 JUCE 实现一个基本的 FIR 滤波器。

我使用在 DSPGuide 中找到的信息编写了这个简单的算法,但我似乎只得到了所有频率的音量变化,而不是频率过滤。

如何纠正它以有效地应用频率过滤?

if (channel == 0) {

    float result = 0; // initialisation to 0 of the result

    for (int sample = 0; sample < buffer.getNumSamples(); sample++) { // for each sample

        // moving the samples in the delay line
        for (int i = 0; i < 8; i++) { // delayLine being 9 values long
            delayLine[i + 1] = delayLine[i];
        }
        delayLine[0] = reader[sample];

        result = 0;
        for (int i = 0; i < 9; i++) { // for each tap
            result = result + delayLine[i] * filterTaps[i]; // multiply     
        }
        writeback[sample] = result; // output
    }
} 

以下是使用的系数,它们应该在可听范围内产生低通滤波器:

filterTaps[0] = 0.002385;
    filterTaps[1] = 0.011910;
    filterTaps[2] = 0.026352;
    filterTaps[3] = 0.039825;
    filterTaps[4] = 0.045351;
    filterTaps[5] = 0.039825;
    filterTaps[6] = 0.026352;
    filterTaps[7] = 0.011910;
    filterTaps[8] = 0.002385;

我使用这个网站生成了它们http://www.arc.id.au/FilterDesign.html 不记得我选择的截止频率,但它在 1000 到 5000 kHz 之间,采样率为 44100 Hz。这些系数只是一个例子,因为我最初的目标是制作一个抗混叠滤波器。由于滤波器工作不正常,可能是算法的原因,我在可听范围内选择了另一组系数来简化调试过程)。

谢谢你。

1个回答

您对延迟线的实施存在缺陷。它只是在每个元素上复制倒数第二个样本。

试试这个:

    for (int i = 7; i >=0; i--) { // delayLine being 9 values long
        delayLine[i + 1] = delayLine[i];
    }

下面是之前的回答

您的滤波器似乎是一个有损低通滤波器——即使通带也有 -15dB 的衰减。

尝试使用这些系数:

0.01156111 0.05773286 0.12773940 0.19304879 0.21983567 0.19304879 0.12773940 0.05773286 0.01156111

它们是通过对您提供的系数的总和进行归一化获得的。

您的过滤器有以下响应:

在此处输入图像描述

归一化系数给出以下响应:

在此处输入图像描述


下面的R代码

 #30506
filterTaps <- c(0.002385,
0.011910,
0.026352,
0.039825,
0.045351,
0.039825,
0.026352,
0.011910,
0.002385)

filterTaps2 <- filterTaps / sum(filterTaps)

freqz(filterTaps)


freqz(filterTaps2)

getNumSamples <- 1000

reader <- rnorm(getNumSamples,0,1)
writeback <- 0*reader

delayLine <- 0*filterTaps
result <- 0; # initialisation to 0 of the result
for (sample in seq(1,getNumSamples)) 
{ # for each sample

    # moving the samples in the delay line
    for (i in seq(8,1,-1)) 
    { # delayLine being 9 values long
        delayLine[i + 1] = delayLine[i];
    }
    delayLine[1] = reader[sample];

    result = 0;
    for (i in seq(1,9)) 
    { # for each tap
          result = result + delayLine[i] * filterTaps[i]; # multiply     
    }
    writeback[sample] <- result; # output
}