MATLABの関数にあるconvを使わないで以下の式を実現したくてプログラムを作成しているのですが出力結果がうまくいかず解決方法に悩んでいます。教えていただけないでしょうか。1つ前にも同様の質問をしていますが、プログラムを修正しています。
具体的にはフィルタ係数a,bを指定する際にa,bともに1より大きな値で指定するとfilter(b,a,x)でプロットした結果と一致するのですが、フィルタ係数を1より小さい値にしたときに一致しません。
matlab
1prompt = 'What is the value of "a" ? '; 2a = input(prompt); 3prompt = 'What is the value of "b" ? '; 4b = input(prompt); 5 6N=49; 7x = [1; zeros(N,1)]; 8 9 10 11b_length=length(b); 12a_length=length(a); 13k1=length(x)+length(b)-1; 14y1=zeros(1,N); 15y2=zeros(1,N); 16 17x1=length(x); 18y=zeros(1,N); 19 20 21 for n=1:k1 22 for k=max(1,n+1-x1):min(n,b_length) 23 24 y1(n)=y1(n)+x(n-k+1)*b(k); 25end 26 27 28%for m=1:a_length 29for m=max(1,n+1-x1):min(n,a_length) 30 y2(n)=y2(n)+y(n-m+1)*(-a(m)); 31 32 33end 34y(n)=y1(n)+y2(n); 35end 36plot(y) 37xlim([0 50]) 38
コードを詳しく読んでませんが、とりあえず気づいたことだけ書きます
[その1]
https://jp.mathworks.com/help/matlab/ref/filter.html#buagwwg-2
の「詳細」の「有理伝達関数」の、
「有理伝達関数は、次の差分方程式で表すこともできます。」
と書かれてるところのすぐ下の式を見てください
「a(1)」は左辺の係数であり、右辺で使われているのは「a(2)」以降です
質問に記載の式に合わせて「y(n)=...」とするには、右辺全体を「a(1)」で割ります
a(1)を使うのはそこだけで、a(2)以降の使い方の個別のy()との掛け算には使いません
a(1)の扱いが異なるので、質問者さんが書いたコードと
filter(b,a,x)
の結果は同じにはならないと思います
for m=max(1,n+1-x1):min(n,a_length)
を、a(1)を使わないように
for m=max(2,n+2-x1):min(n,a_length)
に変えて、
y(n)=y1(n)+y2(n);
を
y(n)=(y1(n)+y2(n))/a(1);
に変えるのではないですかね
[その2]
質問のコードを実行してもエラーになります
y1, y2, yのサイズは
y1=zeros(1,N);
y2=zeros(1,N);
y=zeros(1,N);
なので、どれもN=49です
k1は
k1=length(x)+length(b)-1;
なので、length(x)=50以上ですから、
for n=1:k1
でnは50以上になり、そのループ内での
y1(n)=...
y2(n)=...
y(n)=...
で、サイズが49しかないy1, y2, yに、それよりも大きなnでアクセスしようとして、エラーになります
y1, y2, yのサイズを、
y1=zeros(1,x1);
y2=zeros(1,x1);
y=zeros(1,x1);
でxと同じx1にして、
for n=1:k1
を
for n=1:x1
に変えるのではないですかね