为什么我的加窗 sinc 函数具有非线性相位?
Why does my windowed-sinc function have non-linear phase?
与网络上的许多教程类似,我尝试使用以下 python 函数实现窗口化 sinc 低通滤波器:
def black_wind(w):
''' blackman window of width w'''
samps = np.arange(w)
return (0.42 - 0.5 * np.cos(2 * np.pi * samps/ (w-1)) + 0.08 * np.cos(4 * np.pi * samps/ (w-1)))
def lp_win_sinc(tw, fc, n):
''' lowpass sinc impulse response
Parameters:
tw = approximate transition width [fraction of nyquist freq]
fc = cutoff freq [fraction of nyquest freq]
n = length of output.
Returns:
s = impulse response of windowed-sinc filter appended zero-padding
to make len(s) = n
'''
m = int(np.ceil( 4./tw / 2) * 2)
samps = np.arange(m+1)
shift = samps - m/2
shift[m/2] = 1
h = np.sin(2 * np.pi * fc * shift)/shift
h[m/2] = 2 * np.pi * fc
h = h * black_wind(m+1)
h = h / h.sum()
s = np.zeros(n)
s[:len(h)] = h
return s
对于输入:'tw = 0.05'、'fc = 0.2'、'n = 6000',fft 的大小似乎是合理的。
tw = 0.05
fc = 0.2
n = 6000
lp = lp_win_sinc(tw, fc, n)
f_lp = np.fft.rfft(lp)
plt.figure()
x = np.linspace(0, 0.5, len(f_lp))
plt.plot(x, np.abs(f_lp))
magnitude of lowpass filter response
然而,相位在 ~fc 以上是非线性的。
plt.figure()
x = np.linspace(0, 0.5, len(f_lp))
plt.plot(x, np.unwrap(np.angle(f_lp)))
phase of lowpass filter response
鉴于脉冲响应的非零填充部分的对称性,我希望得到的相位是线性的。有人可以解释发生了什么吗?也许我错误地使用了 numpy 函数,或者我的期望不正确。我非常感谢任何帮助。
************************编辑********************* **
基于对这个问题的一些有用的评论和一些更多的工作,我编写了一个产生零相位延迟的函数,因此更容易解释 np.angle() 结果。
def lp_win_sinc(tw, fc, n):
m = int(np.ceil( 2./tw) * 2)
samps = np.arange(m+1)
shift = samps - m/2
shift[m/2] = 1
h = np.sin(2 * np.pi * fc * shift)/shift
h[m/2] = 2 * np.pi * fc
h = h * np.blackman(m+1)
h = h / h.sum()
s = np.zeros(n)
s[:len(h)] = h
return np.roll(s, -m/2)
此处的主要变化是使用 np.roll() 在 t=0 处放置对称线。
图中显示的相位实际上是线性的。它是通带中的恒定斜率,对应于时域中的恒定延迟。这是一个更陡峭的斜率,在阻带中呈现为在 2pi 边界处环绕。但是阻带中的相位值并不是特别重要,因为这些频率无论如何都不会通过滤波器。
阻带中的幅度正过零。过零后系数的相位会跳跃 180 度,这会混淆 np.angle()/np.unwrap()。 -1*180° = 1*0°
与网络上的许多教程类似,我尝试使用以下 python 函数实现窗口化 sinc 低通滤波器:
def black_wind(w):
''' blackman window of width w'''
samps = np.arange(w)
return (0.42 - 0.5 * np.cos(2 * np.pi * samps/ (w-1)) + 0.08 * np.cos(4 * np.pi * samps/ (w-1)))
def lp_win_sinc(tw, fc, n):
''' lowpass sinc impulse response
Parameters:
tw = approximate transition width [fraction of nyquist freq]
fc = cutoff freq [fraction of nyquest freq]
n = length of output.
Returns:
s = impulse response of windowed-sinc filter appended zero-padding
to make len(s) = n
'''
m = int(np.ceil( 4./tw / 2) * 2)
samps = np.arange(m+1)
shift = samps - m/2
shift[m/2] = 1
h = np.sin(2 * np.pi * fc * shift)/shift
h[m/2] = 2 * np.pi * fc
h = h * black_wind(m+1)
h = h / h.sum()
s = np.zeros(n)
s[:len(h)] = h
return s
对于输入:'tw = 0.05'、'fc = 0.2'、'n = 6000',fft 的大小似乎是合理的。
tw = 0.05
fc = 0.2
n = 6000
lp = lp_win_sinc(tw, fc, n)
f_lp = np.fft.rfft(lp)
plt.figure()
x = np.linspace(0, 0.5, len(f_lp))
plt.plot(x, np.abs(f_lp))
magnitude of lowpass filter response
然而,相位在 ~fc 以上是非线性的。
plt.figure()
x = np.linspace(0, 0.5, len(f_lp))
plt.plot(x, np.unwrap(np.angle(f_lp)))
phase of lowpass filter response
鉴于脉冲响应的非零填充部分的对称性,我希望得到的相位是线性的。有人可以解释发生了什么吗?也许我错误地使用了 numpy 函数,或者我的期望不正确。我非常感谢任何帮助。
************************编辑********************* **
基于对这个问题的一些有用的评论和一些更多的工作,我编写了一个产生零相位延迟的函数,因此更容易解释 np.angle() 结果。
def lp_win_sinc(tw, fc, n):
m = int(np.ceil( 2./tw) * 2)
samps = np.arange(m+1)
shift = samps - m/2
shift[m/2] = 1
h = np.sin(2 * np.pi * fc * shift)/shift
h[m/2] = 2 * np.pi * fc
h = h * np.blackman(m+1)
h = h / h.sum()
s = np.zeros(n)
s[:len(h)] = h
return np.roll(s, -m/2)
此处的主要变化是使用 np.roll() 在 t=0 处放置对称线。
图中显示的相位实际上是线性的。它是通带中的恒定斜率,对应于时域中的恒定延迟。这是一个更陡峭的斜率,在阻带中呈现为在 2pi 边界处环绕。但是阻带中的相位值并不是特别重要,因为这些频率无论如何都不会通过滤波器。
阻带中的幅度正过零。过零后系数的相位会跳跃 180 度,这会混淆 np.angle()/np.unwrap()。 -1*180° = 1*0°