首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >将FFT转换为spectogram

将FFT转换为spectogram
EN

Stack Overflow用户
提问于 2009-11-05 19:33:37
回答 5查看 10.8K关注 0票数 12

我有一个音频文件,我正在迭代该文件,并在每一步中获取512个样本,然后通过FFT传递它们。

我将数据输出为块514浮点长度(使用IPP的ippsFFTFwd_RToCCS_32f_I),其中实部和虚部交错。

我的问题是,一旦我得到了这些复数,我该如何处理它们?目前,我正在为每个值执行

代码语言:javascript
运行
复制
const float realValue   = buffer[(y * 2) + 0];
const float imagValue   = buffer[(y * 2) + 1];
const float value       = sqrt( (realValue * realValue) + (imagValue * imagValue) );

这给出了一些稍微有用的东西,但我更希望得到0到1范围内的值。上面的问题是,峰值最终返回到9或更多。这意味着事情变得非常饱和,然后频谱图的其他部分几乎没有显示出来,尽管当我通过试听的频谱图运行音频时,它们看起来相当强。我完全承认我不能100%确定FFT返回的数据是什么(除了它代表我传入的512个样本长块的频率值)。特别是我对compex数字到底代表什么缺乏理解。

任何建议和帮助都将不胜感激!

编辑:只是为了澄清一下。我最大的问题是,如果不知道规模是多少,返回的FFT值是没有意义的。有没有人能告诉我怎么算出那个标尺?

Edit2:通过执行以下操作,我获得了非常漂亮的结果:

代码语言:javascript
运行
复制
size_t count2   = 0;
size_t max2     = kFFTSize + 2;
while( count2 < max2 )
{
    const float realValue   = buffer[(count2) + 0];
    const float imagValue   = buffer[(count2) + 1];
    const float value   = (log10f( sqrtf( (realValue * realValue) + (imagValue * imagValue) ) * rcpVerticalZoom ) + 1.0f) * 0.5f;
    buffer[count2 >> 1] = value;
    count2 += 2;
}

在我看来,这甚至比我看过的大多数其他频谱图实现都要好。

我的所作所为有什么重大错误吗?

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-11-05 22:28:09

为了让所有的FFT都可见,通常的做法是取数值的对数。

因此,输出缓冲区的位置告诉您检测到的频率。复数的幅值(L2范数)告诉您检测到的频率有多强,相位(L2)提供的信息在图像空间比音频空间重要得多。由于FFT是离散的,因此频率范围从0到奈奎斯特频率。在图像中,第一项(DC)通常是最大的,因此如果您的目标是归一化,则是一个很好的候选者。我不知道这是否也适用于音频(我很怀疑)

票数 11
EN

Stack Overflow用户

发布于 2009-11-05 23:09:22

对于每个包含512个样本的窗口,您可以像以前一样计算FFT的大小。每个值表示信号中存在的相应频率的大小。

代码语言:javascript
运行
复制
mag
 /\
 |
 |      !         !
 |      !    !    !
 +--!---!----!----!---!--> freq
 0          Fs/2      Fs

现在我们需要计算出频率。

由于输入信号是实数值,因此FFT是围绕中间(奈奎斯特分量)对称的,第一项是直流分量。已知信号采样频率Fs,奈奎斯特频率为Fs/2。因此,对于指数k,对应的频率为k*Fs/512

因此,对于长度为512的每个窗口,我们得到指定频率下的幅度。这些在连续窗口上的组形成了谱图。

票数 7
EN

Stack Overflow用户

发布于 2011-12-17 08:30:57

只是为了让人们知道我在整个问题上做了很多工作。我发现的最主要的事情是,FFT需要在完成之后进行规范化。

为此,您可以将窗口向量的所有值平均在一起,以获得一个略小于1的值(如果使用的是矩形窗口,则为1)。然后,将该数字除以经过FFT变换后的频率位数。

最后,将FFT返回的实际数字除以归一化数字。现在,振幅值应在-Inf到1的范围内。日志,等等,随你喜欢。您仍将使用已知的范围。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1679974

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档