Web Audio API でビジュアライザーを作った話

目次
何もしていないのにぎっくり腰になりました。
この記事は、社内イベント「お茶会」での発表内容をもとにまとめたものです。
今回は弊社の morisaki が「Web Audio API を使った波形の可視化」について話しました。
私は音楽は聴く専門で、楽器はリコーダーくらいしか経験がありません。
でも音楽そのものは好きで、たまにライブに行ったり、野外フェスにも毎年のように参加しています。
ずっと楽器に対してゆるく憧れを持ちながら、気がつけば時間だけが過ぎていきました。
最近は「子どもたちと一緒に何か始めてみるのもいいかも」と思ったりしつつも、なかなか行動には移せていません。
そのうちに、「電子楽器でも触ってみようかな」と思うようになります。見た目のかっこいい機材を見つけては気持ちが高まり、YouTube で動画を見漁っては、カートに入れて見送る……という日々が続いていました。
ちょうどそんな時期に、お茶会の発表の順番がめぐってきます。
せっかくだし、JavaScript でなにか音楽っぽいことができないかなと思い立ち、「音のビジュアライザーを作ってみた」という話です。
01 気づけば機材を調べていた
電子楽器に対する興味がふつふつと湧いてきた頃、気になる機材を見つけては、スペックや使い方を調べるようになっていました。
その中でも特に印象に残ったモデルをいくつか紹介します。
YAMAHA SEQTRAK
コンパクトな筐体に、16小節分のボタンが並んだデザイン。視認性の高いインターフェースとオレンジのアクセントが印象的で、「これが家にあったらかっこいいな」と思わせてくれる見た目。
アプリでも似たような構成のものは見かけますが、やはり物理ボタンの説得力には惹かれます。
価格はおよそ55,000円。すぐに手を出すには少し勇気のいる値段です。
TEENAGE ENGINEERING OP–1 field
さらに調べていくうちに出会ったのが、TEENAGE ENGINEERING というスウェーデンの電子楽器メーカー。中でも代表的なモデルのひとつが「OP–1 field」です。
これはいわゆるシンセサイザーで、音作り・録音・エフェクトなど一通りの操作がこれ一台で完結します。
操作性や音質もさることながら、無駄のない美しいデザインに強く惹かれました。
ただし、価格は日本円でおよそ30万円。現実的にはなかなか手が出せるものではなく、眺めるだけで満足する“憧れの存在”といったところです。
TEENAGE ENGINEERING EP–133 K.O. II
もう少し手頃な選択肢として見つけたのが、「K.O. II」と呼ばれるモデルです。
こちらは「サンプラー」に分類される機材で、価格はおよそ5万円。
実際にこの機材を使って制作している動画も多く、使いこなせれば楽しそうだなと思わせてくれましたが、まだ手を出すには迷う価格帯でもあります。
PO-33 K.O!
「とりあえず何か一つ触ってみよう」という気持ちで、最終的に購入したのがこのモデルです。
K.O. IIの前身にあたる機種で、電卓のような見た目をした非常にコンパクトなサンプラー。
マイクとスピーカーが内蔵されており、これ単体で録音・再生ができる手軽さが魅力です。
コラボモデルも豊富で、例えば『ストリートファイター』や『ロックマン』などとの限定版も展開されています。
ときどき触っては音を鳴らして遊んでいるのですが、やはり“音楽をつくる”というのは、想像以上に難しい。
02 Web Audio API で“音楽っぽいこと”を
電子楽器の代わりに、ブラウザ上で音を扱えないかと調べていくうちに、「Web Audio API」という技術にたどり着きました。JavaScript で音を合成したり、フィルターをかけたりと、シンセサイザーのような機能を持った API です。
「これを使えば、ブラウザ上で音楽っぽいことができるかもしれない」と思ったものの、実際に触れてみると、信号処理や周波数、波形など、なかなか専門的な世界。いきなり作曲やシンセを自作するには、ちょっとハードルが高すぎました。
そこで方向転換。同じ Web Audio API を使って、音そのものではなく“音の見た目”にフォーカスしてみようということで、ビジュアライザーを作ってみることにしました。
03 ビジュアライザーの実装
シンプルな構成で、HTML も非常に軽量です。
波形を表示するまで
音源の読み込みと再生
音源の読み込みから波形データの取得までを Web Audio API を使って実装しました。
HTMLはとてもシンプルで、<audio>
タグを使ってローカルの音源を読み込んでいます。
もうひとつの方法として、JavaScript の Audio()
コンストラクタを使うやり方もあります。
こちらは HTML に要素を追加せずに音源を再生できる上、必要なタイミングで読み込み・再生ができるため、効果音など再生タイミングを細かく制御したいケースに向いていそうです。また、再生後はガベージコレクションの対象になるため、メモリ効率が良いという利点があります。
ただし、再生のたびにクローンが必要など少し癖があるため、今回はよりシンプルに扱える <audio>
タグを選びました。
音の解析構成
音の解析には AnalyserNode
を使用し、音量調整用に GainNode
を追加。各ノードは以下のように接続しています。
audio(音源)
↓
AnalyserNode(解析)
↓
GainNode(音量調整)
↓
destination(出力)
実際のコードはこちらです。
if (!this.analyserNode) {
const audioContext = new AudioContext();
// analyser 生成
this.analyserNode = audioContext.createAnalyser();
// 符号なし long 値で、周波数領域データを取得するために高速フーリエ変換 (FFT) を行う際に使用するウィンドウサイズをサンプル数で表します
// ※符号なしlong値とは、負の値ではなく、0以上の整数のみを表現するlong型のデータ型です。通常、32ビットまたは64ビットの長さを持ちます
// https://developer.mozilla.org/ja/docs/Web/API/AnalyserNode/fftSize
this.analyserNode.fftSize = FFT_SIZE;
// 最後の分析フレームとの平均化定数を表す double 値です。
// これは基本的に、現在のバッファーと AnalyserNode が処理した最後のバッファーとの間の平均であり、
// 結果として、よりスムーズな時間による値の変化の集合になります
// 0 から 1 までの範囲で、1に近づくほど遅い
// https://developer.mozilla.org/ja/docs/Web/API/AnalyserNode/smoothingTimeConstant
this.analyserNode.smoothingTimeConstant = 0.5;
// volume control
this.volumeControl = audioContext.createGain();
this.volumeControl.gain.value = 0.5;
// gainNode を出力に接続
this.volumeControl.connect(audioContext.destination);
// analyserNode を gainNode に接続
this.analyserNode.connect(this.volumeControl);
if (this.audio) {
this.source = audioContext.createMediaElementSource(this.audio.getElement()!);
// source を analyserNode に接続
this.source.connect(this.analyserNode);
}
}
この接続が正しくないと、音が鳴らなかったり、解析がうまくいかなかったりするので注意が必要です。
音の解析には FFT(高速フーリエ変換) という手法が使われています。
これは音を周波数ごとのデータに分解する処理で、Web Audio API では AnalyserNode が自動的にこの処理を行ってくれます。
AnalyserNode
では、解析サイズ(2の累乗、今回は1024)や滑らかさの度合い(smoothingTimeConstant
:今回はデフォルト値の 0.8)を設定しました。滑らかさを高くすると波形がなだらかに変化し、低くすると急激に変化します。
周波数データの値は、左から右にかけて低音から高音の順に並んでいます。
こちらの音源はリズム中心だったため、左側が強く反応しました。
this.analyserNode = this.analyser.getAnalyserNode();
if (!this.analyserNode) return;
this.bufferLength = this.analyser.getBufferLength();
// 8 ビット符号なし整数値の配列
this.frequencyData = new Uint8Array(this.bufferLength);
// 渡された Uint8Array (符号なしバイト配列)に現在の周波数データをコピーします
// 周波数データは、 0 から 255 まで の範囲の整数で構成されます
this.analyserNode.getByteFrequencyData(this.frequencyData);
if (!this.analyserNode) return;
if (this.frequencyData && this.elementList.length > 0) {
const baseAngle = 360 / this.bufferLength;
this.frequencyData.forEach((data, i) => {
// 値は256段階で取得できるので正規化して 0.0 〜 1.0 の値にする
const scale = data / 256;
const bar = this.elementList[i];
if (bar) {
const angle = (baseAngle * i) % 360;
bar.style.scale = `1 ${scale}`;
bar.style.backgroundColor = `hsl(${angle} 100% 50%)`;
}
});
}
また、アニメーションを音に合わせて動かす場合、「どの帯域を使うと気持ちいい動きになるか」は感覚的な部分も大きく、音源によって反応する帯域も異なります。
例えば音階の違い(ドレミファソラシド)を再生しても、意外と反応の差は小さく、単純に「高い音=右側が反応する」とは限りませんでした。
ビジュアライザーのアレンジ例
先程のような波形描画は、AnalyserNode
が取得できれば比較的簡単に実装できます。
同じ音のデータを使って、他にどんな表現ができるかいくつか試してみました。
以下の動画では、上から順に3つのアレンジパターンを再生しています。
- 基本の波形描画
横に伸びるバーで音の強弱を表現したもの。 - ブレンド&ぼかしによる演出
CSS のブレンドモードやぼかし効果を使って、視覚的にカッコよく見えるように工夫したアレンジ。 - 円形での音の分布可視化
低周波を外側、高周波を内側に配置し、色でもグラデーションをかけた表現。
※ いずれも DOM のみで描画しています。
現状、約2000要素の DOM が動いていますが、実用的には canvas を使った方が滑らかかつ自由度の高い描画が可能です。
上のアレンジをベースに、もっと映像っぽくカッコよく見えるように調整したバージョンも作ってみました。
- 反転パターン
最初に作った波形を縦に並べ、上下左右に反転させて描画したものです。 - 複製パターン
先ほどの 2 つ目のアレンジを左右反転して複製したものです。 - ブレンドモード重ねパターン
3 つ目のアレンジにブレンドモードを適用し、図形同士の重なりを強調しています。
この円だけを表示しても何も見えませんが、背面に何か(ここでは1つ目のアレンジなど)を表示させて重ねることで、中央に円が浮かび上がる仕掛けになっています。 - 回転・ボーダー化パターン
円形波形をもとに、背景色をなくしボーダー(線)だけで構成。図形そのものを回転させるアレンジです。
そして、これら4つをすべて組み合わせたバージョンがこちら。
重なりや動きに奥行きが生まれ、よりビジュアルとしての完成度が上がりました。
また、AnalyserNode の smoothingTimeConstant
を調整することで、アニメーションの印象も大きく変わります。
例えば値を 0 に近づけると反応が鋭くなり、クラブで流れるような激しめのチカチカした演出に。
逆に 1 に近づけると動きがなだらかになり、滑らかでスムーズな映像表現になります。
04 まとめ
データ自体は簡単に取得できるため、WebGL で描画したり、フェーダーやシーケンサー的な UI を組み合わせたりすれば、見た目にも凄そうなものが意外と手軽に作れてしまいそうです。
最近では、Webサイト上で音を使う機会は減ってきている印象もありますが、だからこそ、音に合わせて何かが動くような演出があると、逆に新鮮に映るかもしれません。
実際に、以前担当した案件では音楽に合わせて画像の動きを変化させる実装を行ったのですが、そのときは知識も浅く、波形の一部しか使っていませんでした。
この度あらためて試してみて、AnalyserNode を使えば遥かに多彩な表現が可能だということを実感したので、今後、また音を扱うような場面があれば、ぜひこうした表現にも挑戦してみたいと思います。
このような音とビジュアルを組み合わせた表現に興味がある方は、Chrome Music Lab もぜひチェックしてみてください。手軽に試せる実験的なコンテンツがいろいろ用意されています。
「こういう表現をWebでやってみたい」「音に合わせて動く演出を作ってみたい」といったご相談があれば、ぜひお気軽にお問い合わせください。

S2ファクトリー株式会社
様々な分野のスペシャリストが集まり、Webサイトやスマートフォンアプリの企画・設計から制作、システム開発、インフラ構築・運用などの業務を行っているウェブ制作会社です。
実績
案件のご依頼、ご相談、その他ご質問はこちらからお問い合わせください。