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

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

  •  2
  • Krunklehorn  · 技术社区  · 7 年前

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

    对输入信号应用任何窗口函数后,输出幅度似乎突然随频率成比例变化。

    image

    精确黑人

    image

    图形按对数缩放,采样频率为44100 Hz。所有谐波均在同一水平产生,在矩形情况下,峰值为0dB。精确的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);
    

    这是我获取输出的代码。

    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
    }
    

    奇怪的是,我尝试了以下几点,试图在确切的布莱克曼案件中平抑反应。这种缩小导致了接近但仍然不是完全平坦的响应。很好,但仍然无法向我解释为什么会发生这种情况。

    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 回复  |  直到 7 年前
        1
  •  1
  •   hotpaw2    7 年前

    可能是个bug。您似乎在每个示例中多次应用窗口函数。任何加窗都应该从输入合成循环中删除,并只应用于输入向量一次,就在FFT之前。

        2
  •  0
  •   user3062390    7 年前

    https://en.wikipedia.org/wiki/Spectral_leakage

    这是窗口函数和采样的无效性。如果你看一下那篇文章的权衡部分,窗口的类型可以适应广泛的频率范围,也可以专注于特定的频率。由于信号的频率在增加,可能目标外的低频信号更容易发生频谱泄漏。