[ Jpn | Eng ]

Main Menu



Recent

最近の記事

Search

サイト内検索:

Archive

Powered by
MTOS 5.2.2


g200kg > Web Audio API 解説 > 04.ノードの接続

Web Audio API 解説

2016/11/14

04.ノードの接続



ノードを繋ぐ

今までの例でも既に使いましたが、ノードを接続するには connect() 関数を使用します。

sourceNode.connect(destinationNode [,output [,input]])

という形式です。追加パラメータの output、inputはノードに複数の出力や入力がある場合にそれを指定するものですが、ほとんどのノードは入出力端子を1つしか持っていませんので、通常は sourceNode.connect(destinationNode)という使い方になります。

複数の出力を持っているのはステレオ2chや5.1chのマルチチャンネル信号を分解して独立した出力として取り出す ChannelSplitter 、複数の入力を持っているのは独立した複数の信号から2chステレオや5.1chのマルチチャンネル信号を作り出す ChannelMerger だけです。

また接続を切るには、

sourceNode.disconnect([output])
または
souceNode.disconnect(destination [,output [,input]]);

を使用します。追加パラメータの output および input は connect()の時と同じく、複数の出力や入力がある場合(つまりChannelSplitter、ChannelMerger関係)でしか使用しません。

単純に sourceNode.disconnect() を呼び出すとsourceNodeから接続されているすべてのコネクションがまとめて切られます。また、sourceNode.disconnect(destinationNode) で接続先を指定した場合は sourceNode から destinationNode への接続だけが切られます。
初期の仕様では、sourceNode.disconnect(destinationNode) の形式がサポートされていなくて、まとめて切るしかなく、複雑なルーティングをダイナミックに切り替えるアプリの場合に随分と面倒な事になっていたのですが、WebAudio API の仕様も随分使いやすくなってきています。

ファンインとファンアウト

ノードの接続は1対1に限りませんので、1つの出力から複数の入力に接続(ファンアウト)したり1つの入力に対して複数の出力を接続(ファンイン)したりする事が可能です。1つの出力を複数の入力に接続した場合は同じものが複数の入力に渡されるだけですが、1つの入力に対して複数の出力を接続した場合は自動的にミックスの処理が行われます。

このミックス処理は単なる加算ですので、複数の信号のピークがたまたま重なるとそれだけ大きな信号になるという事は意識しておく必要があります。

ゲームアプリで不特定数の音源が現れる可能性がある場合などは最後にコンプレッサーを入れるとか、同時発音数の決まっているポリフォニックな楽器ならあらかじめマージンを取っておくなどの対処が必要になります。

ちなみにポリフォニック楽器でのマージンの取り方は Web Audio APIに限った事ではなくソフトシンセのノウハウとして結構重要なんですが、真面目に最悪ケースを考えて 1/音源数 だと音が小さくなりすぎるので 1/(音源数の平方根) なんかを使うケースが多いです。これはつまり音源数の変化に対して RMS パワーを一定にするという意味があります。たまたま全音源の位相があっちゃったりするとピークが潰れるんですけどね。


ノードからパラメータへの接続

connect()は信号の出力をノードの入力に繋ぐだけではなく、ノードの AudioParam 型のパラメータに接続する事もできます。例えばオシレータの frequencyパラメータはAudioParamなのでここに別のオシレータを接続してビブラートを掛ける、というような使い方ができます。シンセサイザーで言えば LFO で VCO をモジュレーションする、という感じです。

この例のコードは次のようになります。

<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>Vibrato Test</h1>
<img src="images/vibrato.png"/><br/>
<table>
<tr><td>LFO Freq : </td><td><input type="text" size="10" id="lfofreq" value="5"/></td></tr>
<tr><td>Depth    : </td><td><input type="text" size="10" id="depth" value="10"/></td></tr>
<tr><td>VCO Freq : </td><td><input type="text" size="10" id="vcofreq" value="440"/></td></tr>
</table>
<br/>
<button onclick="Setup()">Play</button><br/>
<script type="text/javascript">

window.AudioContext = window.webkitAudioContext||window.AudioContext;
var audioctx = new AudioContext();

var play = 0;
var vco = audioctx.createOscillator();
var lfo = audioctx.createOscillator();

var depth = audioctx.createGain();

vco.connect(audioctx.destination);
lfo.connect(depth);
depth.connect(vco.frequency);	// <== connect to frequency parameter of vco

function Setup() {
	if(play == 0) {
		play = 1;
		vco.start();
		lfo.start();
	}
	vco.frequency.value = parseFloat(document.getElementById("vcofreq").value);
	lfo.frequency.value = parseFloat(document.getElementById("lfofreq").value);
	depth.gain.value = parseFloat(document.getElementById("depth").value);
	
}
</script>

</body>
</html>
テストページ:ビブラート

さて、この例ではオシレーターの出力を別のオシレータの frequency に接続したのですが、frequencyには.valueプロパティがあってそちらにも数値が入っています。この数値の扱いは複数の信号が入力された時と同様に単なる加算となります。

つまり、.valueに440があってコネクションから(-10~+10)の信号が入ってくるとすると、オシレータの周波数は (430 ~ 450)Hzの範囲でビブラートがかかります。




g200kg