デジタルフィルタ

 覚え書き、もしくは落書きです。

窓関数

つかいかた

遅延を基準にする
  • 目的のサイドローブレベルを満たす窓関数を選んでくる
  • メインローブが最初に0になる周波数が \(f\makeunit{Lf}\) だったとする
  • フィルタの遅延量 \(t_d\makeunit{s}\) を決める
  • 普通に設計すれば遅延は窓関数の長さの半分になるので、窓関数の長さは遅延の倍になり \(2t_d\makeunit{s}\)
  • このフィルタの遷移域の幅は \(f/(2t_d)\makeunit{Hz}\) になる
遷移域を基準にする
  • 目的のサイドローブレベルを満たす窓関数を選んでくる
  • メインローブが最初に0になる周波数が \(f\makeunit{Lf}\) だったとする
  • フィルタの遷移域の帯域幅 \(f_{tbw}\makeunit{Hz}\) を決める
  • メインローブはゼロを中心に左右にあるので、必要な窓関数の長さは \(2f/f_{tbw}\makeunit{s}\)
  • 遅延はその半分なので \(f/f_{tbw}\makeunit{s}\)

8ビットリサンプル用の窓関数


Frequency Range:

窓関数をサンプリングする

両端が0ではない窓関数のサンプリング

Sampling Frequency [Hz]:

ローパスフィルタ(LPF)

ローパスフィルタのインパルス応答

\begin{align*} h(t)&=\frac{1}{2\pi}\int_{-\omega_c}^{\omega_c} 1\cdot e^{j\omega t} d\omega \eol &=\frac{1}{2\pi}\int_{-\omega_c}^{\omega_c}e^{j\omega t} d\omega \eol &=\frac{1}{2\pi}\left[\frac{1}{jt}e^{j\omega t}\right]_{-\omega_c}^{\omega_c} \eol &=\frac{1}{2\pi}\left[\frac{{e^{j\omega_c\,t}}}{jt}-\frac{e^{-j\omega_c\,t}}{jt}\right] \eol &=\frac{e^{j\omega_c\,t}-e^{-j\omega_c\,t}}{2\pi jt} \eol &=\frac{2j\sin \omega_ct}{2j\pi t} \eol &=\frac{\sin \omega_ct}{\pi t} =\frac{\sin 2\pi f_ct}{\pi t} \tag{1}\eol &=\frac{\omega_c}{\omega_c}\frac{\sin \omega_ct}{\pi t} \eol &=\frac{\omega_c}{\pi}\frac{\sin \omega_ct}{\omega_c t} =2f_c\frac{\sin 2\pi f_ct}{2\pi f_ct} \end{align*}

FIRローパスフィルタ

\begin{align*} h_n &=\frac{\sin 2\pi f_cnT}{\pi nT} \eol &=2f_c\frac{\sin 2\pi f_cnT}{2\pi f_cnT} \end{align*}

Sampling Frequency [Hz]:


Waveform:


使いかた
描画関連

その他のフィルタ

オールパスフィルタ(APF)

バンドパスフィルタ(BPF、コサイン変調)

ハイパスフィルタ(HPF)

 2通りの係数計算方法がある。

周波数領域で1からLPFの特性を引く
  • 時間領域でも引き算でよいが、全帯域を1にしてしまうと時間領域ではインパルスになってしまって都合が悪い
  • オールパスフィルタ(APF)の結果を使えばよい、つまり、APFからLPFの特性を引けばよい
  • APFはサンプリングするときに位相をずらしていなければ中央で \(f_s\) 、その他は0なので、全体を \(f_s\) で割って正規化すれば、LPFの係数を全て符号反転した上で中央に1を足せばよい
LPFの特性をナイキスト周波数だけシフトする
  • HPFの特性と左右対称なLPFを作り、それをコサイン変調してナイキスト周波数だけ上にシフトする
  • LPFの中心は0Hzで、それをナイキスト周波数だけ上にシフトするので、中心はナイキスト周波数になり、これはつまりHPFである
  • ナイキスト周波数のコサイン波は1と-1を交互に繰り返すので、LPFの係数の奇数項の符号を反対にすればよい
その不思議を解き明かす

 実は完全に同じではない。 \(t=n/f_s\) の位置でサンプリングしている限り同じになる。

前者の方法

 素直にAPFの応答からLPFの応答を引く。

\begin{align*} h(t) &= f_s\frac{\sin \pi f_st}{\pi f_st} - 2f_c\frac{\sin 2\pi f_ct}{2\pi f_ct} \end{align*}

\(t=0\) の時はsinc関数の部分が1になり、

\begin{align*} h_0&=f_s-2f_c\eol \end{align*}

\(t\ne 0\) の場合、もし \(t=n/f_s\) の位置でサンプリングするならば、 第1項の分子は \(\sin\pi f_st\;\)\(=\sin(\pi f_sn/f_s)\;\)\(=\sin\pi t\) となり、これは常に0である。 したがって

\begin{align*} h_n &= - 2f_c\frac{\sin(2\pi f_cn/f_s)}{2\pi f_cn/f_s} \end{align*}
後者の方法

 ローパスフィルタのインパルス応答の \(f_c\) を \(f_s/2-f_c\) に置き換え、 \(\cos\pi f_st\) を乗じて計算を進める。 出発点はsinc関数の形にしたものではなく、項数の少ない (1) の式を使う。 途中、三角関数の積和公式を使っており、このときに係数1/2が付くことに注意。

