ITU-T G.227 にあるフィルタを実装して、無線機の特性試験の試験方法に登場する「疑似音声信号発生器」を WebAudio で作ってみる。
ITU-T G.227
Conventional Telephone Signal という名前の勧告。伝達関数が書いてある。600Hz ぐらいにピークのあるフィルタになっている。
ホワイトノイズをこのフィルタに通すことによって疑似音声となる。なので、この周波数特性を持つフィルタを設計する。
フィルタの設計方法
フィルタの知識がないので、試行錯誤しながら以下のようにすすめていった。
- 周波数特性をそのままFIRフィルタにする
- 最初から実数 FIR フィルタとして設計してみる
- 双一次変換を使って IIR フィルタにしてみる
結論からいえば、今回の場合はアナログフィルタの伝達関数が示されているので、そこからデジタル IIR フィルタに変換するのが一番良かった (と思う)
求めるのは Jupyter Notebook 上で行なった。
周波数特性をそのままFIRフィルタにする
FIR フィルタは周波数特性がわかっていれば IFFT で作ることができる。ほぼ何も考えずに作れる。
最初は対称をつくらず IFFT して、最後に実数だけとるのを作った。
実数 FIR フィルタとして設計する
フィルタを左右対称にすればほぼ実数フィルタになるはずだが、低域の減衰が急峻すぎるせいかこれでも虚数が出てきてしまう。しかたないのでこのまま虚数を捨てて実数フィルタとして評価した。
まぁまぁうまくいくけど、かなり重くなってしまう。そして、それなりに G.227 の特性から誤差が発生して気持ちがわるい。FIR なので次数を増やせばそれだけ近似はできるが、どんどん重くなっていく。
なお FIR フィルタを WebAudio で使いたい場合は、ConvolverNode を使えば良い。
アナログフィルタを双一次変換 (bilinear transform) してIIRフィルタを得て FIR フィルタで補正する
↑補正なし↓補正
アナログフィルタ(周波数連続という意味)からデジタルフィルタ(離散という意味)をつくる方法の一つに双一次変換がある。scipy で簡単にできるので、これを試す。
今回の場合、アナログの伝達関数はわかっているので、この規格に書いてある伝達関数を双一次変換してIIRフィルタの係数を得る。つまり以下を変換してデジタルフィルタを得たい。
なぜ微妙に括弧がついてるのかわからないが、結局これは次数ごとに書きなおすと見なれた以下の形になる。ほぼ scipy.signal.freqs などが受けとる形になっている。4次。
ただ、p が なので、これを角周波数 をとる関数に変えたい。
python で上記通り係数計算して、signal.bilinear() に渡してあげると、デジタルフィルタの係数になる。ただ、双一次変換は周波数歪みが起こるので、完全にアナログフィルタの特性と一致するわけではない。
こういう場合どうするのかよくわからなかったが、次数の少ない FIR で容易に補正できそうだったため、アナログフィルタの周波数特性との差分をとって補正する FIR フィルタを追加で設計する。
IIR フィルタを WebAudio で使う場合は IIRFilterNode を使えば良い。feedForward に分子 feedBack に分母の係数を渡せば動いてくれる。
ということでできたのが冒頭にリンクしたレポジトリとなる。https://github.com/cho45/pseudo-audio-signal