freqz 함수없이 MATLAB에서 대역 통과 버터 워스 필터의 주파수 응답을 수동으로 플롯하는 방법은 무엇입니까?


15

신호에 대역 통과 필터를 적용하는 아래와 같은 코드가 있습니다. 나는 DSP에서 멍청한 놈이며 진행하기 전에 무대 뒤에서 무슨 일이 일어나고 있는지 이해하고 싶습니다.

이를 위해을 사용하지 않고 필터의 주파수 응답을 플롯하는 방법을 알고 싶습니다 freqz.

[b, a] = butter(order, [flo fhi]);
filtered_signal = filter(b, a, unfiltered_signal)

출력이 주어지면 [b, a]어떻게해야합니까? 이것은 간단한 작업 인 것처럼 보이지만 설명서 또는 온라인에서 필요한 것을 찾는 데 어려움을 겪고 있습니다.

또한 가능한 fft빠른 방법 ( 예 : 빠른 알고리즘 사용)을 이해하고 싶습니다 .

답변:


25

우리는 일반적으로 필터의 전달 기능이 다음과 같이 주어진다는 것을 알고 있습니다.

H(z)=k=0Mbkzkk=0Nakzk

이제 단위 원에서 전달 함수를 평가하려면 z=ejω 를 대입 하십시오.

H(ejω)=k=0Mbkejωkk=0Nakejωk

따라서 이것은 주어진 ω 에서 다항식 평가의 문제가된다 . 단계는 다음과 같습니다.

  • 모난 주파수 생성 벡터 ω=[0,,π] 스펙트럼의 전반부 (까지 갈 필요위한 2π )에 저장하고이 w.
  • 그들 모두에서 사전 계산 지수 ejω 를 변수에 저장하십시오 ze.
  • polyval함수를 사용하여 다음을 호출하여 분자 및 분모 값을 계산하십시오. polyval(b, ze), 나누고에 저장하십시오 H. 우리는 진폭에 관심이 있으므로 결과의 절대 값을 취하십시오.
  • 다음을 사용하여 dB 스케일로 변환하십시오. HdB=20log10H 이 경우 1 은 참조값입니다.

그 모든 것을 코드에 넣으십시오.

%% Filter definition
a = [1 -0.5 -0.25]; % Some filter with lot's of static gain
b = [1 3 2];

%% My freqz calculation
N = 1024; % Number of points to evaluate at
upp = pi; % Evaluate only up to fs/2
% Create the vector of angular frequencies at one more point.
% After that remove the last element (Nyquist frequency)
w = linspace(0, pi, N+1); 
w(end) = [];
ze = exp(-1j*w); % Pre-compute exponent
H = polyval(b, ze)./polyval(a, ze); % Evaluate transfer function and take the amplitude
Ha = abs(H);
Hdb  = 20*log10(Ha); % Convert to dB scale
wn   = w/pi;
% Plot and set axis limits
xlim = ([0 1]);
plot(wn, Hdb)
grid on

%% MATLAB freqz
figure
freqz(b,a)

원본 출력 freqz:

enter image description here

그리고 내 스크립트의 출력 :

enter image description here

선형 스케일의 빠른 비교-멋지게 보입니다!

[h_f, w_f] = freqz(b,a);
figure
xlim = ([0 1]);
plot(w, Ha) % mine
grid on
hold on
plot(w_f, abs(h_f), '--r') % MATLAB
legend({'my freqz','MATLAB freqz'})

enter image description here

이제 함수를 일부 함수로 다시 작성하고 조건을 추가하여 더 유용하게 사용할 수 있습니다.


필터의 주파수 응답이 임펄스 응답의 푸리에 변환이라는 기본 속성을 사용하는 또 다른 방법 (이전에 제안 된 것이 더 신뢰할 수 있음)입니다.

H(ω)=F{h(t)}

δ(t)

d = [zeros(1,length(w_f)) 1 zeros(1,length(w_f)-1)];
h = filter(b, a, d);
HH = abs(fft(h));
HH = HH(1:length(w_f));

이에 비해 다음이 생성됩니다.

enter image description here


1
자세한 설명
partida

나는이 라인을 생각하고있다 a = [1 -0.5 -0.25]; % Some filter with lot's of static gain. 여기에서 이러한 매개 변수의 선택에 대해 설명해 주시겠습니까? Matlab 매뉴얼을 읽고 있는데 [h,w] = freqz(hfilt,n)시냅스의 한 부분에 나와 있습니다. 에 두 개의 필터 (a, b)를 제공하고 freqz있습니다. 두 필터가 모두 hfilt있습니까? 아니면 하나 n?
Léo Léopold Hertz 준영

