Подобно многих учебников в Интернете, я попытался реализацией оконного синка фильтра нижних частот, используя следующие функции: питонПочему моя функция windowed-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
Для ввода: «застегивается = 0,05», «к = 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
однако, фаза нелинейна выше ~ к.
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, или, может быть, мои ожидания неверны. Я очень благодарен за любую помощь.
*********************** EDIT ********************** *
Основываясь на некоторых полезных комментариях к этому вопросу и некоторой дополнительной работе, я написал функцию, которая производит нулевую фазовую задержку и поэтому немного легче интерпретировать результаты 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.
Я голосующий, чтобы закрыть этот вопрос как не по теме, потому что он лучше подходит для http://dsp.stackexchange.com – mtrw