2017-01-04 45 views
1

在网络上许多教程类似的,我已经尝试使用以下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处。

+0

我投票结束这个问题作为题外话,因为它更适合http://dsp.stackexchange.com – mtrw

回答

2

阻带中的量值过零。零交叉后系数的相位将跳过180度,这会令np.angle()/ np.unwrap()变得混乱。 -1 * 180°= 1 * 0°

+0

我想了解你关于零交叉的观点。这个阶段在通带中很多时间都是零,看起来np.unwrap处理好了,特别是在阻带中有什么东西会导致交叉点被区别对待? – jeimer

+0

这不是相位过零点,而是零交叉的幅度/量值。这只发生在阻带中,因为通带中的幅度非常大*无处不在*。当幅度过零时,它“真正”从正向负或反之。 np.angle将其解释为180度相位跳跃。假设你有一个* zero *相位滤波器......其中响应是(0.001 + 0j),np.angle表示0.当响应是(-0.001 + 0j)时,np.angle表示pi。 –

+0

请参阅:https://ccrma.stanford.edu/~jos/fp/Example_Zero_Phase_Filter_Design.html –

1

图中所示的阶段实际上是线性的。这是通带中的恒定斜率,对应于时域中的恒定延迟。这是一个非常陡峭的斜坡,它呈现为在2pi边界处缠绕在阻带中。但是阻带中相位的值并不特别重要,因为这些频率无论如何都不会通过滤波器。

+0

谢谢!受到您的评论的启发,我可以用新鲜的眼睛看到相位图,并看到阻带中的斜率看起来与通带中的相同 - 只要2pi跳跃得到治疗。我天真地期望np.unwrap()会为我处理这个问题,但似乎有些东西在那里不起作用。如果它是相同的斜率,它肯定是一个很好的线性相位滤波器。再次感谢。 – jeimer

相关问题