다른 사람들을 위해 명확히 : "2 pi까지 올라갈 필요가 없습니다"는 계수가 실제 일 때입니다. 복잡한 계수를 가진 필터에 적용 할 수 있으며,이 경우 스펙트럼은 더 이상 대칭이 아니므로 주파수를 2pi로 확장하려고합니다.
Dan Boschen

14

이것은 배정도 수학을 사용할 때 더 일반적이고 완벽하게 좋은 jojek의 대답에 대한 부록입니다. 정밀도가 떨어지면 주파수 응답의 주파수가 매우 낮거나 (Nyquist보다 훨씬 낮음) 필터의 공진 주파수가 매우 낮을 때 발생하는 "코사인 문제"가 발생합니다.

|H(ejω)|2|H(ejω)|=|H(ejω)|

이 삼각 정체성을 고려하십시오.

cos(ω) = 12sin2(ω2)

sin2(ω2)ω0

sin2(ω2)

H(z)=b0+b1z1+b2z2a0+a1z1+a2z2

복잡한 주파수 응답이있는

H(ejω)=b0+b1ejω+b2ej2ωa0+a1ejω+a2ej2ω

크기의 제곱이 있습니다.

|H(ejω)|2=|b0+b1ejω+b2ej2ω|2|a0+a1ejω+a2ej2ω|2=(b0+b1cos(ω)+b2cos(2ω))2+(b1sin(ω)+b2sin(2ω))2(a0+a1cos(ω)+a2cos(2ω))2+(a1sin(ω)+a2sin(2ω))2=b02+b12+b22+2b1(b0+b2)cos(ω)+2b0b2cos(2ω)a02+a12+a22+2a1(a0+a2)cos(ω)+2a0a2cos(2ω)

|H(ejω)|cos(ω)cos(2ω)ω11

위의 trig identity를 사용하면 크기가 제곱됩니다.

|H(ejω)|2=b02+b12+b22+2b1(b0+b2)cos(ω)+2b0b2cos(2ω)a02+a12+a22+2a1(a0+a2)cos(ω)+2a0a2cos(2ω)=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(12sin2(ω))a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(12sin2(ω))=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(2cos2(ω)1)a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(2cos2(ω)1)=b02+b12+b22+2b1(b0+b2)(12sin2(ω2))+2b0b2(2(12sin2(ω2))21)a02+a12+a22+2a1(a0+a2)(12sin2(ω2))+2a0a2(2(12sin2(ω2))21)=b02+b12+b22+2b1(b0+b2)(12ϕ)+2b0b2(2(12ϕ)21)a02+a12+a22+2a1(a0+a2)(12ϕ)+2a0a2(2(12ϕ)21)=b02+b12+b22+2b1(b0+b2)(12ϕ)+2b0b2(18ϕ+8ϕ2)a02+a12+a22+2a1(a0+a2)(12ϕ)+2a0a2(18ϕ+8ϕ2)=b02+b12+b22+2b1b0+2b1b24(b1b0+b1b2)ϕ+2b0b216b0b2ϕ+16b0b2ϕ2a02+a12+a22+2a1a0+2a1a24(a1a0+a1a2)ϕ+2a0a216a0a2ϕ+16a0a2ϕ2=(b02+b12+b22+2b1b0+2b1b2+2b0b2)4(b1b0+b1b24b0b2)ϕ+16b0b2ϕ2(a02+a12+a22+2a1a0+2a1a2+2a0a2)4(a1a0+a1a24a0a2)ϕ+16a0a2ϕ2=14(b02+b12+b22+2b1b0+2b1b2+2b0b2)(b1b0+b1b24b0b2)ϕ+4b0b2ϕ214(a02+a12+a22+2a1a0+2a1a2+2a0a2)(a1a0+a1a24a0a2)ϕ+4a0a2ϕ2=(b0+b1+b22)2ϕ(4b0b2(1ϕ)+b1(b0+b2))(a0+a1+a22)2ϕ(4a0a2(1ϕ)+a1(a0+a2))

where ϕsin2(ω2)

if your gear is intending to plot this as dB, it comes out as

20log10|H(ejω)| = 10log10((b0+b1+b22)2ϕ(4b0b2(1ϕ)+b1(b0+b2)))10log10((a0+a1+a22)2ϕ(4a0a2(1ϕ)+a1(a0+a2)))

so your division turns into subtraction, but you have to be able to compute logarithms to some base or another. numerically, you will have much less trouble with this for low frequencies than doing it the apparent way.


2
That's really cool, thank you Robert! +1
jojek

@Robert I "believe" similar to my comment for Jojek above that this only applies as well when the coefficients are real (and therefore the spectrum is symmetric and thus the magnitude converts to cosines as you show)... Am I correct?
Dan Boschen

yes. that commitment is made when you go from the first line of |H(ejω)|2=... to the second line. no going back after that.
robert bristow-johnson
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.