[ Jpn | Eng ]

Main Menu



Recent

最近の記事

Search

サイト内検索:

Archive

Powered by
MTOS 5.2.2


Products : Gembox Synth 販売中

ゼムクリップの容器に入ったコンパクトなシンセサイザー「Gembox Synth」を販売中です。

DTMステーション様で紹介していただきました
クリップ箱に収まった4,500円のミニシンセ、Gembox Synthが誕生

詳細はこちら : Gembox Synth


2015/01/25

HTML5 Conference

Twitter Google+ Facebook


さて、今日1月25日、東京電機大学千住キャンパスで「HTML5コンファレンス」が開催されました。という事で展示コーナーで音関係のアプリを展示してきました。



セッションの方は左の写真みたいな感じでWebの最新技術について色々あったのですが、展示の方に張り付いていたのでほとんど見てません。ちょっと残念。右、CodeIQさんでドーナツもらった図。


左、うなだれるPepperくん(撤収中)。右、FirefoxOS、はじめて触った。


左、Webとガジェット連携の例で湿度センサーとの組み合わせ。右はイベント常連のD.F.MacさんのWebRTC経由で動作する「ち~ん」。


左、MicrosoftさんはWindows10とAzure推し。右はKinectを使ったUI、こういうのはなかなか実用までには時間かかると思うけど未来を感じるねぇ。


左、顔認識による「あっち向いてホイ」。右はネット経由で遠隔地で乾杯ができるシステム。


最後はHTML5Quiz大会。あんどうさんのサイン入りDart本をげとしました。うぇい。

という事で無事終了しました。関係者の皆様お疲れ様でした。
しかしあれだね。横浜からだと千住キャンパス結構遠い。


Posted by g200kg : 10:31 PM : PermaLink

2015/01/21

今度の日曜日はHTML5 Conference

Twitter Google+ Facebook

2015年1月25日、今度の日曜日にhtml5j主催、「HTML5カンファレンス」 が開催されます。

HTML5の最新テクノロジーのセッションが目白押しなのですが、勿論WebAudio/WebMIDI系のセッションもあり、Web Music Developers JP代表として@ryoyakawaiさんが登壇されます。そして今年はブツの展示用の会場が設けられるとの事ですので、このブログを見ていただいている方には目新しいネタではないのですが、Webオーディオ系のデモを幾つか展示してきます。

私は多分オーディオ系デモのコーナーに張り付いています。ご都合付く方は是非どうぞ!


主催:html5j
日時:2015年1月25日(日) 10:00-19:00 (受付開始 9:30)
場所:東京電機大学 千住キャンパス1、2号館
参加費:無料
催し:基調講演、一般公演、展示、ハッカソン、ラジオ・・・

http://events.html5j.org/conference/2015/1/

Posted by g200kg : 5:07 AM : PermaLink

2015/01/05

WebAudioDesignerにGUIデザインエディタを統合する

Twitter Google+ Facebook

去年末くらいからWebAudioDesignerというWebAudioAPIのツールを作り始めていて、足りないものはまだたくさんありますが、やろうとしている事がなんとなく見えてきたかなと思っています。
WebAudioDesignerには3つのモードがあります。初期状態のDesignモードではWeb Audio APIの各種ノードを繋いでいって音を出す事ができます。また、ツマミやキーボードなどのコントローラーからパラメータを操作するように接続する事もできます。

Layoutモードではツマミやキーボードなどのコントローラーだけが表示され、GUIパネルの上に好きなように配置できます。

そしてPlayモードではGUI付きの完成したアプリケーションとして動作させる事ができます。

最終的にはできたものをローカルファイルとしてダウンロードできるようにしたいのですが、そのあたりはまだ途中です

WebAudioDesignerで作ったGUI付きのサンプルはこちら:
WebAudioDesignerサンプル

Posted by g200kg : 12:32 PM : PermaLink

2015/01/01

あけましておめでとうございます

Twitter Google+ Facebook

Posted by g200kg : 9:00 AM : PermaLink

2014/12/29

Base64/Base64Url エンコーダー/デコーダー

Twitter Google+ Facebook
なんかBase64/Base64Urlのエンコーダー、デコーダーを必要になる度に書き直している気がする。探せばいくらでもある事はあるし、毎回書いても大した事ないと言えばないのだけど、それなりに面倒なのでここに割と潰しが効きそうな感じの奴を置いておく事にします。

