JOY DIVISIONの世代ではありませんが…
JOY DIVISIONというロックバンドをご存知でしょうか?ニュー・オーダーの前身となる70年代のイギリスのアーティストです。活動期間は短いですが、Unknown Pleasuresというアルバムが有名で、特にそのアートワークは現在も人々にインスピレーションを与えているようです。どんなジャケットかというと、こんな感じです。(この演出はイラっとするかもしれません。)
ご覧のように、周波数のスペクトルを時系列で縦に重ね並べただけの何の変哲もないグラフです。ですが、なぜかなかなかインパクトがあり、検索結果でもわかるように衣服のデザインに使われたりもします。
今回これをjavascriptで出来たらいいな、と考えて見ました。
このようなアプリケーションは私はWindowsのネイティブアプリケーションとして作ったことはありましたがブラウザ上では初めてです。そもそもできるのかどうかわかりません。でも今は21世紀です。きっと出来るに違いありません。
FireFox Experiments
ちょっと調べてみたら、Mozilla Wiki – Audio Data API https://wiki.mozilla.org/Audio_Data_API
というのを見つけました。
Defining an Enhanced API for Audio (Draft Recommendation) Abstractこの概要説明によると、HTML5 media APIのMozilla独自拡張という事ですが、ウェブ開発者へ生音声データへのr/wを提供するという事なので期待できます。 そして、下の方にやりたい事ほぼそのままのサンプルコードがありました。
The HTML5 specification introduces the <audio> and <video> media elements, and with them the opportunity to dramatically change the way we integrate media on the web. The current HTML5 media API provides ways to play and get limited information about audio and video, but gives no way to programatically access or create such media. We present a new Mozilla extension to this API, which allows web developers to read and write raw audio data.
Complete Example: Visualizing Audio Spectrum This example calculates and displays FFT spectrum data for the playing audio:まさにこれです。あっさり冒険が終了してしまいました。
そして、ひとまずこのソースをそのままコピペして表示させてみたのが、
こんな(音声は録音していません)感じです。なかなか良い感じですね!
HTMLのソースは、
<audio id="audio-element" src="./LivingFree.wav" controls="true" style="width: 512px;"> </audio> <div><canvas id="3dfft" datasrc="./3DdemoSpectrum.pjs" width="512" height="300"></canvas></div> <script src="./3DdemoSpectrum_audio.js"></script> <script> var audio = document.getElementById('audio-element'); audio.addEventListener('MozAudioAvailable', audioAvailable, false); audio.addEventListener('loadedmetadata', loadedMetadata, false); </script> |
このようになっていて、MozAudioAvailableとloadedmetadataに対応したイベントハンドラを追加し、javascript側で音声データのストリームを受け付けられるようにします。外出ししたjsファイル側ではこれらのイベントハンドラの実装を行なっています。
3DdemoSpectrum_audio.js(オーディオ関連のイベントハンドラとFFTを記述している)
function loadedMetadata() { //(任意の処理を実装) //loadedmetadataイベントはHTML5標準だがMozillaはメディア要素から //mozChannels,mozSampleRate,mozFrameBufferLengthが取得できる } function audioAvailable(event) { //(任意の処理を実装) //MozAudioAvailableイベントはMozilla独自拡張。音声データのストリームが取得できる。 //ここでは受け付けたストリームデータのスペクトルを求める(FFTの実行) } // FFT from dsp.js, see below var FFT = function(bufferSize, sampleRate) { //FFT実装 } |
javascriptソースにあるとおり、FFT部分のロジックはdsp.jsのソースの一部を流用しています。dsp.jsではFFTといった分析の他に正弦波矩形波といったアナログシンセの基本波形の発信も出来るようでjavascriptでソフトウェアシンセサイザーを作るという事も可能と思われます。
processing.jsと連動させる
そして今回はJOYDIVISIONの様に奥行きのある波のような動画を作ってみたいので、3Dを使って波形を表示して見ることにします。processingのサンプルソースでこれに近いものは無いかと探していたところ、Andor Salgaという方が立方体の各辺をランダムに揺らすアプリケーションElectric Cube(3D)を作っていましたので、これをベースに周波数表示を行うものに改変してみます。改変後のソースはこちらです。
いくつかクラスがありますが要となるメソッドは、LightningBolt#updateで、ここでaudio側のjavascriptのメソッドinitSpecとgetSpecを読みだしています。getSpecからFFTの演算結果を取得しています。
firefoxで表示してみる
3DdemoSpectrum.html(下の黒い部分に緑の線が出ない場合はページをリロードしてください。うまく行かないのは何でだろう?)
私の手元のマシンで動作させた様子は、こんな感じです(内蔵マイクの音声でスミマセン)。曲は、http://soundcloud.com/rollin-fire-cru/living-free/こちらの作品を使わせて頂きました。
JOYDIVISIONとちょっと投影法や精度が違いますが、なんとなく同じように表示させることができました!
課題
初期表示でラインが表示されないことがある。
→多分これは私の実装方法に何か問題があるのだと思います。
現在のところFirefoxでしか動かない。Chromeでもダメ。
音声データに関しては、先に上げた引用文にもあるようにHTML5とその関連技術が過渡期なので、今後どうなるのかわかりません。一方3Dに関してもWebGLについては同様に過渡期のようです。processing.jsは3DモードだとWebGLを使うようですが、2D Canvas上で3Dを再現したpre3dというプロジェクトもあるようです。速度面のデメリットがありそうですがこちらの方が環境依存しないというメリットがあるかもしれません。今回の場合は音声を扱いましたので割りきりましたが純粋に3Dの実装を行う場合にはどちらが良いのか迷いどころな気がします。
速度が遅い。
もっとパフォーマンスを良くしたいです。本当はライン一本一本をブリンブリンに光らせたいです。