FFT窗口导致频谱上的不等放大

时间:2017-08-05 20:28:38

标签: c++ window fft fftw spectrum

我正在使用FFTW在C ++中创建频谱分析仪。

将任何窗函数应用于输入信号后,输出幅度突然似乎随频率而变化。

Retangular Window

image

EXACT-布莱克曼

image

图形以对数方式缩放,采样频率为44100 Hz。所有谐波都在同一水平上产生,在矩形情况下看到的峰值达到0dB。 Exact-Blackman窗口被放大了7.35dB,试图化妆以获得处理增益。

这是我生成输入表的代码......

freq = 1378.125f;

for (int i = 0; i < FFT_LOGICAL_SIZE; i++)
{
    float term = 2 * PI * i / FFT_ORDER;

    for (int h = 1; freq * h < FREQ_NYQST; h+=1) // Harmonics up to Nyquist
    {
        fftInput[i] += sinf(freq * h * K_PI * i / K_SAMPLE_RATE); // Generate sine
        fftInput[i] *= (7938 / 18608.f) - ((9240 / 18608.f) * cosf(term)) + ((1430 / 18608.f) * cosf(term * 2)); // Exact-Blackman window
    }
}

fftwf_execute(fftwR2CPlan);

增加或减少窗口大小不会改变任何内容。我也用Hamming窗口进行了测试,同样的问题。

这是我获取输出的代码。

float val; // Used elsewhere
for (int i = 1; i < K_FFT_COMPLEX_BINS_NOLAST; i++) // Skips the DC and Nyquist bins
{
    real = fftOutput[i][0];
    complex = fftOutput[i][1];

    // Grabs the values and scales based on the window size
    val = sqrtf(real * real + complex * complex) / FFT_LOGICAL_SIZE_OVER_2;
    val *= powf(20, 7.35f / 20); // Only applied during Exact-Blackman test
}

奇怪的是,我尝试以下方法试图在Exact-Blackman案例中平息答案。这种缩减导致了几乎但仍然不是完全平坦的响应。整洁,但仍然没有向我解释为什么会这样。

float x = (float)(FFT_COMPLEX_BINS - i) / FFT_COMPLEX_BINS; // Linear from 0 to 1
x = log10f((x * 9) + 1.3591409f); // Now logarithmic from 0 to 1, offset by half of Euler's constant
val = sqrt(real * real + complex * complex) / (FFT_LOGICAL_SIZE_OVER_2 / x); // Division by x added to this line

2 个答案:

答案 0 :(得分:1)

可能是一个错误。您似乎每个样本多次应用窗口函数。应该从输入合成循环中删除任何窗口,并在FFT之前将其应用于输入向量一次。

答案 1 :(得分:0)

我无法重现代码,因为我手边没有库。然而,这可能是频谱泄漏的结果。 https://en.wikipedia.org/wiki/Spectral_leakage

这是窗函数和采样的不可避免性。如果你看一下那篇文章的权衡部分,窗口的类型可以适用于各种频率或专注于特定频率。由于信号频率增加,目标外的较低频率信号可能更容易发生频谱泄漏。