了解FFT输出

时间:2011-07-18 23:17:46

标签: java audio signal-processing accelerometer fft

我需要一些帮助来理解DFT / FFT计算的输出。

我是一位经验丰富的软件工程师,需要解释一些智能手机加速度计读数,例如查找主要频率。不幸的是,我在十五年前的大部分EE课程中都睡过了,但过去几天我一直在阅读DFT和FFT(显然没什么用)。

请不要回答“参加EE课程”。如果我的雇主付钱给我,我实际上打算这样做。 :)

所以这是我的问题:

我以32 Hz的频率捕获了一个信号。这是一个32秒的1秒样本,我在Excel中绘制了它。

enter image description here

然后我从哥伦比亚大学获得了一些用Java编写的FFT code(在关注“Reliable and fast FFT in Java”的帖子后提出建议。)

该程序的输出如下。我相信它正在运行就地FFT,因此它会为输入和输出重复使用相同的缓冲区。

Before: 

Re: [0.887  1.645  2.005  1.069  1.069  0.69  1.046  1.847  0.808  0.617  0.792  1.384  1.782  0.925  0.751  0.858  0.915  1.006  0.985  0.97  1.075  1.183  1.408  1.575  1.556  1.282  1.06  1.061  1.283  1.701  1.101  0.702  ]

Im: [0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  0.0  ]

After: 

Re: [37.054  1.774  -1.075  1.451  -0.653  -0.253  -1.686  -3.602  0.226  0.374  -0.194  -0.312  -1.432  0.429  0.709  -0.085  0.0090  -0.085  0.709  0.429  -1.432  -0.312  -0.194  0.374  0.226  -3.602  -1.686  -0.253  -0.653  1.451  -1.075  1.774  ]

Im: [0.0  1.474  -0.238  -2.026  -0.22  -0.24  -5.009  -1.398  0.416  -1.251  -0.708  -0.713  0.851  1.882  0.379  0.021  0.0  -0.021  -0.379  -1.882  -0.851  0.713  0.708  1.251  -0.416  1.398  5.009  0.24  0.22  2.026  0.238  -1.474  ]

所以,在这一点上,我无法做出输出的正面或反面。我理解DFT概念,例如真实部分是分量余弦波的幅度,虚部是分量正弦波的幅度。我也可以从伟大的书“The Scientist and Engineer's Guide to Digital Signal Processing”中遵循这个图表: enter image description here

所以我的具体问题是:

  1. 从FFT输出中,我如何找到“最常出现的频率”?这是我对加速度计数据的分析的一部分。我应该阅读真实(余弦)或虚构(正弦)数组吗?

  2. 我在时域中输入了32分。 FFT的输出不应该是用于实数的16元素数组和用于虚数的16元素数组吗?为什么程序会给出大小为32的实数和虚数阵列输出?

  3. 与上一个问题相关,如何解析输出数组中的索引?鉴于我输入的32个样本以32 Hz采样,我的理解是16个元素的阵列输出应该使其索引均匀地扩展到采样率的1/2(32 Hz),所以我理解每个元素是正确的数组表示(32 Hz * 1/2)/ 16 = 1 Hz?

  4. 为什么FFT输出具有负值?我认为这些值代表了正弦曲线的幅度。例如,对于频率为3的余弦波,Real [3] = -1.075的输出应表示-1.075的幅度。是吗?幅度如何为负?

4 个答案:

答案 0 :(得分:76)

  1. 你既不应该寻找复数的真实或想象部分(你的实数和想象数是什么)。相反,你想要寻找频率的大小,定义为sqrt(real * real + imag * imag)。这个数字总是积极的。现在您需要搜索的只是最大值(忽略数组中的第一个条目。这是您的DC偏移并且不包含频率相关信息)。

  2. 您可以获得32个实数和32个虚数输出,因为您正在使用复数到复数FFT。请记住,通过使用零虚部来扩展它,将32个样本转换为64个值(或32个复数值)。这导致对称FFT输出,其中频率结果发生两次。一旦准备好在输出0到N / 2中使用,并且在输出N / 2到N中镜像一次。在你的情况下,最简单地忽略输出N / 2到N.你不需要它们,它们是只是关于如何计算FFT的假象。

  3. fft-bin方程的频率为(bin_id * freq / 2)/(N / 2),其中freq是您的采样频率(又名32 Hz,N是FFT的大小)。在您的情况下,这简化为每箱1 Hz。箱子N / 2到N代表负频率(奇怪的概念,我知道)。对于您的情况,它们不包含任何重要信息,因为它们只是前N / 2频率的镜像。

  4. 每个bin的实部和虚部形成一个复数。如果实部和虚部是负的,而频率本身的幅度是正的,那也没关系(参见我对问题1的回答)。我建议你阅读复杂的数字。解释它们如何工作(以及它们有用的原因)超出了在单个stackoverflow问题中可以解释的内容。

  5. 注意:您可能还想了解自相关是什么,以及如何使用它来查找信号的基频。我觉得这就是你真正想要的。

答案 1 :(得分:8)

你已经有了一些很好的答案,但我只想补充一点,你真的需要在FFT之前对你的时域数据应用window function,否则你会在你的频谱中得到令人讨厌的假象。

答案 2 :(得分:5)

1)除了第一个(即DC组件)之外,查找具有最高值的实数组中的索引。你可能需要一个远高于32 Hz的采样率和一个更大的窗口大小,以获得有意义的结果。

2)两个阵列的后半部分是上半部分的镜像。例如,请注意,实数组的最后一个元素(1.774)与第二个元素(1.774)相同,而虚数组的最后一个元素(1.474)是第二个元素的否定元件。

3)您可以以32 Hz的采样率采集的最大频率为16 Hz(Nyquist limit),因此每一步都是2 Hz。如前所述,请记住第一个元素是0 Hz(即DC偏移)。

4)当然,负幅度非常有意义。它只是意味着信号被“翻转” - 标准FFT基于余弦,在t = 0时通常具有值= 1,因此在时间= 0时具有值= -1的信号将具有负幅度

答案 3 :(得分:4)

请注意,即使使用窗函数,“最常出现的频率”也会溅入多个FFT区间。因此,您可能需要使用更长的窗口,多个窗口或插值来更好地估计任何光谱峰值的频率。