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)信号に入力して、フィルターの応答を計算し、そのFFTを取得する必要があります。

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
詳細な説明
パルティーダ

私はこの行を考えていますa = [1 -0.5 -0.25]; % Some filter with lot's of static gain。ここでこれらのパラメーターの選択について説明してください。私はMatlabのマニュアルを読んでおり[h,w] = freqz(hfilt,n)、シナプスの一部でそれを述べています。に2つのフィルター(a、b)を与えていfreqzます。両方のフィルターが入っていhfiltますか?それとも1つn
レオレオポルドヘルツ

他の人のために明確にするために、「2 piまで上げる必要はありません」とは、係数が実数である場合です。複素係数を持つフィルターのアプリケーションがあり、その場合、スペクトルはもはや対称ではなくなり、その場合、周波数を2 piに拡張する必要があります。
ダンボスチェン

14

これはjojekの答えの補遺であり、倍精度の数学を使用した場合により一般的で完全に適切です。精度が低い場合、周波数応答の周波数が非常に低い(ナイキストよりはるかに低い)場合、およびフィルターの共振周波数が非常に低い場合に生じる「余弦問題」があります。

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

このトリガーIDを検討してください。

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ω)

so, one can see that the magnitude frequency response |H(ejω)| is an even symmetry function and depends only on the cosines cos(ω) and cos(2ω). for very low ω, the values of those cosines are so close to 1 that, with single-precision fixed or floating point, there are few bits remaining that differentiate those values from 1. that is the "cosine problem".

using the trig identity above, you get for magnitude squared:

|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.