2017-01-04 15 views
1

Подобно многих учебников в Интернете, я попытался реализацией оконного синка фильтра нижних частот, используя следующие функции: питонПочему моя функция 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.

+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