2012-02-22 172 views
5

我想获得wav文件中每个时刻最大功率的频率。 所以我用Python从scipy编写了STFT。我使用scipy的kaiser窗口函数。一切看起来不错,但我的输出看起来很奇怪。它有一些非常小的数字和一些非常高的。Python中的短时傅里叶变换

这里是一个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 2012-02-22 17:13:34

+0

我刚刚发现这个:http://stackoverflow.com/questions/2459295/stft-and-istft-in-python 它看起来相似,我看到在窦的情节是2行,不是1.我有同样的在我的输出为窦。我不知道为什么...... – user1226419 2012-02-22 19:01:41

回答

5

正弦波的实际FT是一对从0频率等距离δ函数。对于离散函数(采样),在频域中每隔fs(采样率)重复一次。 FFT计算中的小错误将意味着这两个增量(正弦波的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]。