エンコーダーの方は文字列でもバイト配列でも受け付けて第2引数にtrueを渡すとBase64Urlになります。デコーダーの方は入力は文字列でBase64/Base64Urlのどちらでもデコードでき、第2引数にtrueを渡すと出力が文字列、省力するとバイト配列で戻します。 頑張ればもうちょっと短くなるかも知れないけど、これくらいなら満足かなぁ

WTFPL(Do What The Fuck You Want To Public License) v2 ライセンス : http://www.wtfpl.net
//Licensed under WTFPLv2
function EncBase64(x,base64url){
	var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	var r = "", d = 0, bits = 0, l = x.length, get = function(i){return x[i]};
	if(base64url)
		tab = tab.replace("+/","-_");
	if(typeof(x) == "string")
		get = function(i){return x.charCodeAt(i);};
	for(var i = 0; (i < l) || bits; ++i){
		d <<= 1,++bits;
		if(i < l)
			d = (d << 7) + (get(i) & 0xff), bits += 7;
		while(bits >= 6)
			r += tab[(d >> (bits -= 6)) & 0x3f];
	}
	if(!base64url)
		r += "===".substr(0,((r.length + 3) & ~3) - r.length);
	return r;
}
function DecBase64(x,str){
	x = x.split("=")[0];
	var tab = "-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
	var r = [], d = 0, bits = 0, l = x.length;
	for(var i = 0; i < l; ++i){
		d=(d << 6) + ((tab.indexOf(x[i]) - 2) & 0x3f);
		if((bits += 6) >= 8)
			r.push((d >> (bits -= 8)) & 0xff);
	}
	if(str)
		r = String.fromCharCode.apply(null,r);
	return r;
}


※いや、これ、atob()/btoa()が動かない環境がまだあるとばっかり思っていたので作ったのだけど、今の最新のブラウザはどれもatob()/btoa()をサポートしてるんですね orz。ただまあBase64Urlをatob/btoaでやるにはパディングの処理とか文字の置換が必要なのでその辺だけ前後処理が必要になります。後はデコード結果を直接配列で取りたい時とかは使えるかも。まったく無意味という訳でもないので許してください。

Posted by g200kg : 3:43 PM : PermaLink

2014/12/25

WebAudioAPIのPeriodicWaveを波形テーブルから使う

Twitter Google+ Facebook
Web Audio APIのオシレータのカスタム波形の使い方についての話です。

Web Audio APIのオシレータにはサイン波や鋸歯状波などの基本波形以外にカスタム波形というモードがあります。これを使うと自由な波形を設定できるのですが、ある意味便利、ある意味厄介な事にこの設定が通常の波形の形を指定するのではなく、倍音構成を表すPeriodicWaveと言うテーブルで指定するという仕様になっています。

Web Audio API (日本語訳) : createPeriodicWaveメソッド

オルガンのドローバーのようなものを作るには直接このテーブルの値をいじれば良いので結構音楽的ではあるのですが、逆にチップチューン的なアプリで出力波形を直接指定したい場合にはどうすれば良いのでしょうか。

このPeriodicWaveテーブルは各倍音の強さを表し、

[波形] =フーリエ変換=> [PeriodicWave] => [Oscillator] => [波形]

という関係になりますので、出したい波形をフーリエ変換する事で必要なPeriodicWaveテーブルを得る事ができます。無駄な処理をしているような気もしますが、それが仕様なので諦めましょう。
という事でフーリエ変換? と言えばFFT? どこかにライブラリあるかな? という方向に行くのも良いのですが、FFTというのはフーリエ変換の特殊な計算省略方法でしかないので、FFTなんか使わずにまともにフーリエ変換するという道もあります。

と言われてもなぁ、と思うかも知れませんが、まともなフーリエ変換なんて下の関数程度の話です。
function fourier(waveform,len){
	var real=new Float32Array(len),imag=new Float32Array(len);
	var wavlen=waveform.length;
	for(var i = 0; i < len; ++i){
		for(var j = 0; j < len; ++j){
			var wavj = j / len * wavlen;
			var d = waveform[wavj|0];
			var th = i * j / len * 2 * Math.PI;
			real[i] += Math.cos(th) * d;
			imag[i] += Math.sin(th) * d;
		}
	}
	return [real,imag];
}
この関数fourier()に任意の長さの波形そのままのテーブルwaveformと欲しいテーブルの長さlenを渡すと、periodicWaveを作るための real、imagのテーブルが返ってきます。waveformの長さと返すテーブルの長さは独立していますので、8ステップの入力に対して256の長さのテーブルを返すなど自由にできます。

