我正在尝试使用 FFT 对信号进行时移,但是我遇到了一些奇怪的效果,这些效果取决于时移的大小。我需要能够将时间移动任意量 - 即浮点时间。我正在使用该线程中的方法:
这是我的代码:
import numpy as np
import matplotlib.pyplot as plt
f1 = 1.8
f2 = 2.6
#try tDelay = .02002 and tDelay = .0205
tDelay = .0205 #seconds
samples = 1024 #number of samples in the time interval
tstart = 0.0
tend = 1.0
# create a waveform to use for the time shifting
samplePeriod = (tend - tstart) / (samples)
print("\nThe sampling period is %f seconds" % samplePeriod)
print("The time delay is %f seconds" % tDelay)
tDelayInSamples = tDelay / samplePeriod
print("The time delay in samples is %f samples" % tDelayInSamples)
timeList = np.linspace(tstart, tend, samples)
waveform = np.sin(2 * np.pi * f1 * timeList) + np.sin(2 * np.pi * f2 * timeList)
# do the time shifting
fftOut = np.fft.fft(waveform)
N = fftOut.shape[0]
k = np.linspace(0, N-1, N)
phaseShiftFunction = np.exp((-2*np.pi*1j*k*tDelayInSamples)/(N))
fftWithDelay = np.multiply(fftOut, phaseShiftFunction)
waveform2 = np.fft.ifft(fftWithDelay)
plots = 1
plt.subplot(plots, 1, 1)
plt.plot(waveform)
plt.plot(waveform2)
plt.show()
如果您使用 .02002 和 .0205 之类的 tDelay 运行上述代码,您将看到恢复的信号完全不同。我不明白为什么会这样,或者该怎么做。
编辑:
经过相当大的努力,我相信我已经解决了这个问题。这里有两个关键见解:
当您进行分数时移时,您必须对相移值数组进行 fftshift 以使其对称。(整数样本时移不需要这样做)。看到这个线程。
将 FFT 后的数据与相移值相乘后,如果立即进行 IFFT,您会发现数据正确时移,但波形在复平面中旋转了某个角度。该角度取决于与时间偏移相对应的样本分数。例如,对应于 N+.5 个样本的时间偏移将是完全虚构的(即旋转)。要旋转回实轴,请添加额外的相移(在进行 IFFT 之前): (其中 D 是样本中的时移)。
所以为了超级清楚,这个过程是:
- 采取 FFT
- 构造相移 (其中 k=样本数,D=样本时间偏移,N=FFT 的样本长度)
- 对 #2 中计算的相移系数进行 FFTshift
- 现在将 FFT 数据与相移系数相乘
- 做IFFT
示例代码:
import numpy as np
import matplotlib.pyplot as plt
f1 = 12.8
f2 = 22.6
samples = 1024
tDelay = .00938
tstart = 0.0
tend = 1.0
# 0. Example waveform to demonstrate the time shift
timeList = np.linspace(tstart, tend, samples)
waveform = np.sin(2 * np.pi * f1 * timeList) + 1*np.sin(2 * np.pi * f2 * timeList)
# 1. Take the FFT
fftData = np.fft.fft(waveform)
# 2. Construct the phase shift
samplePeriod = (tend - tstart) / (samples)
tDelayInSamples = tDelay / samplePeriod
N = fftData.shape[0]
k = np.linspace(0, N-1, N)
timeDelayPhaseShift = np.exp(((-2*np.pi*1j*k*tDelayInSamples)/(N)) + (tDelayInSamples*np.pi*1j))
# 3. Do the fftshift on the phase shift coefficients
timeDelayPhaseShift = np.fft.fftshift(timeDelayPhaseShift)
# 4. Multiply the fft data with the coefficients to apply the time shift
fftWithDelay = np.multiply(fftData, timeDelayPhaseShift)
# 5. Do the IFFT
shiftedWaveform = np.fft.ifft(fftWithDelay)
print("\nThe sampling period is %f seconds" % samplePeriod)
print("The time delay is %f seconds" % tDelay)
print("The time delay in samples is %f samples" % tDelayInSamples)
print("The correction phase shift is %f pi" % (tDelayInSamples))
plots = 1
plt.subplot(plots, 1, 1)
plt.plot(waveform)
plt.plot(shiftedWaveform)
plt.show()
我欢迎任何其他人可能有更好的方法来做到这一点,或者如果我忽略了任何事情!