

HTML5のAudioオブジェクトとJavaScriptで簡易ドラムマシンを作ってみた
» 音楽ネタ全般
前に書いた 主要ブラウザの HTML5 の Audio 要素の対応状況を調べた記事に続いて、HTML5 Audio ネタ第二弾です。
今回は audio タグで再生ファイルを指定するのではなく、JavaScript で Audio オブジェクトを複数生成したものを速いタイミングで鳴らしてどれくらい反応できるのか見てみようということで、簡単な16ステップのドラムマシンを作ってみました。
すで同じような記事を書かれている方が何人かいるので、二番煎じ(三番…いや五番煎じくらいか)ではありますが今回はとりあえず自力で。
グリッドの間に何かあるように見えるのは錯視です
↓テストページはこちら
» HTML5のAudioオブジェクトとJavaScriptで作った簡易ドラムマシン
Internet Explorer 6/7/8 は HTML5 に対応していないので動きません。
非対応の場合はメッセージが表示されます。
HTML5 の Audio 要素で使える音声ファイルはブラウザによって対応フォーマットが違うので、WAV (16bit/44.1kHz)、MP3 (128kbps/44.1kHz)、OGG (128kbps/44.1kHz) を用意しました。ブラウザごとにそれぞれ対応した形式のファイルが自動的に選択されて読み込まれます。
主要ブラウザの音声ファイル対応状況は以前の記事 を参考にしてください。
複数の Audio オブジェクトを生成して音声ファイルを読み込んだ後、スタートボタンを押すと指定した BPM の間隔(15sec/BPM)で毎回 setTimeout() でタイマーを起動してステップのトリガーにあわせて Audio オブジェクトのメソッド play() で再生していきます。
細かい処理内容は JavaScript が分かる人は直接コードを見てもらったほうが早いかも。
(あんまりきれいなコードではないですけど)
現状の Audio オブジェクトでは複数の音(オブジェクト)をミックスして1つのメソッドで同時再生する機能は実装されていないので、1ステップで発音するパートの数だけ続けて play() を呼び出す必要がでてきます。
たとえば「キック+スネア+ハイハット」なら3回 play() を呼ばなければならなくなり、そうなるとどうしても発音のタイミングにずれがでてきます。
そこで考えたのが、パート単体の音以外に、キック+スネア、キック+ハンドクラップ・・・のようにあらかじめ複数のパートを重ねた音を全て用意しておく方法です。これだと1ステップあたり1回だけ play() を呼べば済みます。
パートが少ないからこそできるワザなのですが、それでも5パートの組み合わせはオープン/クローズハイハットの排他を抜いても全部で23パターンもあって素材を作るのに結構手間がかかってしまいました。
他に Audio オブジェクトをたくさん作るとメモリ消費の影響でブラウザがどんどん重くなってくる問題もあって、特に Windows 版の Safari ではロードからスタンバイの状態になるまでが異様に長くなる場合があります。
iOS 4.2 の mobile Safari も間引きが起こって正常に再生されませんでした。音声ファイルのキャッシュに問題がありそうな気がしたので、HTML5 の Offline Application Caching APIs を設定してみましたが変化なし。とりあえず後で調べることにして今回は保留。
Windows 版 Safari は、BPM をうんと下げてやると一応再生してくれる場合もあったので、リリースと次のアタックが重なるとダメだということが分かりました。(Chrome はテンポを落としてもダメだった)
そこでどうにかリリース部分を制御できないか試行錯誤していて、再生時間位置を持つプロパティ currentTime に 0 を入れてから play() を呼んでやると一応効き目はあったようで、多少改善はされたものの完全には間引を解消できず。
Internet Explorer 9 beta は、以前試した audio タグは対応していましたが、Audio オブジェクトはまだ実装されていないようで、オブジェクトを生成する時点でエラーが出て動きませんでした。
これが意外にも Safari には有効で音はゲートがかかったようにザクッと切れますが、ちゃんと BPM に追従してパターンが再生されました。Chrome には効き目がなく相変わらず間引かれたパターンが再生されてます。
今回はここでギブアップ。
引き続き試行錯誤してバージョンアップしていきたいと思います。
[追記] 2011/02/04
Chrome 9.0 がリリースされたので試してみたら、ver.8 に比べるとかなりスムーズに動くようになっていました。 (Windows 7)
[関連サイト]
HTML5 - W3C Editor's Draft - Audio Element
jQuery UI

