RSS Twitter Facebook


« 2014年08月 | 2014年09月のアーカイブ | 2014年10月 »

2014/09/21

WebGLで音声信号処理してみる


WebGLのシェーダープログラムで音声処理をしてみるというのを数日前から試してみたりしているのですが、結論から言えば今のところたいして良い結果は得られていません。それなりのGPUを積んだPCならJavaScriptで書いたよりは速い程度で動くのですが、グラフィックチップが非力なノートなんかでは酷い事になったりします。

まあせっかくなので、メモ代わりに一応公開しておきます。
https://github.com/g200kg/WebGL-Audio-processing

これは、平面上の波の伝播の物理シミュレーションをWebGLでやってそこに音信号を通してみるという実験で、プレートリバーブの物理モデリングみたいなものです。浮動小数テクスチャーを使ってRGBの各面をそれぞれ点の変位、点の速度、出力バッファとして使うというような事をやっています。残念ながらサンプル単位で順次処理が必要な関係でGPUの並列処理能力をあまり活かせない感じです。ウインドウを切ったブロック内で完結する処理なんかをうまく書ければかなり良い結果が出そうな気はするのですが。

追記(2014/09/22):
 パフォーマンスが上がらない原因を調べると、GPUからCPUにデータを受け渡すのに使用しているreadPixels()が問題のようです。実行時間のかなりの部分をこのreadPixels()に費やしているように見えます。ただし、転送するデータ量だけでなく、また単なる関数の呼び出しオーバーヘッドでもなさそうな挙動があります。推測ですがGPUが描画可能な状態とデータ転送可能な状態をスイッチするのが遅いのではないかと思われます。環境にもよると思いますが、44.1kHzで1024サンプル(=23mSec程度)毎にreadPixels()する実装でオーディオを通そうとするとマウスの動きなどによる描画処理などが入るだけで間に合わなくなったりします。オーディオ処理のようなタイムクリチカル処理をここに入れるのはそう簡単ではなさそうです。

posted by g200kg : 7:06 AM : PermaLink

2014/09/17

WebGLでシェーダープログラム書こうぜ!


LiveBeatsでビジュアルエフェクトを幾つか作ってみたりしているんですが、さすがにJavaScriptのCanvas上で画像のピクセル単位の処理をごにょごにょしたりしているとパフォーマンスが厳しくなってきます。

まだもう少しはCanvasだけでも頑張れるかなぁと思いつつも、これに関してはもう進むべき道ははっきりしていてるんですよね。WebGLですよ、やっぱり。とは言え、GPUの性能をフルに引き出すにはシェーダープログラムをGLSLなる言語で書く必要がある所が結構な障壁になっています。という事でとっつきやすいTHREE.jsあたりを使って取りあえずJavaScriptでコントロールするだけでも今までとは一味違う表現ができるんですが...

それでも満足できなくなったらこっち、GLSL Sandbox。GLSLでがしがし書いて即テストできるサイトで、ビジュアライザー系にそのまま使えそうなサンプルがてんこ盛りです。素晴らしい。このサンプルを見てると(THREE.jsとかのライブラリを使うにせよ)GLSLで書くモチベーションが湧いてきますね。

ただし、GLSL Sandboxでは入力となるパラメータが時間とマウス座標くらいしかないので、音のビジュアライザーにするにはちょっと物足りない所もあります。やっぱり生のWebGLの全貌をちゃんと理解しないといかんなぁ、となったらこっち、wgld.org。物凄く丁寧にWegGLを解説されていますので、みっちり読めばWebGLマスターになれそうです。

という事で、LiveBeatsで処理が重くてこの先不安な感じがあったカメラ画像で動きを検出したりエフェクトを掛けたりする部分をなんとかGLSLで書いてみました。Webカメラから画像を取り込んで、色々エフェクトをかけつつ、動きの激しい部分の座標を追いかけます。Canvasオンリーで書いてた時はかなり重かったんですが、GLSL化で古いMBAでもほぼ60FPSで安定して動作するようになりました。


ShaderTest

これは、カメラ画像のフレーム差分から動きを検出する部分と画像にエフェクトを掛けつつ表示する部分で2つのシェーダープログラムを使用しています。ポイントとしてはGPU側で行った動き検出の結果をCPUで使いたかったのでそのあたりの受け渡しをどうすれば良いのかちょっと悩みましたが、シェーダーでオフスクリーンバッファに書き込んでCPUでreadPixelsするという感じで行ける模様です。この辺のボトルネックがどの程度なのかまだ感じが掴めてないんですけど、音声信号もGPUに送ってシェーダーで処理するなんて事も頑張ればできそうです。その内試してみるかも。


