代码之家  ›  专栏  ›  技术社区  ›  Trap

DSP-使用DFT过滤频率

  •  4
  • Trap  · 技术社区  · 14 年前

    我正试图实现一个基于DFT的8波段均衡器的唯一目的是学习。为了证明我的DFT实现是有效的,我输入了一个音频信号,对其进行了分析,然后在不修改频谱的情况下重新对其进行了合成。到现在为止,一直都还不错。

    我使用的是所谓的“标准方法计算DFT”,即通过相关性。该方法计算n/2+1样本的实部和虚部长度。为了降低频率,我只是在做:

    float atnFactor = 0.6;
    Re[k] *= atnFactor;
    Im[k] *= atnFactor;
    

    其中“k”是0到n/2范围内的一个指数,但我在重新合成后得到的是一个轻微的失真信号,特别是在低频下。

    输入信号采样率是44.1千赫,因为我只需要一个8波段均衡器,我一次给DFT 16个采样,所以我有8个频箱可以玩。

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

    事先谢谢。

    1 回复  |  直到 14 年前
        1
  •  5
  •   MusiGenesis    9 年前

    对于这个问题,dft和fft基本上是相同的。

    要衰减FFT变换数组中的频率bin(或“波段”),需要将实部和虚部乘以相同的因子,并将相应的实部和虚部乘以 消极的 频率箱。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;
        }
    
    }
    

    更新: 在阅读了你的编辑之后,我不得不说你的代码按预期工作。我以为你得到了 大规模地 失真的重新合成信号,而不是“轻微失真的信号,特别是在低频率下”。

    我认为你看到的失真是你使用的窗口尺寸非常小的结果——如果你不使用汉宁窗口方法来重建原始信号,情况尤其如此。

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

    还有一点:频率仓均匀地划分了可用范围,因此无论窗口大小有多大,超过一半的频率仓都覆盖了人耳听不到的频率。这就是为什么 乐队 均衡器覆盖的范围通常以对数方式缩放(例如,对于典型的3波段均衡器,100Hz、1kHz和10kHz),因此不适用于相同的频率数。 箱子 .

    对于间隔均匀的8仓窗口,8个窗口中的5个的衰减除可听频率失真外,肯定没有可听效果。