AudioParam Viewer
Web Audio API の AudioParam の値を可視化できるやつを作った。
コードを書いて実行(eval)すると30秒分の値の遷移を記録してグラフ表示します。param
というのが操作する AudioParam のインスタンスで、Ctrl+O
か Ctrl+Space
で操作関数を補完できます。
仕組み
Web Audio API はリアルタイムでオーディオ処理をするためのAPIだと思われがちだけど、OfflineAudioContext というのを使えば静的なオーディオ処理もできます。以下は簡単な使い方。レンダリング用のインターフェースがあるだけで基本的には AudioContext と同じように使えます。これを使うと30秒の処理を一瞬で行うことができるので、それを使って常に 1 を出力する AudioBufferSource とパラメータ操作用の GainNode を接続し、レンダリング結果をグラフ化しています。
// (1) OfflineAudioContext を作る var context = new OfflineAudioContext(numOfChannels, length, sampleRate); context.oncomplete = function(e) { // (4) 処理の結果 e.renderedBuffer; // AudioBuffer }; // (2) ここで処理をする(同期処理) audioProcessing(context); // (3) レンダリング開始 context.startRendering();
AudioContext と OfflineAudioContext の違い
AudioContext と OfflineAudioContext の大きな違いは処理を行うタイミングにあります。良くある AudioContext のアプリケーションでは setInterval 等を使って数ミリ秒単位で少しずつ行いますが、OfflineAudioContext の場合は一気に処理を行う必要があります。また、複数トラックを扱うようなアプリケーションを書くときに AudioContext の場合はすべてのトラックをリアルタイムに並列で処理する必要がありますが、OfflineAudioContext の場合はリアルタイムでないので各トラックずつ順番にといったように直列に処理することができます。そして、AudioContext ではボタンクリック等のイベントを介して今すぐ音を鳴らすというような書き方ができるのに対して、OfflineAudioContext はイベントを介した操作はまずできなくて、いつ音を出して、いつ音を止めるか、いつパラメーターをどう変化させるかを厳密に指定する必要があります。
お前それ OfflineAudioContext でも同じこと言えんの?
上記のように時間にシビアな OfflineAudioContext では osc.start(0)
で今すぐ音を出すみたいな書き方や、一定時間経過後にオシレーターの周波数を変えたいので、それっぽいタイミングで osc.frequency.value = newValue
をするというような使い方はできません。シンセサイザーアプリのようにユーザーイベントがきっかけになるような場合は仕方がないケースもありますが、それでもきっちりと時間を指定して osc.start(context.currentTime)
や osc.frequency.setValueAtTime(newValue, startTime)
のように書いておいた方が後々に機能の追加や、コードの流用などの点で有利になります*1。OfflineAudioContext を制するものは Web Audio API を制するといっても過言ではないのです。
ということで練習です
AudioParam Viewer は OfflineAudioContext を使っているので厳密に時間を指定する方法で書く必要がありますが、逆にこれを使いこなして思い通りのグラフが書けるようになると AudioContext でもかっちりしたコードが書けるようになります。以下、適当に練習問題を考えてみましたので、どうぞお試しください。
ヒント: timeConstant = 0.1
答え
ヒント: var a = 0.2, d = 0.1, s = 0.4, r = 0.2, keyOff = 0.8;
答え
keyOff = 0.1
とかしても適切なカーブを描かせる
答え
*1:例外として変化しないパラメーターは param.value で直接代入したほうが良いです