Web Audio API:コーディングできるのになぜ作曲するのですか?
公開: 2022-03-11WebオーディオAPIの最初のドラフトは、2011年にW3Cに登場しました。Webページのオーディオは長い間サポートされてきましたが、Webブラウザからオーディオを生成する適切な方法はごく最近まで利用できませんでした。 私は個人的にこれをグーグルクロームに帰します、なぜならグーグルの利益に関しては、ブラウザがコンピュータの最も重要な部分になり始めたからです。 覚えているかもしれませんが、Google Chromeが登場するまで、Webブラウザの領域はあまり変化し始めませんでした。 今回、Webページでサウンドを使用した場合、設計上の決定は不十分でした。 しかし、Web実験のアイデアが登場して以来、Webオーディオは再び意味をなし始めました。 最近のWebブラウザーは、芸術的な表現のためのもう1つのツールであり、Webブラウザーのビデオとオーディオはその中で重要な役割を果たします。
Web Audio APIはまだ開発中であるため、一部の目的では非常に使いにくい場合がありますが、作業を簡単にするために多数のJavaScriptライブラリがすでに存在します。 この場合、Tone.jsというライブラリを使用してWebAudioAPIを使い始める方法を紹介します。 これにより、基本を学ぶだけで、ブラウザのサウンドのニーズのほとんどをカバーできるようになります。
Hello Web Audio API
入門
ライブラリを使用せずに開始します。 最初の実験では、3つの正弦波を作成します。 これは簡単な例であるため、hello.htmlという名前のファイルを1つだけ作成します。これは、少量のマークアップを含む裸のHTMLファイルです。
<!DOCTYPE html> <html> <head> <meta charset="utf‐8"> <title> Hello web audio </title> </head> <body> </body> <script> </script> </html>
Web Audio APIの中核は、オーディオコンテキストです。 オーディオコンテキストは、Webオーディオに関連するすべてのものを含むオブジェクトです。 1つのプロジェクトに複数のオーディオコンテキストを含めることは良い習慣とは見なされません。 まず、MozillaのWebAudioAPIドキュメントに記載されている推奨事項に従ってオーディオコンテキストをインスタンス化します。
var audioCtx = new (window.AudioContext || window.webkitAudioContext);
発振器を作る
オーディオコンテキストがインスタンス化されると、オーディオコンポーネントがすでにあります:audioCtx.destination。 これはあなたのスピーカーのようなものです。 音を出すには、それをaudioCtx.destinationに接続する必要があります。 サウンドを生成するために、オシレーターを作成しましょう。
var sine = audioCtx.createOscillator();
素晴らしいですが、十分ではありません。 また、開始してaudioCtx.destinationに接続する必要があります。
sine.start(); sine.connect(audioCtx.destination);
これらの4行を使用すると、正弦波を再生する非常に迷惑なWebページが作成されますが、モジュールが相互に接続する方法を理解できました。 次のスクリプトでは、出力に接続された3つの正弦波トーンがあり、それぞれが異なるトーンを持っています。 コードは非常に自明です:
//create the context for the web audio var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); //create, tune, start and connect each oscillator sinea, sineb and sinec var sinea = audioCtx.createOscillator(); sinea.frequency.value = 440; sinea.type = "sine"; sinea.start(); sinea.connect(audioCtx.destination); var sineb = audioCtx.createOscillator(); sineb.frequency.value = 523.25; sineb.type = "sine"; sineb.start(); sineb.connect(audioCtx.destination); var sinec = audioCtx.createOscillator(); sinec.frequency.value = 698.46; sinec.type = "sine"; sinec.start(); sinec.connect(audioCtx.destination);
発振器は正弦波に限定されませんが、MDNで述べられているように、三角形、のこぎり波、正方形、カスタム形状にすることもできます。
Webオーディオのパッチロジック
次に、Webオーディオコンポーネントのオーケストラにゲインモジュールを追加します。 このモジュールを使用すると、サウンドの振幅を変更できます。 ボリュームノブに似ています。 すでに接続機能を使用して、オシレーターをオーディオ出力に接続しています。 同じ接続機能を使用して、任意のオーディオコンポーネントを接続できます。 Firefoxを使用していて、Webオーディオコンソールを見ると、次のように表示されます。
音量を変更したい場合、パッチは次のようになります。
つまり、オシレーターはオーディオデスティネーションに接続されておらず、代わりにゲインモジュールに接続されており、そのゲインモジュールはデスティネーションに接続されています。 あなたがギターのペダルとケーブルでこれをすることを常に想像するのは良いことです。 コードは次のようになります。
var audioCtx = new (window.AudioContext || window.webkitAudioContext) // we create the gain module, named as volume, and connect it to our var volume = audioCtx.createGain(); volume.connect(audioCtx.destination); //these sines are the same, exept for the last connect statement. //Now they are connected to the volume gain module and not to the au var sinea = audioCtx.createOscillator(); sinea.frequency.value = 440; sinea.type = "sine"; sinea.start(); sinea.connect(volume); var sineb = audioCtx.createOscillator(); sineb.frequency.value = 523.25; sineb.type = "sine"; sineb.start(); sineb.connect(volume); var sinec = audioCtx.createOscillator(); sinec.frequency.value = 698.46; sinec.type = "sine"; sinec.start(); sinec.connect(volume); volume.gain.value=0.2;
解決策はhttps://github.com/autotel/simple-webaudioapi/にあります。
GainNodeは最も基本的なエフェクトユニットですが、ディレイ、コンボルバー、バイクアッドフィルター、ステレオパンナー、ウェーブシェイパーなどもあります。 Tone.jsなどのライブラリから新しいエフェクトを取得できます。
これらのサウンドパッチの1つを独自のオブジェクトに保存すると、必要に応じてそれらを再利用し、より少ないコードでより複雑なオーケストレーションを作成できます。 これは、将来の投稿のトピックになる可能性があります。
Tone.jsで物事を簡単にする
バニラWebオーディオモジュールがどのように機能するかを簡単に見てきたので、すばらしいWebオーディオフレームワークであるTone.jsを見てみましょう。 これ(およびユーザーインターフェイスコンポーネント用のNexusUI)を使用すると、より興味深いシンセサイザーやサウンドを非常に簡単に作成できます。 試してみるために、サンプラーを作成し、それにユーザーインタラクティブ効果を適用してから、このサンプルにいくつかの簡単なコントロールを追加します。

