Python中的短时傅里叶变换

5
我希望能够在wav文件中获取每个时刻最大功率的频率。因此,我使用了Python中的STFT,并使用来自scipy的fft函数和kaiser窗口函数。一切看起来都很好,但我的输出结果看起来有些奇怪。它包含一些非常小的数字和一些非常高的数字。
下面是一个wav文件的输出结果:http://pastebin.com/5Ryd2uXj,以下是Python代码:
import scipy, pylab
import wave
import struct
import sys

def stft(data, cp, do, hop):
    dos = int(do*cp)
    w = scipy.kaiser(dos,12) //12 is very high for kaiser window
    temp=[]
    wyn=[]
    for i in range(0, len(data)-dos, hop):
        temp=scipy.fft(w*data[i:i+dos])
        max=-1
        for j in range(0, len(temp),1):
            licz=temp[j].real**2+temp[j].imag**2
            if( licz>max ):
                max = licz
                maxj = j
        wyn.append(maxj)
    #wyn = scipy.array([scipy.fft(w*data[i:i+dos])
        #for i in range(0, len(data)-dos, 1)])
    return wyn

file = wave.open(sys.argv[1])
bity = file.readframes(file.getnframes())
data=struct.unpack('{n}h'.format(n=file.getnframes()), bity)
file.close()

cp=44100 #sampling frequency
do=0.05 #window size
hop = 5

wyn=stft(data,cp,do,hop)
print len(wyn)
for i in range(0, len(wyn), 1):
    print wyn[i]

2
你是否尝试使用已知的波形,例如正弦波进行测试,以查看是否获得了预期输出? - steve8918
我刚发现这个链接:https://dev59.com/_XE95IYBdhLWcg3wGZ9_ 它看起来很相似,我注意到正弦波的图形上有两条线,而不是一条。我的正弦波输出也是这样的。我不知道为什么会这样... - user1226419
1个回答

6
一个正弦波的实际傅里叶变换是一对距离0频率相等的delta函数。使用离散函数(样本),在频域中每隔 fs(采样率)就会重复这个过程。FFT计算中小误差意味着这两个delta(正弦波的FT)高度可能不完全相同,因此您的算法只是选择更高的一个。
Scipy FFT函数将为您提供具有域[0,fs]的频率分量。由于(如上所述)这是周期性的,因此可以通过交换中心点处的结果将这些值重新映射为[-fs/2, fs/2] - 探索使用fftshift来完成这一点。 但是,您可能仅对频率感兴趣,因此可以简单地丢弃FFT结果的后半部分。
根据scipy.fftpack.fft的注释:

结果的打包方式是“标准”的:如果A = fft(a,n),则A [0]包含零频率项,A [1:n/2+1]包含正频率项,A [n/2+1:]按降低的负频率顺序包含负频率项。因此,对于8点变换,结果的频率为[0, 1, 2, 3, 4, -3, -2, -1]。


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