A08 Octaveでフィルタ設計fir1

室長:今回はoctaveを使って実用になるフィルタを作っていくのだ。とはいっても難しいことはない。面倒なことはすべてoctaveがやってくれる。今回はfir1という関数を使うぞ。この関数は直線位相のfirフィルタを計算してくれる。

助手:fir1の説明はoctaveを起動して’help fir1’と入力するんでしたね。簡単に説明をお願いします。

室長:最初の引数nはフィルタの次数だ。n+1がtap数になる。tap数は通常2の乗数にする。 次のwはband edgeの指定だ。0と1の間の値を指定する。

助手:あれ、サンプリング周波数fsは関係ないのですか?

室長:その通り。0.5を指定したフィルタをサンプリング周波数44.1kのデータに適応するとfs/2が1なので11025Hz、96kなら24kHzになる。

助手:おなじフィルタの周波数特性がサンプリング周波数によって変わるのか。ということはフィルタを設計する時にはサンプリング周波数を決めてから係数を計算しなければならないですね。

室長:そうじゃ。例えばカットオフ3kHzのローパスフィルタが欲しい場合にはサンプリング周波数別に係数を計算する必要があり、実際に再生する時にはサンプリング周波数にあった係数に切り替えなければならない。

助手:それは面倒ですね。

室長:別の手としてはサンプリング周波数を1つに決めて、再生ソフト側でサンプリングレートを変換してしまうというのがある。どちらがよいかはケースバイケースじゃな。デジタルチャンデバなどでもDCX2496はどの入力もすべて96kに変換して計算している。イコライザのAPEQ2ProDIOもすべての入力を48kHzに変換している。DEQXでは入力データのサンプリング周波数に応じて係数を切り替えているようじゃ。ワシは面倒が嫌いなのでサンプリングレートの方を変換して係数は1つでいくことにしてる。

助手:次のtypeはフィルタのタイプを指定するのですね。チャンネルデバイダを作るのに必要なのはローパス、バンドパス、ハイパスですね。

室長:それぞれ ‘low’ ‘pass’ ‘high’ を指定してやればよい。ただ’high’を指定するとnに偶数しか受け付けないので都合が悪い。したがってハイパスフィルタも’pass’を使って設計する。

助手:windowというのは何ですか?

室長:窓関数の指定だ。何種類もあるぞ。指定しなければハミング窓(hamming)が使われる。窓関数の説明は面倒なので省くが、窓関数によって帯域内のリップルや肩特性、阻止帯域の減衰量などが変わるのだ。まあ実際にやってみるのがよいだろう。

助手:どの窓関数を選べばよいのか教えてください。

室長:ワシはカイザー窓(kaiser)を使っておる。カイザー窓では長さのほかにパラメータとしてβ値を指定する。この値によって特性が変化するのだ。

助手:なぜカイザー窓を選んだんですか?

室長:名前が一番強そうじゃろ?

助手:……..

室長:とりあえず実際に計算してみよう。サンプリング周波数96kで3wayのミッドレンジという想定だ。300~2500Hzのバンドパスフィルタとする。tap数は512で計算する。

fs=96000;
tap=512;
cf=[300 2500];
w=cf/(fs/2);
a=fir1(tap-1,w,'pass');
b=fir1(tap-1,w,'pass',kaiser(tap,8));
clf;
hold on;
filterplot(a,fs,'1');
filterplot(b,fs,'2');

fig1 緑がβ8のカイザー窓、赤がデフォルトのハミング窓じゃ。阻止帯域の減衰量の違いがわかる。右の肩のところを拡大してみるぞ。 fig2 肩特性はハミング窓の方が良いのがわかる。一般的に阻止帯域の減衰量を多くすれば肩特性は悪くなる。

助手:なるほど、よくわかりますね。ところで2500Hzでのハイカットは良いのですが、左側の300Hzでのローカットは減衰量が全然足りませんよ。どうなっているのですか?

室長:これは簡単に言ってしまえばtap数が足りないのだ。またハイカットとローカットで特性が違うように見えるが実は同じなのだ。長くなったのでこのへんの話は次回にするぞ。

2012年12月12日