使用PCM样本作为DFT输入

3
我正在编写一个应用程序,将使用FFT算法计算声音信号的DFT。FFT算法所需的输入是PCM样本-即,我有一个大的16位无符号整数列表。
我知道我需要使用窗口函数独立地计算声音信号的几个段的DFT,并且我已经编写了工作代码,将输入声音文件解码为原始PCM样本。
我的问题是关于维基百科上给出的DFT定义:
DFT应对输入x(0),x(1),...,x(N-1)执行可逆线性变换,其中每个x(n)是复数。然而,我不明白如何将我的解码样本整数转换为适合算法的复数。
我看到某些在线示例中,每个样本都被除以获取[0,1)范围内的浮点值,然后虚部设置为0。
这个缩放到[0, 1)是必要的吗?而且将每个样本表示为x + 0i,其中x是样本值,是正确的吗?

是的,对于所有输入值,虚部都为0,不需要缩放到<0,1>。请注意,有许多不同缩放因子的DFT实现,因此请检查输出信号的幅度或功率,并根据您的需求重新调整比例(以避免溢出...)。我通常使用归一化的DFT,它不会改变信号的幅度。 - Spektre
1
还有,在这里看一下:http://stackoverflow.com/a/21658139/2521214,在其中一个评论中有链接到我的win32声卡示波器/频谱分析仪和信号发生器,这样你就可以将你的结果与之进行比较... - Spektre
1个回答

2
是的,您可以通过将虚部设置为0来为每个实数值创建复数。尝试一下,它会起作用。但是,您刚刚增加了要处理的数据量,并且创建了很多冗余。您可以在输出中注意到冗余:正频率和负频率的结果系数将是相同的,除了虚部的符号不同。因此,为了提高效率并减少冗余,通常使用不同的转换将N个实数值转换为N/2个复数值,因此您会得到(大约)N/2个频率。我不会在这里详细介绍,但是可以在这里找到复杂FFT和实际输入变换的不错实现:http://sourceforge.net/projects/kissfft/ 关于您的最后一个问题:不需要缩放输入。DFT是线性变换,因此缩放的输入仅导致等比例缩放的输出。
编辑:顺便问一下,你确定你需要复杂DFT吗?对于实际数据,特别是PCM数据,你应该考虑使用余弦变换,它可以直接将实数输入数据映射为实数输出。

这是一个很好的答案。 :) 正是我不清楚的信息。我的目标是制作类似于此的东西:http://en.wikipedia.org/wiki/File:Spectrogram-19thC.png,从我所读的内容来看,应该使用短时傅里叶变换(它似乎只是在输入信号的几个小片段上计算DFT)。然而,由于DCT-II“与4N个实对称性的实数输入的DFT完全等价(最多相差一个总体比例因子为2),其中偶数索引元素为零”,也许我可以使用它代替DFT,并应用相同的窗口技术? - CmdrMoozy
我会使用普通的DFT,得到复杂频率分量。这些复杂系数的范数将是相应频率上的能量。正确的后处理和解释DCT结果更加复杂。看到那个示例图像中的点状伪影了吗?可能是由于不正确的后处理导致的结果。你肯定不想要那样的结果。但当然,如果你小心处理,从DCT得到的结果也可能非常好。为了获得完美的性能,你甚至可以考虑在这里使用MDCT:http://en.wikipedia.org/wiki/MDCT - pentadecagon
太好了,感谢你的帮助!我会在网上阅读更多资料,并检查KissFFT的源代码。 :) - CmdrMoozy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接