DSP - 使用DFT过滤频率

Tra*_*rap 4 signal-processing fft dft

我正在尝试实现一个基于DFT的8波段均衡器,仅用于学习.为了证明我的DFT实现工作,我输入了一个音频信号,对其进行了分析,然后再次重新合成它,而没有对频谱进行任何修改.到现在为止还挺好.

我正在使用所谓的"计算DFT的标准方式",这是通过相关性.该方法计算长度为N/2 + 1个样本的实部和虚部.为了减弱我正在做的频率:

float atnFactor = 0.6;
Re[k] *= atnFactor;
Im[k] *= atnFactor;
Run Code Online (Sandbox Code Playgroud)

其中'k'是0到N/2范围内的指数,但我在再合成后得到的是一个轻微的失真信号,特别是在低频时.

输入信号采样率是44.1 khz,因为我只想要一个8波段均衡器,我一次只能给DFT 16采样,所以我有8个频率区可供使用.

有人能告诉我我做错了什么吗?我试图在互联网上找到关于这个主题的信息,但找不到任何信息.

提前致谢.

Mus*_*sis 5

出于此问题的目的,DFT和FFT基本相同.

要衰减FFT变换阵列中的频率仓(或"频带"),您需要将实部和虚部乘以相同因子,并将相应频率仓的实部和虚部相乘.FFT产生一对变换的阵列,其中前半部分值代表正频率分量,后半部分代表负频率分量.

这是一个简化的低通滤波器代码示例,解释了我的意思:

// fftsize = size of fft window
int halfFFTsize = fftsize / 2;
float lowpassFreq1 = 1000.0;
float lowpassFreq2 = 2000.0;
for (int i = 0; i < halfFFTsize; i++)
{
    int ineg = fftsize - 1 - i; // index of neg. freq.
    float freq = (float)i * (44100.0F / (float)halfFFTsize);
    if (freq >= lowpassFreq2)
    {
        real[i] = 0;
        imag[i] = 0;
        real[ineg] = 0;
        imag[ineg] = 0;
    }
    else if (freq >= lowpassFreq1)
    {
        float mult = 1.0 - ((freq - lowpassFreq1) / 
            (lowpassFreq2 - lowpassFreq1));
        real[i] *= mult;
        imag[i] *= mult;
        real[ineg] *= mult;
        imag[ineg] *= mult;
    }

}
Run Code Online (Sandbox Code Playgroud)

更新:阅读完编辑后,我不得不说你的代码按预期工作.我以为你得到了一个大规模失真的重新合成信号,而不是"轻微的失真信号,特别是在低频时".

我认为你看到的失真是你正在使用的非常小的窗口尺寸的结果 - 如果你没有使用Hanning窗口方法重建原始信号,情况尤其如此.

尝试使用更典型的窗口大小(如1024)运行代码.8波段均衡器通常不使用8-bin FFT窗口.通常,8个滑块的设置将用于计算连接频域中的8个点的曲线函数,然后该函数将用于设置更大,更精细粒度的频率组的区间振幅.

还有一点:频率分档均匀地划分可用范围,因此无论窗口大小多大,超过一半的分档覆盖了人耳听不到的频率.这就是均衡器覆盖的频带通常以对数方式缩放的原因(例如,对于典型的3频段均衡器,为100Hz,1Khz和10Khz),因此不适用于相同数量的频率区间.

在均匀间隔的8个窗口窗口的情况下,除了可听频率的失真之外,8个中的5个的衰减肯定没有听觉效果.

  • +1.你的最后一句话特别重要.通过将频域中的值设置为零来进行滤波实际上是应用方形滤波器,这将在频率响应中引起大量振铃(吉布斯现象).请记住,将离散频域中的值设置为零只会影响该确切频率的响应.频率样本之间的频率响应将与砖墙滤波器一起剧烈振荡.我建议你看看有关带通FIR设计的教程. (2认同)