179
175

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WebAudioAPIで遊べるようになった

Last updated at Posted at 2013-10-21

音楽の覚えがあるエンジニアとしては、触らなきゃダメだろーと思いつつ、なかなか手を付けられていなかったWebAudioAPI、
先日のハッカソンでようやく着手できました。

その過程でわかったこと・つくったものなどまとめました。

登場人物

HTML5のAudio要素を使う時と違って、
WebAudioAPIの場合は、使っているオブジェクトがけっこう多い。
そのあたりを把握するのが、WebAudioAPIのマスターの第一歩っぽい。

context (AudioContext)

音をとりまとめるcontext。
音の再生先(destination)なんかも、このcontextが握っているみたい。

WebAudioAPIに対応しているブラウザは、
window.AudioContext (window.WebkitAudioContext)というのが生えてるので、
これをインスタンス化すると作れる。

var context = new window.AudioContext();

buffer

再生する音のデータ。
.wavなど外部のファイルを使う場合は、

  • XMLHttpRequest(responseType: arraybuffer で!)で読み込む
  • 読み込んだものを、contextにdecodeしてもらう (context.decodeAudioData)

という流れでできる。

// ここにbufferを格納したい
var buffer;

// ファイルを取得 (arraybufferとして)
var request = new XMLHttpRequest();
request.open('GET', '/sounds/sample.wav', true);
request.responseType = 'arraybuffer';

request.send();
request.onload = function () {
    // 読み込みが終わったら、decodeしてbufferにいれておく
    var res = request.response;
    context.decodeAudioData(res, function (buf) {
        buffer = buf;
    });
};

source

こうして作ったbufferを再生するためには、sourceというものを作る。
これもcontextに生えているメソッドを使う。(context.createBufferSource)

// source作成
var source = context.createBufferSource();

// さきほど作ったbufferを、ここにセット
source.buffer = buffer;

// 再生準備。contextの持っている再生先に接続
source.connect(context.destination);

// 再生 (引数はtimeout)
source.noteOn(0);

たとえば、できること

音の高さを変える

厳密にはピッチ変更ではないけれど、
単発の音を鳴らすのであれば、sourceのplaybackRate.valueをいじればおk。

気をつけること

sourceは使い捨て

sourceは、 再生するたびに生成して、使い捨てるというかたち になっている。
最初は、つくったsourceに対して何度も .noteOn したりできるのかと思ってた。

一度は、ユーザーアクションをトリガーにして、音再生させないとだめ。

逆に言えば、1度タップのタイミングなどで再生をさせてしまえば、 その後は好きなタイミングで鳴らし放題 なもよう。

その辺の挙動から、「ユーザーアクションで再生許可」は、おそらくcontextに紐付いてるんじゃないかなぁという印象。
(source単位での許可だとすると、sourceは再生のたびに使い捨ててるので、再生のたびに許可が必要なはず)
ちゃんとしらべてないけど。

ちなみに、ユーザアクションから間接的に音再生呼んだ場合、
(clickのlistenerでsetTimeout通して音再生、とか)
なんかときどき再生できちゃってたけれど、

確実に鳴らしたいなら、やっぱり1度は直接再生呼び出しした方がいいみたい。

つくったもの

DripMetro

先日のハッカソンで作ったもの。
ぴちょんぴちょん言うメトロノーム。
いちおうBPMを上げるほど、音も高くなるようにしてます。

ToneMap

↑のDripMetroを作る過程でできた、WebAudioAPIのwrapper。
(wrapperとはいえ、もうすこし機能追加するつもり)
複数の音源を使う場合でも、やりやすくなる…はず。

デモでは、
画面タッチで音再生→スワイプのスピードに応じて音を高く
っていうのやってます。

まとめ

  • たのしい
  • ↓のデモなど見ても思うけれど、iOSは十分にWebAudioAPIつかえるっぽい
  • 音をばしばしつかったスマホサイトなんかも、挑戦したいなぁ

参考とかっこいいデモ

179
175
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
179
175

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?