posted by g200kg : 7:28 PM : PermaLink

2014/09/14

Web Music Hackathon #3 が開催されました


2014年9月13日@Google東京オフィスにてWeb Music Hackathon#3 が開催され、無事終了しました。回を追う毎に参加者が増えてきています。右はMIDIコントローラを中心に色々準備されている機材。
という事でハック開始。昼食はサンドイッチです。

チューターの方々は、ローランドVDrumからDONTATA君をドライブしたり、ギター持ち込みでブラウザをエフェクターにしてみたり。ちなみに私は相変わらずLiveBeatsでごにょごにょしてます。

日本のインターネットの父、村井純先生登壇。打ち上げは北京ダックで。

と、こんな感じだったのですが、実は私としてはとても気になったニュースが、ヤマハからさらっと紹介された「Web Music DAW Connector」というものです。これは何かというと、下の図のようにDAW、CubaseのVST pluginインターフェースの所にブラウザのWeb Audio APIを接続するものなんですね。
これを使うといよいよブラウザでの信号処理を本格的なDAWに接続して使う事が可能になります。WebSocketで繋がりますので、DAWが走っているPCからリモートのタブレットで信号処理して戻す、なんて事も可能です。アイデア次第で今までになかったDAWの使い方とかも出てくるかも知れません。
詳細はこちら⇒Web Music DAW Connector

posted by g200kg : 12:52 AM : PermaLink

2014/09/07

Web Music ハッカソン#3


今度の土曜日、9月13日はWeb Musicハッカソン#3が開催されます。

場所:Google東京オフィス
日時:2014年9月13日 10:00-18:00
主催:Web Music Developers JP、Google
協賛:AMEI

もう3回目ですね。AMEI協賛で各社機材が豊富に準備されるので、触れてみるいい機会でもあります。
今回もチューター役やらさせていただきます。自分のネタとしてはLiveBeatsをもうちょっとなんとかしたいと思っているんですがどうしましょうか。


http://googledevjp.blogspot.jp/2014/08/web-music-3.html

posted by g200kg : 4:11 PM : PermaLink

2014/09/02

映像効果のvjプラグイン仕様を考えてみた



LiveBeatsのビジュアライザーを分離してプラグイン化しました。デフォルトで波形/スペクトラム表示プラグインとマトリックス風エフェクトを読み込むようになっていますが、基本的にはただのJSファイルで描画部分の関数だけを書いたものです。これをカスタムしてLiveBeatsにドロップすると読み込めます。

DOMエレメントを作って描画する部分だけの関数になっていますので、ホストアプリ側で必要な場所にエレメントを貼り付ける構造です。何か共通規格的なものにできれば良いんですが。


//-- vj_simplewave.js --
vj_simplewave=function(param) {
	this.w=param.w;
	this.h=param.h;
	this.n=param.n;
	this.wavedat=param.wavedat;
	this.freqdat=param.freqdat;
	this.elem=document.createElement("canvas");
	this.elem.width=this.w;
	this.elem.height=this.h;
	this.ctx=this.elem.getContext("2d");
	this.ctx.lineJoin="round";
	this.anim=function(timestamp) {
		this.ctx.strokeStyle=this.param.col.value;
		this.ctx.lineWidth=this.param.line.value;
		this.ctx.clearRect(0,0,this.w,this.h);
		this.ctx.beginPath();
		this.ctx.moveTo(0,this.h/2-(this.wavedat[0]-128)*this.h/512);
		for(var i=1;i<this.n;i+=2) {
			var x=this.w*i/this.n;
			var y=this.h/2-(this.wavedat[i]-128)*this.h/512;
			this.ctx.lineTo(x,y);
		}
		this.ctx.stroke();
	};
	this.param={
	"line":{"value":3,"type":"double","min":1,"max":10},
	"col":{"value":"#f00","type":"string"},
	};
}

vjプラグイン仕様
ちょっと色々やりすぎてMBAだと厳しくなってきました。たまにひっかかる。

posted by g200kg : 3:39 AM : PermaLink

« 2014年08月 | 2014年09月のアーカイブ | 2014年10月 »


g200kg