2009年10月22日木曜日

audioタグとJavaScriptでピアノを作ろうとしたけど諦めた

タイトル通りの話をざっくり書いてみます。
(下の方に(挫折した)サンプルあります)

HTML5といえば、canvasタグたーのしぃーひゃっほーいで、videoタグとaudioタグでリッチなコンテンツもFlashなしで見せてやんよ、って感じでございますが、canvasタグは個人的にも多少はいじってみて可能性を感じましたが、videoタグとaudioタグはこれといった「おもしろ方向性」が思いつかなかったので今まで全然いじりませんでした。が、ちょっと思いつきまして、audioタグ利用してブラウザだけで動作するピアノを作ってみようと、こんなことをやってみました。


まずピアノ単音をG1~C5まで用意します。wavファイルで2.5sくらいの長さの。
GarageBandでソフト音源トラックを作り、音色ピアノ、BPM120、4分音符1つ、をwavで書き出しました。GarageBandが最短小節数8という縛りがあるようで、無駄に長いwavが生成されたので、QuickTimeProで2.5sまで短くして、さらにもっと低レートにして、変換します。ってのをG1~C5まで42音あるのでそれだけの回数やりました。アホみたいです。


音ネタが用意できたら、html内にaudioタグを43個作ります。idに id_C3
とかつけて、それぞれのsrcに作ったwavを指定してloadします。ちなみに、制御はJavaScriptからのみ行うので、controller
= falseで、ページ内にPlayerっぽいものを表示しません。用意したwavは42個なのに43個のタグとは如何に?それはあとで書きます。


これで、鍵盤の絵描いて(各鍵盤は独立したobjで)、たとえばC3の鍵盤クリックしたら、onClick =
document.getElementById("id_C3").play(); で該当する音鳴らす、とかやればピアノができるなーと。

ただそれだけだとおもしろくないので、シーケンサーみたいに「再生」してみようかと。でも処理が複雑且つ重くなりそうなので、まずは和音は無視の方向で、単音でメロディーを奏でるだけのを考えます(って思考が先走ったので、鍵盤は作成してないです)。メロディを記述して、それを読み込んで順次タイミング合わせて音鳴らしていく、って感じですが、BASICやってた方はわかるでしょうか、PLAYコマンドの中身みたいな感じで書いて、それを解釈して再生ってのを考えました。

たとえば。「チューリップ」の冒頭(♪さいたーさいたーちゅーりっぷーのはーなーがー)なら、こんな感じに書くことにします。

C3.4,D3.4,E3.4,R.4,C3.4,D3.4,E3.4,R.4,G3.4,E3.4,D3.4,C3.4,D3.4,E3.4,D3.4,R.4

C3.4は、3オクターブ目のC、長さは4分音符、を意味する、というフォーマットを考えました。Rは休符です。

さてここで、42音用意したのに43個audioタグを作った意味を書いておきます。43個目は、42個のどれでもいいので名前変えてコピーしてloadしてobj.volume
= 0.0 にして、休符代わりに使います。
はい。

C3.4,D3.4,E3.4,R.4,C3.4,D3.4,E3.4,R.4,G3.4,E3.4,D3.4,C3.4,D3.4,E3.4,D3.4,R.4

これをどう読み込んで、解釈して、audioタグの制御に使うか、ですが、全部JavaScriptでやります。

http://なんららかんたら?BPM=120&Melody=C3.4,D3.4,E3.4,R.4,C3.4,D3.4,E3.4,R.4

という感じにサーバサイドでなんかやるっぽい記述なんかしてみちゃったりして。別にたいしたことやるわけじゃないのですが、document.locationでURI拾ってきて、?で分割、&で分割、"指定ワード="で対象を変数に読み込む、とやります。で、Melody=で取得した文字列は、さらにカンマで分割して配列に。この配列を順次再生していけばいいのです。


まず配列先頭には「C3.4」があります。ピリオドで分割して、キーと長さにわけて、

document.getElementById("id_C3").play();

で音を鳴らします。が、長さが問題。まあ自然減衰するピアノ音ってことで深く考えず、長さは次の音をいつ鳴らすか、にします。とすると、BPM120で4分音符の長さ、というのを計算すると、500msなので、配列の次の要素「D3.4」を500ms後に鳴らせばいい、ということに。

具体的には、今何個目の音(配列のデータ)を鳴らしているかを管理する変数を用意しておき、それをインクリメントして、

setTimeout(playNextSound, 500);

とかこんな感じで、500ms後に処理が実行されるようにします。これを配列が空になるまで、順繰りやっていけばいいのです。やったね!


…とうまくできたーと思ったのですが、まともなメロディを作ろうとすると、なんかうまく再生タイミングが合わなかったりします。
Safari4(audioタグサポートしてるはずだけど)では最初の音源の読み込みが激重かったり、同じキーを連続で鳴らすと汚かったり。Firefoxでもテンポ設定次第で、指定タイミングで発音されない音が出たり(Script自体は指定タイミングで走っているが、発音がずれる)、と、現実的なモノはできませんでした。あとiPhoneのSafariから使えるブラウザベースのをピアノシーケンサーを夢見ていたのですが、iPhone版Safariはもっとダメでした。audioタグを思うように制御できん。


一応サンプル。
Macの最新Safari、最新Firefox、Windowsなら最新Firefox、以外ではアクセスしない方がいいです。あとplayボタンが緑になるまで待って、クリックしてください。読み込みはMac Safariで10秒くらい。音量注意。(リンク先、MelodyのEditできそうな感じになってますが、いやできるのですが、動作不安定です)

audio tag sample(聞いたことある曲がサンプルとして読み込まれます)

audio tag sample (URL引数をPlay)(上に書いたようにチューリップをURLで渡してます)


やっぱこういう、音(とか映像)をぐりぐり用いるような遊びは、Flashやサーバサイドの力借りてやるべし、ってなところでしょうかね、今のところは。うーん、PC性能にもよるのかもしれませんが、PC性能が問題なくても、ブラウザの力の限界的なところかもしれません。僕のプログラミング能力が低いせいかもしれません。PrototypeやjQuery等のJavaScriptのLibraryまともにさわったことすらないもんでして…。

2009年10月12日月曜日

連休中に撮った写真

Flickrから3枚。金木犀、夕暮れ前、野アザミ。一応iPhotoで露出、コントラスト、色調など補正してあります。トリミングは、今回はしてるのないかな。blogへの貼付けは、各写真のページでALL SIZES→指定サイズ→表示されてるhtmlコードをひとつずつコピペ。枚数多いと面倒。

金木犀/Orange osmanthuscoming twilightノアザミ/Cirsium japonicum


こっちはTwitterで投稿してた写真5枚。Twitterログhtmlソース化の自作JavaScriptを改変して、↓みたいに、画像の投稿だけ抜粋してhtmlコード吐くやつ作った。title属性につぶやき本文埋め込まれてます。


おまけ。チョウを運ぶアリ。

ant work from chordstriker on Vimeo.

2009年10月10日土曜日

最近のTwitter投稿写真(2009/09/29 - 10/9)

そんなわけで、写真ばっかりTwitterで投稿してる日ってのはそんなになかったのですが、まあいくつかたまってきたので、ここにまとめてみる。投稿時にTweetしたテキストは画像にポインタのせて少々すると出ます。っていうかtitle属性にtweet textを突っ込んだだけ。




今回は6割くらい手動編集。過去500Tweetから画像投稿のみ抜き出して、↑のhtmlソース吐くやつも作りたいなぁ。