Web audio API✕Web Workersでシンセサイザー裏話

HTML5のシンセライブラリは6月中旬から作りはじめデモコンテンツを完成させるまでに約3週間かかったのですが、 その間様々な壁に当たりました。

Javascriptクラスで2重参照できない?

this.is = function(chu) { alart(chu); }
this.arai = function() { this.is('a pen'); }

例えば、こういうスクリプトで「this.isは未定義です」というエラーが出るやつです。対処法は以下になります。

Worker側でWeb Audio APIが使えない!?

Web Audio APIはバックグラウンドでは使えません。 その為、バックグラウンドでは波形レンダリングのみを行う必要があります。

Worker内のFroat32Arrayを、フロント側に参照渡ししたい

postMessageでは、ArrayBufferを参照渡し送信することができます。 大容量の波形データは値渡しだと遅いので、ぜひ参照渡ししたいところです。 ただし、第1パラメータと第2パラメータのオブジェクトは同一でなければなりません。

object.L = new Float32Array(length);
object.R = new Float32Array(length);
:
object.L[n] = -1~1;
object.R[n] = -1~1;
:
postMessage(object, [object.L.buffer, object.R.buffer])

第2パラメータに別のArrayBufferを指定しても送信されないのでご注意ください。

Workerから送られてきたArrayBufferを受け取りたい

ArrayBufferのset()で受け渡しします。 AudioContextの場合、事前にcreateBufferとgetChannelData(n)を行っておく必要があります。

audio.context = new webkitAudioContext();
audio.context.buffer = audio.context.createBuffer(2, samples, 44100);
audio.L = audio.context.buffer.getChannelData(0);
:
worker.onmessage = function (e) {
:
audio.L.set(e.data.L);

番外編・Ajax取得したソースのスクリプトを実行したい

今回のデモコンテンツとは直接関係ないのですが、 当サイトのようにjQuery Ajaxで部分ロードする場合、 scriptタグ実行は

という方法で行います。