なお、入力の波形は補間はせず、6-7行目あたりで階段状の波形として処理していますが、必要ならここで線形補間などを入れても良いと思います。また、振幅方向は何もスケーリングしていませんがオシレータが勝手に正規化しますので、入力するテーブルは-1~+1でも0~100でも何でもよくて各値の比率だけが重要です。出力にはreal[0]の所にDCオフセットが出てきますが、ChromeのオシレータはDCオフセットは無視します(これが仕様なのかどうかは今一明確ではありません)。気になるならreal[0]を0にしてDCオフセットを潰しておいた方が良いかも知れません。

この方法の良い所はFFTと違って変換の入出力の長さが2の累乗じゃなくても良い所で、自分が欲しい長さだけを計算する事ができます。

もちろん不利な点としてはテーブルが長くなると計算量が爆発的に多くなる所で、数K単位の長いテーブルを使いたいとか、頻繁にテーブルを作り直したいとか、他の所で既にFFTを使っているとかいう場合にはFFTを使った方が良いかも知れませんが、せいぜい数100要素程度の長さのテーブルを設定を変えた時だけ計算し直したい、というような場合にはわざわざ大きなFFTライブラリなんかを持ち込まないというのもありかなと思います。

これを使ったサンプルプログラムを下に置いてありますので触ってみてください。

http://www.g200kg.com/demo/test/fourier.html

Posted by g200kg : 6:00 AM : PermaLink

2014/12/23

WebGLデモに音を付けるあれこれ

Twitter Google+ Facebook

この記事は「WebGL Advent Calendar 2014」23日目の記事です。

WebGL Advent Calendar 2014

WebGLのアドベントカレンダーですが、音関係のお話です。
と言うかですね、音を扱うためのWeb Audio APIという強力なツールがブラウザ上でサポートされつつありますので、WebGLでイケてるデモを作ったら是非音も付けてみて欲しいな、と思うわけです。昔から音と映像は切っても切れない関係で、両方が揃うとインパクト倍増ですからね。

という事で、この記事では映像は出来たけど音をどうやって付けるか? というあたりのあれこれについての紹介です。

ブラウザのサポート状況

ブラウザ上で音を自由自在に扱えるという「Web Audio API」ですが、ブラウザサポート状況はまだまだ道半ばで、フルにガシガシ使うにはブラウザを限定する必要があります。今現在の各ブラウザのサポート状況は下の表のような感じです。

Chrome最もサポートが進んでおり、リファレンスとなっています
SafariYosemiteでかなりChromeに近くなりましたが、一部挙動が異なります。それ以前のものはAPIが古い仕様になっていたりします
Firefox一通りAPIがサポートされた所ですが、まだ挙動が安定しない事が割とよくあります
IE開発に着手した事がアナウンスされましたが、まだ出てきていません

いやもうmp3やらoggやらで裏で鳴らしたい音も出来上がってます、という場合、別にややこしい事はしないで<audio>タグで埋め込むだけでいいですね。と言っては身も蓋もないですが、今の所単純に準備済みのBGMをどの環境でも同じように鳴らしたいという話なら<audio>タグを使うのが有力です。これなら大体どのブラウザでも最新のものを使えば対応しています。ただ、これだと映像と音はそれぞれ勝手に走っているだけなので相互作用的なものを作るのは困難です。各ブラウザ共開発は進みつつありますので今後に期待しましょう。

なお、<audio>タグを使った埋め込みでもWeb Audio APIと連携させる事で相互作用を作る事も可能です。Web Audio APIの全貌をちゃんと知りたいという方はこちらをどうぞ。仕様の日本語訳とか解説を置いてあります。
Web Audio API 日本語訳
Web Audio API 解説

AutoBeats

とりあえずお手軽に音を鳴らす方法としてAutoBeatsというものをご紹介します。

https://github.com/g200kg/AutoBeats