今回は audio タグで再生ファイルを指定するのではなく、JavaScript で Audio オブジェクトを複数生成したものを速いタイミングで鳴らしてどれくらい反応できるのか見てみようということで、簡単な16ステップのドラムマシンを作ってみました。
すで同じような記事を書かれている方が何人かいるので、二番煎じ(三番…いや五番煎じくらいか)ではありますが今回はとりあえず自力で。
グリッドの間に何かあるように見えるのは錯視です
↓テストページはこちら
» HTML5のAudioオブジェクトとJavaScriptで作った簡易ドラムマシン
Internet Explorer 6/7/8 は HTML5 に対応していないので動きません。
非対応の場合はメッセージが表示されます。
概要
ドラムパートはキック、スネア、ハンドクラップ、クローズド/オープンハイハットの計5つです。ハイハットは排他処理を入れてあるので、1ステップにセットできるのは最大4パートになります。HTML5 の Audio 要素で使える音声ファイルはブラウザによって対応フォーマットが違うので、WAV (16bit/44.1kHz)、MP3 (128kbps/44.1kHz)、OGG (128kbps/44.1kHz) を用意しました。ブラウザごとにそれぞれ対応した形式のファイルが自動的に選択されて読み込まれます。
主要ブラウザの音声ファイル対応状況は以前の記事 を参考にしてください。
複数の Audio オブジェクトを生成して音声ファイルを読み込んだ後、スタートボタンを押すと指定した BPM の間隔(15sec/BPM)で毎回 setTimeout() でタイマーを起動してステップのトリガーにあわせて Audio オブジェクトのメソッド play() で再生していきます。
細かい処理内容は JavaScript が分かる人は直接コードを見てもらったほうが早いかも。
(あんまりきれいなコードではないですけど)
テスト結果
BPM 120、パターンは初期表示でセットしているパターンでテストしました。| OS | ブラウザ | 結果 | 備考 |
| Windows (7/XP) |
Firefox 3.6 | ○ | ほぼ問題なし |
| Chrome 8.0 | × | ビートが間引かれて正常に再生できず | |
| Chrome 9.0 | △ | 間引きあり。ver.8 に比べるとかなり改善 | |
| Safari 5.0 | △ | 起動が重い。GATEモードなら再生OK | |
| IE9 beta | × | Audio オブジェクト生成できず | |
| OS X (10.6.4) |
Firefox 3.6 | ○ | ほぼ問題なし |
| Chorme 8.0 | × | ビートが間引かれて正常に再生できず | |
| Safari 5.0 | ○ | ほぼ問題なし? | |
| iOS 4.2 (iPad) |
Safari | × | 間引き発生。原因未調査 |
パートごとの発音タイミングの問題
じつは発音処理のところでちょっとだけズルというか工夫をしています。最初は音声ファイルをパート数(5個)だけ単体で用意して、普通のドラムマシンのようにステップのトリガーに合わせて同時に発音する方式を考えていたのですが、ちょっと無理があることは薄々分かっていました。現状の Audio オブジェクトでは複数の音(オブジェクト)をミックスして1つのメソッドで同時再生する機能は実装されていないので、1ステップで発音するパートの数だけ続けて play() を呼び出す必要がでてきます。
たとえば「キック+スネア+ハイハット」なら3回 play() を呼ばなければならなくなり、そうなるとどうしても発音のタイミングにずれがでてきます。
そこで考えたのが、パート単体の音以外に、キック+スネア、キック+ハンドクラップ・・・のようにあらかじめ複数のパートを重ねた音を全て用意しておく方法です。これだと1ステップあたり1回だけ play() を呼べば済みます。
パートが少ないからこそできるワザなのですが、それでも5パートの組み合わせはオープン/クローズハイハットの排他を抜いても全部で23パターンもあって素材を作るのに結構手間がかかってしまいました。
他に Audio オブジェクトをたくさん作るとメモリ消費の影響でブラウザがどんどん重くなってくる問題もあって、特に Windows 版の Safari ではロードからスタンバイの状態になるまでが異様に長くなる場合があります。
ステップ間のリリースとアタックの問題
また別の問題として、というかこれが一番大きな問題なんですが、Windows/OS X 版 Firefox と OS X 版 Safari は再生が終わる前に次のステップの再生が始まってもちゃんと両方をミックスして発音してくれるのに対して、Windows 版 Safari と Windows/OS X 版 Chrome は再生が終わる前に次を呼び出すと再生がキャンセルされているような挙動になってビートが間引かれてめちゃくちゃになってしまいます。iOS 4.2 の mobile Safari も間引きが起こって正常に再生されませんでした。音声ファイルのキャッシュに問題がありそうな気がしたので、HTML5 の Offline Application Caching APIs を設定してみましたが変化なし。とりあえず後で調べることにして今回は保留。
Windows 版 Safari は、BPM をうんと下げてやると一応再生してくれる場合もあったので、リリースと次のアタックが重なるとダメだということが分かりました。(Chrome はテンポを落としてもダメだった)
そこでどうにかリリース部分を制御できないか試行錯誤していて、再生時間位置を持つプロパティ currentTime に 0 を入れてから play() を呼んでやると一応効き目はあったようで、多少改善はされたものの完全には間引を解消できず。
Internet Explorer 9 beta は、以前試した audio タグは対応していましたが、Audio オブジェクトはまだ実装されていないようで、オブジェクトを生成する時点でエラーが出て動きませんでした。
リリースを強制的にカットする機能をつけた
他に何かいい方法はないかと無い知恵絞って考えついたのが、前のステップの再生が残っているときは次のステップに移る直前に一時停止のメソッド pause() で再生中のオブジェクトを強制的に止めてから次を再生するという力技です。これが意外にも Safari には有効で音はゲートがかかったようにザクッと切れますが、ちゃんと BPM に追従してパターンが再生されました。Chrome には効き目がなく相変わらず間引かれたパターンが再生されてます。
今回はここでギブアップ。
引き続き試行錯誤してバージョンアップしていきたいと思います。
[追記] 2011/02/04
Chrome 9.0 がリリースされたので試してみたら、ver.8 に比べるとかなりスムーズに動くようになっていました。 (Windows 7)
[関連サイト]
HTML5 - W3C Editor's Draft - Audio Element
jQuery UI

Google API Expertが解説するHTML5ガイドブック
- 作者: 羽田野 太巳
- 出版社/メーカー: インプレスジャパン
- 発売日: 2010/09/16
- メディア: 単行本(ソフトカバー)

JavaScriptパターン ―優れたアプリケーションのための作法
- 作者: Stoyan Stefanov
- 出版社/メーカー: オライリージャパン
- 発売日: 2011/02/16
- メディア: 大型本






Win7のFirefox3.613で。まったく問題ないように思います、クールです。
by 404 (2011-02-01 04:31)
Firefoxはaudioタグのテストのときはmp3に対応してなくて、
ちょっとがっかりしたんですが、今回のテストはとても優秀でした。
by TAN (2011-02-01 14:16)