4

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

我正在使用所谓的“计算 DFT 的标准方法”,即相关性。此方法计算长度为 N/2 + 1 个样本的实部和虚部。为了衰减我正在做的频率:

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

其中“k”是 0 到 N/2 范围内的索引,但我在重新合成后得到的是轻微失真的信号,尤其是在低频时。

输入信号采样率为 44.1 khz,由于我只想要一个 8 波段均衡器,我一次输入 DFT 16 个样本,因此我有 8 个频率箱可供使用。

有人可以告诉我我做错了什么吗?我试图在互联网上找到有关此主题的信息,但找不到任何信息。

提前致谢。

4

1 回答 1

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;
    }

}

更新:阅读您的编辑后,我不得不说您的代码按预期工作。我假设你得到的是一个严重失真的重新合成信号,而不是一个“轻微失真的信号,尤其是在低频时”。

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

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

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

In the case of an evenly-spaced 8 bin window, attenuation of 5 of the 8 is certain to have no audible effect other than distortion of the audible frequencies.

于 2010-05-20T17:30:17.930 回答