<audio>タグで楽曲を埋め込むにしても、権利関係の問題は結構厄介ですね。WebGLベースでちょっとしたデモを作ろうとしても流石に曲を作る所まで手が回らないという人も多いかと思います。AutoBeatsはいわゆる自動作曲でタイトルを設定するだけで勝手に曲のようなものを演奏しますので手軽に音を付けたいという場合には向いているかと思います。使い方は単純で、まず、autobeats.jsを読み込みます。polymer版もありますが、単にJavaScriptで使うだけならファイルとしてはautobeats.jsだけあれば良いです。
 <script src="autobeats.js"></script>
そしてJavaScript内でAutoBeatsオブジェクトを作ってstart()させます。
beats = new AutoBeats("song title");
beats.start();
これだけで曲らしきものが演奏されます。"song title"の部分は乱数のシードみたいなものですから適当に設定すれば曲調が変わります。

サンプルはここにあります。このページで「title」を色々書き換えてみてください。
AutoBeatsサンプル

音と映像の相互作用

さて、これで音を付ける事ができましたが映像と音は相互に作用してこそ威力を発揮します。ここでは音に合わせて映像が変化するビジュアライザー的なものの作り方を紹介します。Web Audio APIにはビジュアライザーなどに使えるAnalyserノードというものがあるのでこれを利用します。AutoBeatsは単体で勝手に音を出しますが音を出力先を指定できるようになっていますので、ここにAnalyserを接続します。
audioctx=new AudioContext();
analyser=audioctx.createAnalyser();
analyser.connect(audioctx.destination);
beats=new AutoBeats("song title",0,audioctx,analyser);
beats.start();
何をやっているかと言うとWeb Audio APIの元締めであるAudioContextを外部から与えてAnalyserを経由して音を出すようにします。

[AutoBeats] => [Analyser] => [AudioContext.destination]

こういう繋ぎになります。
音のデータの取り出し方はこのanalyserのgetByteTimeDomainData()を呼び出せば波形そのままのデータ、getFrequencyData()を呼び出せばスペクトラムデータになります。引数には適当な長さのUint8Arrayを渡せば配列を埋めてくれます。後はこれを表示に反映するだけですね。
シェーダーで使うのでしたら、一度canvasのimgdatに落としてTexture2D経由で受け渡しするのが一般的かと思います。
x=window.innerWidth;
y=window.innerHeight;
wavdat=new Uint8Array(256);
wavimgdat=document.createElement("canvas").getContext("2d").createImageData(256,1);
z=Date.now();
(function(){
  analyser.getByteTimeDomainData(wavdat);  //波形データの取得
//analyser.getByteFrequencyData(wavdat);  //こっちを使うとスペクトラムデータ
  for(var i=0;i<256;++i) {
    var j=i<<2;
    wavimgdat.data[j]=wavdat[i];
    wavimgdat.data[j+3]=255;
  }
  gl.clear(gl.COLOR_BUFFER_BIT);
  gl.uniform1f(u.t,(Date.now()-z)*0.001);//<==経過時間(msec)
  gl.uniform2fv(u.r,[x,y]);//<==画面のレゾリューション
  gl.uniform1i(u.wav,0);
  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, wavimgdat);//<==音データ
  gl.drawArrays(gl.TRIANGLE_STRIP,0,4);
  gl.flush();
  requestAnimationFrame(arguments.callee);
})();
こんな感じで、テクスチャー(ここでは256 x 1)にしてGLSLに渡して、後は渡されたテクスチャーデータを使ってシェーダーで好きなように描画します。ちょっと前に作った奴ですが下にサンプルがありますので参考にどうぞ。
ここでは渡された256 x 1のテクスチャーwavを
vec2 p=(gl_FragCoord.xy*2.-reso)/reso;
vec4 v=texture2D(wav,vec2((p.x+1.)*.5,0.));
で読み出し、
vec3 wave(vec2 p,float v){
  float l=p.y-v;
  float r=pow(max(0.,1.-distance(p+vec2(0.,+.5),vec2(p.x,v))),10.0);
  return vec3(r,r*r,0.);
}
と言う風に描画の色を決めて波形データを表示しています。

みなさんご存じのGLSL sandboxなんかでぐりぐり動くデモでもインプットとなる情報は時間とマウス座標くらいですけど、ここに音データが加わるとまた表現の幅が広くなりますね。

Planets

Posted by g200kg : 9:15 AM : PermaLink

g200kg