Tone.jsサンプラー
簡単なプロジェクト構造を作成することから始めることができます。
simpleSampler |-- js |-- nexusUI.js |-- Tone.js |-- noisecollector_hit4.wav |-- sampler.html
JavaScriptライブラリはjsディレクトリにあります。 このデモでは、Freesound.orgからダウンロードできるNoiseCollectorのhit4.wavファイルを使用できます。
Tone.jsは、Playerオブジェクトを介してその機能を提供します。 オブジェクトの基本的な機能は、サンプルをロードし、それをループまたは1回再生することです。 ここでの最初のステップは、sampler.htmlファイル内の「sampler」変数にプレーヤーオブジェクトを作成することです。
<!doctype html> <html> <head> <title> Sampler </title> <script type="text/javascript" src="js/nexusUI.js" ></script> <script type="text/javascript" src="js/Tone.js" ></script> <script> var sampler = new Tone.Player("noisecollector_hit4.wav", function() { console.log("samples loaded"); }); </script> </head> <body> </body> </html>
プレーヤーコンストラクターの最初のパラメーターはWAVファイルの名前であり、2番目のパラメーターはコールバック関数であることに注意してください。 サポートされているファイルの種類はWAVだけではありません。互換性は、ライブラリよりもWebブラウザに依存します。 コールバック関数は、プレーヤーがサンプルをバッファーにロードし終えたときに実行されます。
また、サンプラーを出力に接続する必要があります。 これを行うTone.jsの方法は次のとおりです。
sampler.toMaster();
…ここで、samplerは10行目以降のTone.Playerオブジェクトです。toMaster関数はconnect(Tone.Master)の省略形です。
開発者コンソールを開いた状態でWebブラウザーを開くと、プレーヤーが正しく作成されたことを示す「サンプルが読み込まれました」というメッセージが表示されます。 この時点で、サンプルを聞きたいと思うかもしれません。 そのためには、Webページにボタンを追加し、一度押すとサンプルを再生するようにプログラムする必要があります。 本文でNexusUIボタンを使用します。
<canvas nx="button"></canvas>
これで、丸みを帯びたボタンがドキュメントにレンダリングされているのがわかります。 サンプルを再生するようにプログラムするには、次のようなNexusUIリスナーを追加します。
button1.on('*',function(data) { console.log("button pressed!"); })
NexusUIの優れた点は、NexusUI要素ごとにグローバル変数を作成することです。 これを行わないようにNexusUIを設定し、代わりにnx.globalWidgetsをfalseに設定することで、これらの変数をnx.widgets[]にのみ含めることができます。 ここでは、いくつかの要素を作成するので、この動作に固執します。
jQueryの場合と同様に、これらの.onイベントを配置でき、最初の引数はイベント名になります。 ここでは、ボタンに対して行われたすべての機能を割り当てています。 これは「*」と書かれているものは何でも。 NexusUIAPIの各要素のイベントについて詳しく知ることができます。 ボタンを押したときにメッセージをログに記録する代わりにサンプルを再生するには、サンプラーの開始機能を実行する必要があります。
nx.onload = function() { button1.on('*',function(data) { console.log("button pressed!"); sampler.start(); }); }
また、リスナーがonloadコールバック内に入ることに注意してください。 NexusUI要素はキャンバスに描画され、nxがonload関数を呼び出すまでそれらを参照することはできません。 jQueryのDOM要素で行うのと同じように。
このイベントは、マウスを押したときと離したときにトリガーされます。 プレス時にのみトリガーされるようにする場合は、event.pressが1に等しいかどうかを評価する必要があります。
これにより、押すたびにサンプルを再生するボタンが必要になります。 sampler.retriggerをtrueに設定すると、サンプルが再生されているかどうかに関係なく、サンプルを再生できるようになります。 それ以外の場合は、サンプルを再トリガーするためにサンプルが終了するまで待つ必要があります。
効果の適用
Tone.jsを使用すると、簡単に遅延を作成できます。
var delay= new Tone.FeedbackDelay("16n",0.5).toMaster();
最初の引数は遅延時間です。これは、ここに示すように記譜法で記述できます。 2つ目はウェットレベルです。これは、元のサウンドとそれに影響を与えるサウンドの混合を意味します。 ディレイの場合、通常は100%ウェットにする必要はありません。これは、ディレイが元のサウンドに関して興味深いものであり、ウェットだけでは両方が一緒になってあまり魅力的ではないためです。
次のステップは、サンプラーをマスターから取り外し、代わりにディレイに接続することです。 サンプラーがマスターに接続されているラインを微調整します。
sampler.connect(delay);
ボタンをもう一度試して、違いを確認してください。
次に、ドキュメントの本文に2つのダイヤルを追加します。
<canvas nx="dial"></canvas> <canvas nx="dial"></canvas>
そして、NexusUIlistenerを使用して、ダイヤルの値を遅延効果に適用します。
dial1.on('*',function(data) { delay.delayTime.value=data.value; }) dial2.on('*',function(data) { delay.feedback.value=data.value; })
各イベントで微調整できるパラメーターは、Tone.jsのドキュメントに記載されています。 遅れて、ここにあります。 これで、例を試して、NexusUIダイヤルで遅延パラメーターを微調整する準備が整いました。 このプロセスは、エフェクトだけでなく、各NexusUI要素で簡単に実行できます。 たとえば、別のダイヤルを追加し、そのリスナーを次のように追加してみてください。
dial3.on('*',function(data) { sampler.playbackRate=data.value; })
これらのファイルはgithub.com/autotel/simpleSamplerにあります。
結論
これらのAPIを試したとき、頭に浮かんだすべての可能性とアイデアに圧倒され始めました。 このオーディオの実装と従来のデジタルオーディオの実装の大きな違いは、オーディオ自体ではなく、コンテキストにあります。 ここに合成を行う新しい方法はありません。 むしろ革新は、オーディオと音楽の作成が現在Webテクノロジーに適合していることです。
私は個人的に電子音楽制作に携わっていますが、この分野では、実際に音楽を演奏することと、録音したトラックを再生することとの間のあいまいさというパラドックスが常にありました。 ライブの電子音楽を実際に作成したい場合は、ライブの即興演奏用に独自のパフォーマンスツールまたは「音楽作成ロボット」を作成できる必要があります。 しかし、電子音楽の演奏が、事前に準備された音楽作成アルゴリズムのパラメーターを微調整するだけになる場合は、聴衆もこのプロセスに関与することができます。 私はクラウドソーシングされた音楽のためのウェブとオーディオのこの統合に関する小さな実験に取り組んできました、そしておそらくすぐに私たちは音楽が彼らのスマートフォンを通して聴衆から来るパーティーに参加するでしょう。 結局のところ、それは私たちが洞窟時代に楽しんだかもしれないリズミカルなジャムとそれほど違いはありません。
Toptal Engineeringブログでさらに読む:
- WebAssembly / Rustチュートリアル:ピッチパーフェクトなオーディオ処理
- MIDIチュートリアル:MIDIハードウェアによって制御されるブラウザベースのオーディオアプリケーションの作成