室長:octaveの基本文法は他のサイトをあたってくれ。とりあえず前回の解説をするぞ。最初の行はaに行ベクトルを格納している。セミコロン(;)は出力を抑制するときにつける。つぎの行はfreqzという関数でフィルタを計算している。freqzの説明はoctaveのコマンドラインで
help freqz
とすれば表示される。freqzが定義されているファイルの場所も表示されるはずじゃ。必要とあればfreqz.mの内容をみてどういう計算がされているのか知ることも出来る。最後の3行目だがこれはsemilogxという関数でX軸を対数表示にしてグラフを描いている。普通のグラフはplot、y軸が対数の場合にはsemilogyじゃ。
20*log10()というのは何をしているのかわかるな?
助手:それくらいは私でも解ります。dBに変換しているんですよ。n倍をdBにするには
20*log10(n)
n dBが何倍かの計算は
10^(n/20)
です。
室長:それではdB計算を関数にしてみてくれ。
助手:えーと、functionとendfunctionで挟めばいいんでしたね。
function db = a2db (a)
db=20*log10(a);
endfunction
function a = db2a (db)
a=10.^(db/20);
endfunction
こんな感じでどうですか。aやdbはローカル変数となって他には影響しないんですよね。
室長:よいだろう。ただ毎回これを入力するのは手間なので関数ファイルというのをつくる。1個の関数をコメントをつけて1つのファイルにする。”ファイル名は間数名.m”とする。ファイルの場所はパスが通っている場所にする。カレントディレクトリならOKじゃ。べつのディレクトリにするばあいには ~/.octaverc
ファイルを作ってaddpath (“パスをとおすディレクトリの絶対パス”);とでもしとけば良い。
a2db.m
#function db = a2db (a)
#増幅率をdBに変換
#
function db = a2db (a)
db=20*log10(a);
endfunction
db2a.m
#function a = db2a (db)
#dBを増幅率に変換する
#
function a = db2a (db)
a=10.^(db/20);
endfunction
この2つのファイルを作っておけばいちいち入力しなくても最初から組み込まれている関数のように使えるのだ。他の関数から呼び出すことも可能じゃ。help a2dbとすればコメントが表示されるぞ。
ではフィルタを表示するfilterplotという関数を作ってみてくれ。コメントも忘れずにな。今作った関数a2dbもそのまま使用できるぞ。
助手:出来ました。
filterplot.m
#function filterplot (a,fs[,n][,fmt])
#フィルタaのグラフをdB表示、x軸対数で表示
#nを省略すれば4096
function filterplot (a,fs,n,fmt)
n1=4096;
fmt1='3';
if (exist("n") && ischar(n))
fmt1=n;
elseif (exist("n"))
n1=n;
if (exist("fmt"))
fmt1=fmt;
endif
endif
[h,w]=freqz(a,1,n1,fs);
semilogx(w,a2db(abs(h)),fmt1);
grid on;
endfunction
室長:センスのない関数だな。まあ動けばよい。これでfilterplot(a,44100);と入力するだけでグラフが表示できる。この関数ファイルはこれからも使うので作って保存しておいてくれ。次回はoctave-signalにあるfir1という関数を使ってフィルタを設計してみよう。
2012年12月11日