diff --git a/docs/images/iir-filter-node.png b/docs/images/iir-filter-node.png new file mode 100644 index 0000000..53d6203 Binary files /dev/null and b/docs/images/iir-filter-node.png differ diff --git a/docs/index.html b/docs/index.html index a30d4be..97594d4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -8103,6 +8103,98 @@
All-Pass Filter
+
+

IIRFilterNode

+

+ BiquadFilterNode では実装できない IIR フィルタを実装する場合, 次の手段としては, + IIRFilterNode クラスを利用することです (最後の手段は, AudioWorklet で実装することです). +

+

+ IIRFilterNode では, BiquadFilterNode でフィルタの特性に影響を与えていた, frequency プロパティや + Q プロパティ, gain プロパティなどは, リアルタイムに変化させることができなくなる点には注意してください. + IIRFilterNode に与えるパラメータは, AudioParam ではないからです. +

+

+ 実装としては, IIRFilterNode コンストラクタの第 2 引数に, IIRFilterOptions として, + フィルタの係数の配列を設定します. IIRFilterOptions オブジェクトの feedforward プロパティは, + IIR フィルタの伝達関数の分子となる係数 (以下の伝達関数の $b_{m}$), + feedback プロパティは, IIR フィルタの伝達関数の分母となる係数 (以下の伝達関数の + $a_{n}$) をそれぞれ設定します (ファクトリメソッドの場合, 第 1 引数に feedforward, 第 2 引数に + feedback を指定します). IIRFilterNode の伝達関数は以下の定義式となります. + BiquadFilterNode の伝達関数と異なり, フィルタの次数を自由に設定できる点に着目してください. +

+
+ + $ + \begin{flalign} + &H\left(z\right) = \frac{\sum_{m=0}^{M}b_{m}z^{-m}}{\sum_{n=0}^{N}a_{n}z^{-n}} + \end{flalign} + $ +
+

+ ただし, まったく制約がないわけではなく, 0 次のフィルタはエラーとなります (それ以外にも, $a_{0}$ は, + 0 以外の値である必要があったり, 係数がすべて 0feedforward はエラーとなったりします). また, 実装上, + 20 次までのフィルタが上限となります. +

+

簡易的ではありますが, 1 次の IIR フィルタによる, Low-Pass Filter と High-Pass Filter の実装例です.

+
const context = new AudioContext();
+
+const cutoff = 1000;  // 1000 Hz
+
+const b = (cutoff / context.sampleRate) * Math.PI;
+
+const b0 = b;
+const b1 = b;
+const a0 =  1 + b;
+const a1 = -1 + b;
+
+const feedforward = new Float64Array([b0, b1]);
+const feedback    = new Float64Array([a0, a1]);
+
+const oscillator = new OscillatorNode(context, { type: 'sawtooth' });
+const filter     = new IIRFilterNode(context, { feedforward, feedback });
+
+// If use `createIIRFilter`
+// const filter = context.createIIRFilter(feedforward, feedback);
+
+// OscillatorNode (Input) -> IIRFilterNode (Low-Pass Filter) -> AudioDestinationNode (Output)
+oscillator.connect(filter);
+filter.connect(context.destination);
+
+oscillator.start(0);
+
const context = new AudioContext();
+
+const cutoff = 4000;  // 4000 Hz
+
+const a = (cutoff / context.sampleRate) * Math.PI;
+
+const b0 =  1;
+const b1 = -1;
+const a0 =  1 + a;
+const a1 = -1 + a;
+
+const feedforward = new Float64Array([b0, b1]);
+const feedback    = new Float64Array([a0, a1]);
+
+const oscillator = new OscillatorNode(context, { type: 'sawtooth' });
+const filter     = new IIRFilterNode(context, { feedforward, feedback });
+
+// If use `createIIRFilter`
+// const filter = context.createIIRFilter(feedforward, feedback);
+
+// OscillatorNode (Input) -> IIRFilterNode (High-Pass Filter) -> AudioDestinationNode (Output)
+oscillator.connect(filter);
+filter.connect(context.destination);
+
+oscillator.start(0);
+ IIRFilterNode +