\begin{align*} h(t)&=\frac{\sin 2\pi (f_s/2-f_c)t}{\pi t}\cdot\cos \pi f_st \eol &=\frac{1}{\pi t}\{\sin (\pi f_st-2\pi f_ct) \cdot \cos \pi f_st\} \eol &=\frac{1}{\pi t}\frac{1}{2}\{ \sin(\pi f_st-2\pi f_ct+\pi f_st) +\sin(\pi f_st-2\pi f_ct-\pi f_st) \} \eol &=\frac{1}{2\pi t}\{ \sin(2\pi f_st-2\pi f_ct) +\sin(-2\pi f_ct) \} \eol &=\frac{\sin(2\pi f_st-2\pi f_ct)}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \tag{2}\eol \end{align*}

とりあえず \(t=0\)の時のことを考える。 sinc関数に直す必要があり、

\begin{align*} h(t)&=\frac{\sin(2\pi f_st-2\pi f_ct)}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \tag{2}\eol &=\frac{\sin 2\pi (f_s-f_c)t}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \tag{3}\eol &=(f_s-f_c)\frac{\sin 2\pi (f_s-f_c)t}{2\pi(f_s-f_c)t}-f_c\frac{\sin 2\pi f_ct}{2\pi f_ct} \eol \end{align*}

\(t=0\) の時はsinc関数の部分が1になり、

\begin{align*} h_0&=(f_s-f_c)-f_c\eol &=f_s-2f_c\eol \end{align*}

\(t\ne 0\) の場合、もし \(t=n/f_s\) の位置でサンプリングするならば、

\begin{align*} h(t)&=\frac{\sin(2\pi f_st-2\pi f_ct)}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \tag{2}\eol &=\frac{\sin(2\pi f_sn/f_s-2\pi f_ct)}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \eol &=\frac{\sin(2\pi n-2\pi f_ct)}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \eol &=-\frac{\sin2\pi f_ct}{2\pi t}-\frac{\sin 2\pi f_ct}{2\pi t} \eol &=-2\frac{\sin2\pi f_ct}{2\pi t} \eol &=-2f_c\frac{\sin2\pi f_ct}{2\pi f_ct} \eol h_n&=-2f_c\frac{\sin(2\pi f_cn/f_s)}{2\pi f_cn/f_s} \end{align*}

これはどちらも前者の方式と一致する。 したがって \(t=n/f_s\) の位置でサンプリングしている限り、両者は一致する。

 ただ、意味的には若干違いがあり、APFからLPFを引く場合は周波数特性としては \(\pm f_s/2\) の外は0である。 コサイン変調した場合は (3) の式を吟味すると分かる通り、カットオフ周波数 \(f_s-f_c\) のLPFの特性から、同 \(f_c\) の特性を引いたものの半分になっている。 \(f_c\;\)\(=f_s/2\;\)\(-f_s/2\;\)\(+f_c\;\)\(=f_s/2\;\)\(-(f_s/2\;\)\(-f_c)\)で、 \(f_s\;\)\(-f_c\;\)\(=f_s/2\;\)\(+(f_s/2\;\)\(-f_c)\) なので、結局、 \(f_s/2\;\)\(\pm(f_s/2\;\)\(-f_c)\) の範囲が残る。 カットオフ周波数 \(f_s/2\;\)\(-f_c\) のLPFをナイキスト周波数に移したのだから、こうなって当然である。

 ちょ、周波数特性の一部がナイキスト周波数を超えてるじゃん。

 まぁ、LPFをナイキスト周波数に移す時点で気がつけよ、っていう話である。 連続系では数式的には問題はなく、ただ、特性が想定とちょっと違う状態になる。 これを離散系で考えると、ナイキスト周波数 \(f_s/2\) よりも高い部分がそれより下に折り返してくるので振幅が2倍になり、最終的な特性が1番目の方法と同じになる。 そう思って見返してみると、コサイン変調したときにBPFのときには2倍しろって書いてあったけど、HPFでは書いてないでしょ?

  \(t=n/f_s\) 以外の位置でサンプリングする場合を見るため、両方の方法を係数値を連続系で計算し、中央から前後10.5サンプル時間を切り出したのがこれ。

実線が前者、破線が後者。ドットはサンプリング点で、両者のちょうど交点でサンプリングすることになるため、両者の係数列が一致する。 特に、カットオフを0[Hz]にした場合、前者はカットオフ \(fs/2\) のローパスフィルタになるのに対し、後者はカットオフ \(fs\) のローパスフィルタになるため、sinc関数の周期が2倍違う。 APFでやったようなサブサンプルの遅延も組み込む場合は気をつける必要があり、その場合は前者の方法にしないと正しい結果にならない。

 あ、ということはローパスフィルタの帯域を半分にして、コサイン変調先を \(f_s/2\) じゃなくて \((f_s/2\;\)\(+f_c)\;\)\(/2\) にして全体を2倍すれば一致しそうな気が(まずい、ネタを増やしてしまった)。 ただ、こうするとコサインが \(\pm 1\) にならなくなっておいしくないのだな。

 それにしてもハイパスフィルタのインパルス応答、変にうねうねしていて気持ち悪い。 周波数制限されてるからってのもあるんだろうけど。 もっとも、帯域制限しないと無限の周波数まで応答に含まれてしまうため計算に困ることになる。 どこかで帯域制限しないと計算できないし、帯域制限すればちゃんとした連続波形としてインパルス応答が計算できる。 まぁ、連続系で見た場合、もはやハイパスフィルタではなく、ただのバンドパスフィルタなわけだが…あぁ、バンドパスフィルタの応答が気持ち悪いのか…

バンドエリミネーションフィルタ(BEF)


29 Mar 2026: 「ローパスフィルタ」・「その他のフィルタ」を追加

08 Mar 2026: 「窓関数をサンプリングする」・「両端が0ではない窓関数のサンプリング」を追加

31 Jan 2026: 新規作成

ご意見・ご要望の送り先は あかもず仮店舗 の末尾をご覧ください。

Copyright (C) 2026 akamoz.jp