FFT 频谱未正确显示

Posted

技术标签:

【中文标题】FFT 频谱未正确显示【英文标题】:FFT Spectrum not displaying correctly 【发布时间】:2017-04-15 01:58:22 【问题描述】:

我目前正在尝试使用 FFTW3 和 SFML 显示音频频谱。我已经按照here 的说明进行操作,并查看了有关 FFT 和频谱以及 FFTW 的大量参考资料,但不知何故,我的条形图几乎都与左对齐,如下所示。我遇到的另一个问题是我找不到有关 FFT 输出规模的信息。目前我将其除以 64,但偶尔仍会超出此范围。此外,我还没有找到关于为什么来自 FFTW 的输出必须与输入大小相同的信息。所以我的问题是:

    为什么与下图不同,我的大部分光谱都向左对齐? 为什么输出不在 0.0 和 1.0 之间? 为什么输入样本计数与 fft 输出计数相关?

我得到了什么:

我在寻找什么:

const int bufferSize = 256 * 8;

void init() 
    sampleCount = (int)buffer.getSampleCount();
    channelCount = (int)buffer.getChannelCount();
    for (int i = 0; i < bufferSize; i++) 
        window.push_back(0.54f - 0.46f * cos(2.0f * GMath::PI * (float)i / (float)bufferSize));
    
    plan = fftwf_plan_dft_1d(bufferSize, signal, results, FFTW_FORWARD, FFTW_ESTIMATE);

void update() 
    int mark = (int)(sound.getPlayingOffset().asSeconds() * sampleRate);
    for (int i = 0; i < bufferSize; i++) 
        float s = 0.0f;

        if (i + mark < sampleCount) 
            s = (float)buffer.getSamples()[(i + mark) * channelCount] / (float)SHRT_MAX * window[i];
        

        signal[i][0] = s;
        signal[i][1] = 0.0f;
    

void draw() 
    int inc = bufferSize / 2 / size.x;
    int y = size.y - 1;
    int max = size.y;
    for (int i = 0; i < size.x; i ++) 
        float total = 0.0f;
        for (int j = 0; j < inc; j++) 
            int index = i * inc + j;
            total += std::sqrt(results[index][0] * results[index][0] + results[index][1] * results[index][1]);
        
        total /= (float)(inc * 64);
        Rectangle2I rect = Rectangle2I(i, y, 1, -(int)(total * max)).absRect();
        g->setPixel(rect, Pixel(254, toColor(BLACK, GREEN)));
    

【问题讨论】:

【参考方案1】:

您的所有问题都与 FFT 理论有关。从任何标准教科书/参考书上研究 FFT 的特性,您将只能自己回答所有问题。

您至少可以从这里开始: https://en.wikipedia.org/wiki/Fast_Fourier_transform。

【讨论】:

我浏览了 FFT、DFT 和 Spectral Density Estimation wiki 页面,但无法找到任何问题的答案,因为大部分信息超出了我的理解范围。 @trigger_death:那你应该把问题发到dsp.stackexchange.com。【参考方案2】:

    许多 FFT 实现都是节能的。这意味着输出的规模与输入的规模和/或大小呈线性关系。

    FFT 是 DFT 是方阵变换。因此,除非某些输出被丢弃,否则输出的数量将始终等于输入的数量(或通过忽略给定严格实输入的冗余复共轭的一半)。如果不是,则不是 FFT。如果您想要更少的输出,可以通过其他方式对 FFT 输出进行下采样或对其进行后处理。

【讨论】:

以上是关于FFT 频谱未正确显示的主要内容,如果未能解决你的问题,请参考以下文章

FFT频谱分析(补零频谱泄露栅栏效应加窗细化频谱混叠),MatlabC语言代码

关于用FFT分析信号频谱的问题

Arduino UNO+OLED可视化音乐频谱:32段分频0.96寸OLED显示细条频谱线

如何用matlab求周期函数的频谱?

使用 FFT 进行频谱分析,基频推导

STM32实现FFT,求取幅度频谱