coswinという関数が窓を計算してます
2*2-1といったら1のことなので念のため
canvasの横方向1ピクセルにつきひとつ、値を計算している
devicePixelRatioを乗じた値
canvasのピクセル数分行うため重いが、ブラウザの横幅を小さくするか、窓関数の長さを短くすれば快適になる
2通りの係数計算方法がある。
実は完全に同じではない。 \(t=n/f_s\) の位置でサンプリングしている限り同じになる。
素直にAPFの応答からLPFの応答を引く。
\(t=0\) の時はsinc関数の部分が1になり、
\(t\ne 0\) の場合、もし \(t=n/f_s\) の位置でサンプリングするならば、 第1項の分子は \(\sin\pi f_st\;\)\(=\sin(\pi f_sn/f_s)\;\)\(=\sin\pi t\) となり、これは常に0である。 したがって
ローパスフィルタのインパルス応答の \(f_c\) を \(f_s/2-f_c\) に置き換え、 \(\cos\pi f_st\) を乗じて計算を進める。 出発点はsinc関数の形にしたものではなく、項数の少ない (1) の式を使う。 途中、三角関数の積和公式を使っており、このときに係数1/2が付くことに注意。
とりあえず \(t=0\)の時のことを考える。 sinc関数に直す必要があり、
\(t=0\) の時はsinc関数の部分が1になり、
\(t\ne 0\) の場合、もし \(t=n/f_s\) の位置でサンプリングするならば、
これはどちらも前者の方式と一致する。 したがって \(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\) にならなくなっておいしくないのだな。
それにしてもハイパスフィルタのインパルス応答、変にうねうねしていて気持ち悪い。 周波数制限されてるからってのもあるんだろうけど。 もっとも、帯域制限しないと無限の周波数まで応答に含まれてしまうため計算に困ることになる。 どこかで帯域制限しないと計算できないし、帯域制限すればちゃんとした連続波形としてインパルス応答が計算できる。 まぁ、連続系で見た場合、もはやハイパスフィルタではなく、ただのバンドパスフィルタなわけだが…あぁ、バンドパスフィルタの応答が気持ち悪いのか…
29 Mar 2026: 「ローパスフィルタ」・「その他のフィルタ」を追加
08 Mar 2026: 「窓関数をサンプリングする」・「両端が0ではない窓関数のサンプリング」を追加
31 Jan 2026: 新規作成
ご意見・ご要望の送り先は あかもず仮店舗 の末尾をご覧ください。
Copyright (C) 2026 akamoz.jp