Python:将频率响应转换为脉冲响应

时间:2014-01-18 19:47:17

标签: python signal-processing fft frequency-analysis ifft

我正在使用声学模拟器,它为我输入的任何(正实际)频率提供(复杂的)频率响应。

我想生成一个1024点的脉冲响应。

我相信我有基本的技巧:https://dsp.stackexchange.com/questions/13883/convert-frequency-response-to-impulse-response

但是,我想从命令行实现它。

模拟器生成一个看起来像这样的文件(注意我缩短了数字以使其更具可读性):

# Run name  = pro-ch0-pc1-gmr
# Run owner = umby
# Cfg file  = sphere_source.cfg
# Frequency = 0.000000 + i*1077.566280 (171.5000 Hz)
#
# 1    2  3  4  5       6       7        8        9        10        11      12      13    
# imic xm ym zm re(inc) im(inc) abs(inc) re(scat) im(scat) abs(scat) re(tot) im(tot) abs(tot)
0 +1.4E+00 +0.0E+00 +9.4E-02 -9.8E-04 -5.2E-02 +5.2E-02 -5.4E-03 +1.2E-02 +1.3E-02 -6.4E-03 -4.0E-02 +4.0E-02
1 +1.4E+00 +0.0E+00 +1.8E-01 -3.8E-03 -5.2E-02 +5.2E-02 -5.1E-03 +1.3E-02 +1.3E-02 -9.0E-03 -3.9E-02 +4.0E-02
:
:
etc
  • 第二列是以弧度/秒为单位的角频率

  • 第三列是以Hz为单位的频率

  • 第11列和第12列是Re(z)和Im(z),即此频率的频率响应的实部和虚部

  • 第13列是频率响应的幅度,我猜这可以与前两列之一一起丢弃

所以我的问题是:如何处理这个文件并获得一个脉冲响应?

1 个答案:

答案 0 :(得分:3)

这是将频率响应转换为脉冲响应的必要代码(它包含一个测试信号;信号被转换到频域然后恢复,证明算法确实有效):

import numpy

#http://stackoverflow.com/questions/9062387/ifft-of-symmetric-spectrum/9062837#9062837

# test
waveform = [1,2,3,4,5,6]
print( waveform )

fullSpectrum = list( numpy.fft.fft( foo ) )
for w in fullSpectrum:
    print w

# In my practical application, I would be receiving frequencies DC through Nyquist,
#  i.e. the half of the spectrum containing the positive frequencies, and I would 
#  need to reconstitute the negative frequencies using symmetry:
#
DC_to_Nyquist = list( numpy.fft.fft( foo ) )[0:4]


# RESTORE FULL SPECTRUM BY SYMMETRY
DC      = DC_to_Nyquist[0].real + 0j
nyquist = DC_to_Nyquist[-1].real + 0j

# discard DC and Nyquist from list
Z = DC_to_Nyquist[1:-1]

Z_reverse = Z[::-1]
Z_conj_reverse = [ w.conjugate() for w in Z_reverse ]

spectrum = [DC] + Z + [nyquist] + Z_conj_reverse

print( "\nSpectrum" )
for w in spectrum:
    print( w )

# INVERSE FFT
timedomain = list( numpy.fft.ifft( spectrum ) )

#ir = [s.real for s in timedomain]

print( "\nTimedomain" )
for w in timedomain:
    print w

这是样板代码,用于从输入文件中提取复数:

#!/usr/bin/python

import sys
import csv

infile = sys.argv[1]

Z = [ ]

with open( infile ) as f_in:
    lines = csv.reader( f_in, delimiter=' ', skipinitialspace=True )
    for n, line in enumerate( lines ):
        if n > 6:
            re = float( line[11] )
            im = float( line[12] )

            Z.append( complex( re, im ) )

print( Z )

编辑:更好的是:

Z_conj_reverse = [ w.conjugate() for w in reversed( Z ) ]