Help us understand the problem. What is going on with this article?

WebAudioAPIで遊べるようになった

More than 5 years have passed since last update.

音楽の覚えがあるエンジニアとしては、触らなきゃダメだろーと思いつつ、なかなか手を付けられていなかった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つかえるっぽい
  • 音をばしばしつかったスマホサイトなんかも、挑戦したいなぁ

参考とかっこいいデモ

fnobi
面白法人のテクニカルディレクター 兼 作曲家 兼 ドルヲタ ⌨️ http://github.com/fnobi 🎼 http://soundcloud.com/fnobi
http://fnobi.com/
kayac
古都鎌倉から新しい技術と面白いサービスを、次々にリリースする面白法人カヤックのフロントエンジニアチーム
http://www.kayac.com
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away