2
我得到的聲音信號的FFT計算這個Python代碼:FFT意想不到的頻移
from math import *
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)])
N = 64
res = [sin(k) for k in xrange(N)]
# Window function
a = 2*pi/(N-1)
for k in xrange(N):
z = a * res[k]
res[k] = 0.42659 - 0.49656*cos(z) + 0.076849*cos(2*z)
res = fft(res)
for k in xrange(N/2):
# get the amplitude...
sqr = sqrt(res[k].real * res[k].real + res[k].imag * res[k].imag)
if sqr > 0:
print 20 * log10(sqr) # ...in decibels
else:
print "-INF"
我得到了以下的結果:
WITHOUT窗函數(註釋的):
-20.3017238269
-16.9192604108
-12.5089302395
-8.97999530657
-5.96033201086
-3.12975820108
-0.242090896634
2.97021879504
6.95134203457
12.8752188937
29.5096108632 <-- PEAK
17.1668404562
10.6485650284
7.24321329787
4.98448122464
3.3242079033
2.03154022635
0.987966110459
0.124898554197
-0.600705355004
-1.21748302238
-1.74534177237
-2.1985940834
-2.5878009699
-2.92091067118
-3.20399051424
-3.44171254421
-3.63768393032
-3.79467588076
-3.91478386211
-3.99953964778
-4.04998822971
有窗函數
:
-6.55943077129
-65.8567720414
-65.7987645827
-65.7012678903
-65.5625673034
-65.380788761
-65.1529344157
-64.8750852394
-64.5420675211
-64.1470597764
-63.6810080181
-63.131731575
-62.4825087571
-61.7097419947
-60.7788888801
-59.6368610687
-58.1964601495
-56.3001921054
-53.6185951634
-49.2554491173
-38.3322646561 <-- PEAK
-43.3318138698
-52.0838904305
-56.7277347745
-60.2038755771
-62.9772322874
-65.442363488
-67.7550361967
-70.0212827894
-72.3056579688
-74.5822818952
-76.5522909937
由於某種原因,峯值出現偏移。這是一個2倍頻移!我試過這個Java applet:
http://www.random-science-tools.com/maths/FFT.htm
看來,沒有任何窗口函數的結果是正確的(譜圖的1/3的峯值)。相反,如果我在我的python腳本中應用窗口函數,峯值將顯示在頻譜的2/3處。
這是應該發生的嗎?我如何解決它?