RSS Twitter Facebook


« 2014年11月 | 2014年12月のアーカイブ | 2015年01月 »

2014/12/29

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


なんか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を波形テーブルから使う


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デモに音を付けるあれこれ


この記事は「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

2014/12/06

WebAudioDesignerでボコーダーボイスを作る


一応WebAudioAPIのノードの繋ぎだけでボコーダーっぽい音を出しています。
見ての通り結構大変な事になっていますが、入力音声を6分割してエンベロープを取り出し、再合成しているだけです。
本来ならキャリア側にもフィルターバンクを入れて分解して変調する所ですが、さすがに溢れそうなのでサイン波を加算する感じになっています。

何が溢れるかというとグラフのデータをURL化してるのが長くなりすぎます。ブラウザの限界はもうちょっと行けそうなんだけどgithub上で動かしてる関係でどうやらURLの長さは4Kが限界の模様。

Vocoder voice on WebAudioDesigner


posted by g200kg : 9:42 PM : PermaLink

KDJ-ONEキックスターター開始記念


12月5日、一部で話題になっているKDJ-ONEという機材のクラウドファンディング KickStarter/IndieGogoでの支援募集開始記念お披露目会がありましたのでお邪魔してきました。

ゲーム機風の小さな筐体に音楽制作に必要なシーケンサー/シンセ/サンプラーなどを一式詰め込んだという機器になっています。大きさの雰囲気は右の写真のような感じで、ディスプレイはタッチ操作でき、鍵盤ボタンはベロシティ対応です。
ソフトウェアをほぼ1人で書いているという大和田氏、出荷は来年7月でソフトウェアはまだ色々変更が入るそうです。XYパッド的なものも計画中との事。右のオートメーションのグラフエディタはなかなか使いやすそう。
入出力端子の様子。ヘッドフォン端子、ライン出力、マイク入力とUSBが2つあります。ちなみにこれはまだ試作のもので筐体の質感がマットになっていますが、製品版は光沢ありの塗装になるそうです。て事で右の写真、こんな奴もいました。名前はちゃんと決まっていないらしいです。頭にかぶるだけの被り物は作りやすそうだなといらん事を考えたり。

仕様の詳細等はこちらをどうぞ
http://www.kdj-one.jp/

またKickStarter/IndieGogoでの募集という事で、慣れていない方にはちょっと敷居が高いかも知れませんが、「DTMステーション」さんで凄く親切な手順のマニュアルを書かれていますのでそちらを見ながらどうぞ。今なら早期割引があって$395+(送料$10)になっています。
「DTMステーション:英語サイトでも大丈夫!KDJ-ONE購入手順完全マニュアル」

posted by g200kg : 11:36 AM : PermaLink

2014/12/02

WebAudioDesignerにツマミを付ける


WebAudioDesignerでツマミからパラメータをコントロールできるようになりました。
簡単なシンセくらいならGUI上でさくっと作れるようにしたいんだけど、まだ色々足りません。でもWebAudioAPIでどんな事ができるのか把握してもらうには良いツールになるんじゃないかなあ。

Wah with knob controls

WebAudioDesignerのGitHubページ

posted by g200kg : 12:01 PM : PermaLink

2014/12/01

第14回アナログシンセ・ビルダーズ・サミット


11月29日科学技術館で開催されたアナログシンセ・ビルダーズ・サミットに出展してきました。私が出したのは今更のGemBox Synth/Frisk SynthとLiveBeatsだったのですが、今年もなかなか興味深い話が色々聞けました。

シンセDIY界では伝説的な山下春生氏の山下シンセの説明。右は山下氏が今作っている新作の回転式のレバーで音程を決める楽器。学校のワークショップなんかで使う予定で子供でも作れるように色々工夫しているとの事。
こちらも電子楽器DIY界ではレジェンドになっている沖田氏のボコーダー(通称沖田ボコーダー)の現物基板。右は最近の作品、販売中のマトリョーシカ型のテルミン、マトミョミンと試作品のヒューマンボイス・テルミン。
左、でんはちゃんねるさんのLEDバッチ。右は日本では希少なユーロラック系ガレージメーカー、Hikari Instrumentsさんのモジュール。木製ケースが良い味を出しています。
左Chuck氏のモジュラーシステムはGemBoxシンセをハックしてポリフォニック化したものが搭載されています。右はアルミを削り出したというながさわさんの謎の2弦ギター。
左はオルムさんの桐タンス。ごつそうだけど片手で持ち運べるとの事。右、houshuさんのスネアのスナッピーっぽい音を狙ったノイズジェネレータを搭載したシンセ。外装は実は紙なんだけど遠目には全然そう見えない。
左、一部で話題になってた小野さん(違った、恵比寿さん?)の痛AIRAの現物を確認。右、ノイズジェネレータにFMラジオをそのまま搭載したと言う公生32+さんのシステム。電波状況によってノイズジェネレータがノイズじゃなくなるとか...。
左、今関さんが開発中のフルート型MIDIコン。オクターブ切り替えがボタンでなく息の吹き込み方でできるというこだわりの品。という事であとは中華に突入。

私はこの3年ほどの様子しか知らないのですが、アナログシンセ・ビルダーズ・サミットももう14回目なんですね。運営ほんとうにご苦労様です。という事で濃すぎる年末イベントは終了しました。

posted by g200kg : 6:00 AM : PermaLink

« 2014年11月 | 2014年12月のアーカイブ | 2015年01月 »


g200kg