【问题标题】:FFT wrong value?FFT错误值?
【发布时间】:2013-10-11 07:08:44
【问题描述】:

随机搭建一个非常简单的声谱分析仪。

鉴于此 python 代码:
http://rosettacode.org/wiki/Fast_Fourier_transform#Python
像这样实现:

import math
from cmath import exp, pi

def fft(x):
    N = len(x)
    if N <= 1: return x
    even = fft(x[0::2])
    odd =  fft(x[1::2])
    return ([even[k] + exp(-2j * pi * k / N) * odd[k] for k in xrange(N / 2)] + 
            [even[k] - exp(-2j * pi * k / N) * odd[k] for k in xrange(N / 2)])

#res = fft([1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0])
res = [math.sin(k) / 2.0 + 0.5 for k in xrange(64)]  # positive sine wave
res = fft(res)

for k in xrange(64/2):
    # get the amplitude...
    sqr = math.sqrt(res[k].real * res[k].real + res[k].imag * res[k].imag)
    if sqr > 0:
        print 20 * math.log10(sqr)  # ...in decibels
    else:
        print "-INF"

我得到了这些结果:

30.1160980385
-22.9398603241
-18.5295301528
-15.0005952198
-11.9809319241
-9.15035811436
-6.26269080991
-3.05038111824
0.930742121289
6.85461898041
23.4890109499 <-- PEAK
11.1462405429
4.62796511517
1.22261338459
-1.03611868864
-2.69639200998
-3.98905968693
-5.03263380282
-5.89570135908
-6.62130526828
-7.23808293566
-7.76594168565
-8.21919399668
-8.60840088318
-8.94151058446
-9.22459042752
-9.46231245749
-9.6582838436
-9.81527579404
-9.93538377539
-10.0201395611
-10.070588143

这还不错。我在输入正弦波的频率处有一个 23 dB 的峰值,一切似乎都很好。

唯一的问题是,第一个值是什么:30.1160980385? 那是一些非常响亮的低音吗?或者更可能是算法中的缺陷。在这种情况下,我该如何解决。

最后一个问题。 fft 可以将负值作为输入吗?在上面的例子中,我使用了一个在 [0,1] 范围内始终为正的正弦波。如果我想传递 [-1,1] 范围内的值,我会搞砸一切吗?

编辑:

我删除了编辑,因为它离题了。你可以在这里阅读它的内容:

FFT unexpected frequency shift after window function application

【问题讨论】:

  • 看起来这是一个学习项目,如果是真的,请继续学习如何自己实现 FFT。如果您想使用强大的库,请查看scipy.fftpack,这将比任何纯 python 解决方案都快。以stackoverflow.com/questions/19122157/… 为例,以及在 SO 上库的其他使用示例。

标签: python fft cmath


【解决方案1】:

您的DC component 显然很大,因为您的正弦波有 +0.5 的偏移量。如果您使正弦波的均值为零(即范围为 +/- 0.5 或 +/- 1.0),那么您的频谱在 DC (0 Hz) 端应该看起来更好。

另请注意,您在 FFT 之前没有使用window function,因此您将得到spectral leakage(频谱的“拖尾”),这会加剧任何直流分量的影响。

【讨论】:

  • 谢谢,这很有道理。我现在实现了一个窗口功能并编辑了我的 OP 帖子。由于某种原因,现在峰值发生了变化。也许我弄乱了代码?
  • 对不起,我不是 Python 程序员,所以我只能就 DSP 理论给出一般性建议——代码在我未经训练的眼睛看来还可以,但听起来你可能还有一些调试需要做...
  • 我把转移问题放到另一个问题中:link。我最终回答了自己,大声笑。只是一个关于窗口的愚蠢概念错误:)
猜你喜欢
  • 2013-05-22
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多