2012年12月23日日曜日

プロジェクション・マッピングとフラグメント・シェーダ

先日、ライゾマティクスさんのワークショップでプロジェクション・マッピングについて教えてもらいました。その際利用したmapamokが、投影データはフラグメント・シェーダで描く(キリッ)って内容だったので、頑張ってシェーダ書きました。近頃はシェーダは(僕の中では)Java以上にポータルなわけで、せっかくなのでWebGL上で動かしてみました。一応、Chrome、Safari、Firefoxで表示できてると思います。


モデルデータはかにひらさんが配布していた物を利用させて頂きました。ただ、元データはメタセコイア形式だったので、ply形式に変換して使ってます。

plyローダ作ったついでに、いくつか有名なデータを読み込んでみたんですが、100万ポリゴンくらいになると辛く、Happy Buddhaは描画レートが数フレームくらいまで落ちちゃいました。このくらいは平気だと思ってたんだけど・・・あまり詳しく原因見てませんので、別に理由あるかも。同僚はミクとか普通に動かしてたし。

2012年12月9日日曜日

USB接続が可能な音源デバイスの自作

前置き

そういえば前回書き忘れましたが、今回の記事と前回の記事は、Web Music Developers JP Advent Calendar 2012に向けて書かれました。

デバイス自作のための準備

インタフェースの検討

全然ウェブとは関係ないですが、今回はちょっとテーマを広げて音源デバイスの自作について書きます。自作デバイスで全てを完結させることは困難ですので、どうしても外部から制御するためのインタフェースを載せる必要が出てきます。ハード工作的にはMIDIの口を作ることは簡単なのですが、やり取りできる情報は基本MIDI準拠の情報に限定されますので、MIDI⇔デバイスの間でプロトコル変換してあげる必要があり、それはそれで(デバッグが)面倒です。そこで今更ですがUSBの登場です。USBは利用する分には便利なのですが、いざ自作しようとすると仕様も大きく躊躇してしまいがちですが、簡単な制御だけなら比較的簡単に実装できます。また、USBを自作した時に問題になるのがドライバですが、将来的にはUSB APIを使ってブラウザから制御できるようになるんじゃないかなぁ・・・なんて楽観的に考えてます。ちなみにUSB APIはドライバを書く時と同じようなレイヤーのAPIになっています。(注:私もまだUSB APIは試してみた事がありません。gdkさんともお話をした事はなく、あくまで個人的かつ客観的な希望です。)

USBインタフェースの選択

電子工作レベルでUSBインタフェースを作ろうと思うと、だいたい選択肢は2つです。1つは今回このあと紹介するデバイスでも利用しているPIC18F2550を利用する方法。もう1つはAVRを利用する方法です。
PIC18F2550は秋月で350円で入手可能、かつ下の方に貼ったように書籍もでていますので、比較的敷居は低いのではないかと思います。また筆者さんがウェブでも参考記事を書いています。ただ、普通に開発しようとするとベンダー提供のUSBフレームワークを使う必要があり、標準開発環境MPLABが必須になります。MPLABはWindows版しかなく・・・と書こうと思ったんですが、MPLAB XになってWindows/Mac/Linuxが網羅されてるようです。この辺に日本語で記事が書かれてますが、普通にPIC18F2550の開発ができるようです。自分が試した頃は無償だと制限が多くWindows縛りもあったため、SDCCというオープンソースのCコンパイラ向けに、スクラッチでUSB関連のレジスタを叩くコードを書きました。あまり意味がなくなってしまったかもしれませんが、あとでこの辺も軽く紹介します。
AVRを使う方法がちょっとトリッキーで、V-USBというソフトウェアベースのUSBインタフェースを使います。これはUSBのD+/D-の信号をマイコンで直接読み書きしてくれるライブラリです。物理層の信号をマイコンが作るため1.5Mbpsの速度で汎用I/Oを0/1でパタパタさせます。マイコンのクロックが12MHz程度である事を考えると、ほぼ常時0/1の制御をしている事になります。よって、自作デバイスの制御にある程度CPUパワーが必要な場合には向きません。あるいはマイコン1つUSBインタフェースに専念させて、別のマイコンとシリアル接続、なんて使い方になります。こちらの方法については以前サンプル付きで詳しく書きましたので、そちらを参照して下さい。100円で手に入るTINY2313が使えるのが魅力です。また開発環境もgccなので安心・・・な人にとっては安心。人によっては不安の種になるかもしれませんが。
ちなみにPICの場合はハードウェアがUSBの信号をハンドルしてくれるので、ソフトウェアはデバイス設定やプロトコルの送受信をデバイスのレジスタ経由で指示するだけですみます。またUSB 2.0に完全対応しています。一方でAVRを使う場合にはUSB 1.1互換でかつlow-speedモードのみ利用できます。USB規格はlow-speedモードでのバルク転送、アイソクロナス転送を認めていないため、それらを使いたい場合には利用できません。

音源デバイス

音源デバイスを自作したい場合、大きく分けて2つのモチベーションがあるかと思います。1つは既存のデバイスをPCに繋げるようにしたい、というケース、もう1つ完全オリジナルの音源をスクラッチから開発するとうケースです。
私の場合は前者のケース。PSGやFM音源など往年の音源チップを入手し、PCから操作できるようにする、という物です。類似ケースとして、MIDI対応以前のビンテージシンセの接続なんかも考えられるでしょうか(そういっやシンセの場合、名器と呼ばれるものなら必ずMIDI化改造が出まわってますけどね)。
後者の場合はマイコンで簡易音源を自作したり、FPGAで本格的な音源を自作したりと言った感じですね。以前AVRで実験してた事がありますが、20MHzあればC言語で書いてもPSGくらいはエミュレーションできますし、アセンブラで書けばPSG+SCCやFM音源も十分にいけます。FPGAで自作する場合にはUSB回路自体をFPGAに入れてしまうのも手でしょうか。OpenCoresに使えるIPが幾つかあります。

製作例

PSG音源

秋月でも入手できる、いわゆるPSG音源互換のチップとしてYMZ294があります。コイツを使って作ったデバイスがこれ。作りが適当なのはご愛嬌。
写真左側のボードがUSB部、右側のボードがPSG音源部になります。

USB部の拡大写真です。右下の端子が汎用I/Oに接続され、別ボードの音源と繋げるようになってます。あと、テスト時に抜き差しで端子が弱ると嫌なので、電源スイッチをつけてます。それ以外はだいたいデータシートに載ってるリファレンス回路のまま。1000円もかからずに作れます。
こちらがPSG音源部。音源についてる4MHzクロックを使えば楽なのですが、ここでは敢えて家庭ゲーム機やMSXなどで使われていた3.58MHzを入力しています。またYMZ294の右側にPIC12F629が乗っているのですが、これは何か仕事をしているわけではなく、単にクロックを発振させるためだけに使っています。昔ながらのやり方だったら水晶の周りに発振回路を組むわけですが、面倒ですし。最近のマイコンだったらたいてい内部に色々な発振回路を持っていて、適切にfuse設定を書き込んでやれば発振後のクロックを出力してくれます。部品点数を減らして価格を抑えるって意味では海外のマイコンは非常に便利にできています。

SID音源

USB部はPSG音源と共通になっていますのでSID音源部のみの紹介です。
左の写真がSID音源部のボードになります。ところで、みなさんSID音源ってご存知でしょうか? Commodore 64に搭載されていた音源チップで、同時期の音源の中ではずば抜けて多機能な音源です。MOS Technologyの6581と呼ばれる物が初期の音源で、後期には機能追加された8580と呼ばれる物が流通しています。日本ではなかなか入手できず、海外のオークションで売られているものも故障品が多く、良品入手には非常に苦労しました。S.F.Pageさんのサイトに調度良い記事があったので気になる人は読んでみて下さい。一言で言えばワンチップ・ぷちアナログシンセ。萌える。
PSGと比べてそんなに差がないように見えるかもしれませんが、背面の配線は倍以上あります。なので下に見えるのは74374でラッチ。PICとの間のインタフェースのピン数の都合上、アドレスとデータを別サイクルに分けて転送してます。
さらに右の写真でアップした部分はSID音源ならではの苦労部分、MAX662による変圧回路。あと、ちょろっと見えてる黄色いコンデンサ。上の写真では6581とラッチの間に見える2つの黄色い部品です。実はこれらがSIDがアナログシンセたる所以です。実は6581は2つの電源を必要とします。デジタル部は5Vなので特に苦労はないのですが、アナログ部に使う電圧が12Vとちょっと、というかかなり高めなのです。さらに先ほど述べたコンデンサはアナログフィルタの特性を決める素子になっており、このコンデンサ如何により音色が変わってしまいます。って事で、部品調達にもちょっと手間とお金がかかりました。あと、もう1つ致命的なのが消費電力。実は6581はPMOSです。CMOSじゃないんです。なので消費電力は高めで、電源を入れるとあっという間に驚くほど熱くなります。ほんと最新のCPUバリの発熱。0.6〜1.0Wの消費電力となっており、実は変圧器の変換効率を考えると、2枚のボード合わせてUSBバスパワーの2.5Wを守っているのか怪しい・・・。

資料など

USB-PSG

地味ですが動画など。最初に一瞬出てくるコンソールはUSBモジュールのデバッグ用シリアル出力です。説明しませんでしたがUSBモジュールについてる右上の4本ピンがシリアルになってます。Windowsから思ってもいない初期化シーケンスが飛んできたりして、初期は結構はまりました。2つ目に出てくるコンソールはUSB接続先のLinuxマシンで、拙作のksgplayをUSB-PSG向けに修正したものを使い楽曲データを流し込んでます。KSGってのはMSX用の楽曲ログフォーマットで、PSGやOPLLの実装をチェックするために昔仕事で作った簡易プレイヤーがksgplayです。まぁ、実体は簡易MSXエミュレータです。YMZ294の横にあった2本品が出力になっていて、画面に見えてる小さい丸いスピーカーに繋いで音を出してます。
本当に動いてるの?って聞かれると、レジスタアクセスランプのLEDが光ってるでしょ、くらいしか証拠がない。

USB-SID


こちらはsidplay2という、本来は音源をエミュレーションして再生するオープンソースのプレイヤーを改造して実機対応にしています。最初の2つのチップは壊れていて、これは3つ目に入手したチップだったのですが、どうもch.1の音量が小さくて・・・やはりチップが完全な状態じゃないらしい。もちろん自分の回路がおかしくてチップを壊している可能性も否定できないわけですが。
こちらはアクセスランプすらないので、すでに実機を映すことすら諦めました。

PIC18F2550 USB制御コード

SDCC向けに書いたUSB制御コード。完全とは程遠いかもしれませんが、基本的な部分は問題なく動いてます。同じような事をしたい人の参考になるかもしれないので、一応Google Codeに当時のコードをアップしておきました。なんかもう、ファイル名がtest.cですよ。少なくともWindows Vistaと当時のLinuxのUSB初期化シーケンスには耐えてました。WindowsのUSBスタックも、だんだん厳しく仕様準拠を要求してきてるらしくて、もしかしたら7や8では動かない可能性もなきにしもあらず。その時は足りない部分をきちんと実装してあげて下さい。

参考書籍

改訂版が出ているらしいので、そちらをリンク。ちなみに自分は改定前の古い方を持ってます。MPLABからMPLAB Xになって色々と変わってるかもしれないので、使うツールに合わせて本を選んだほうが良いかも。

2012年12月2日日曜日

WebMidiLinkで遊んでみた

概要

ブラウザ上で動作するソフトウェア音源をボチボチ見かけるようになりました。g200kgさんの発案したWebMidiLinkは、こういった音源をJavaScriptから制御するための仕様です。あまり難しいことは考えずに手軽に利用できるのが嬉しいところです。
ということで、拙作のJavaScript向け音楽ライブラリをWebMidiLinkに対応させて、SMFを再生してみました。

おさらい

WebMidiLinkの話に入る前に、いくつか関連技術について説明しておきます。


Web Audio API

JavaScriptからオーディオを制御するために導入されたAPIです。W3CでGoogleのChris Rogersを中心に仕様の検討が進められています。現在利用できるブラウザはChromeとSafari 6のみですが、Firefoxも現在着々と実装を進めています。g200kgさんが指摘しているように、ChromeとSafariで若干動作が異なる部分もありますが、基本的には実装をWebKitの中で共有しており、ChromeとSafariでは製品で利用しているWebKitのバージョンが異なるのが主な原因と思われます。
今までもオーディオを制御する事はできたじゃないか、と思われる方もいるかもしれませんが、この仕様の(個人的に)一番嬉しいところは、JavaScriptで直接波形をリアルタイム生成できるところです。つまり、JavaScriptでシンセサイザーを実装したりできるわけです。また、オシレータやフィルタ、ディレイといった基本的な音響処理がコンポーネントとして提供されており、これらを接続して音響プログラムを楽しむこともできます。このあたりはEijiさんのはじめてのWeb Audio APIが参考になると思います。

Web MIDI API

同様にMIDIを制御するために考案中のAPIです。同じくW3Cで仕様が議論されていますが、今のところ実装が存在しません。Editorの1人Chris Wilsonが、最近W3Cのpublic-audioの場でWebKit上で実装を進める意思のある旨を表明しました。
WebMidiLinkはこの仕様とは独立したアイデアで、今すぐに利用できるAPIでもあります。

WebMibiLink

WebMidiLinkについて簡単な仕様の説明とデモを紹介します。

仕様について

g200kgさんが考案した仕様で、Web Audio APIなどを使って作られたブラウザ上で動作するシンセサイザーを接続するための規格です。MIDIを基本としており、この仕様ではMIDI信号をどうやってJavaScript上で表現し、コンポーネント間でやりとりするかが規定されています。g200kgさんの仕様ページが、端的かつ具体的なサンプル付きで非常にわかりやすいため、仕様の具体的な説明は割愛します。
ところで、ソフトウェアで音源を実装する場合、一定サイズのバッファ単位で波形合成を行うため、波形合成のタイミングと再生されるタイミングの時間差は一定になりません。別の言い方をすると、波形合成が1秒ごとに行われた場合は、外部からのMIDI入力も1秒ごとに反映されることになります。この問題を解決するためには、MIDI信号に時間情報を載せてあげるか、ソフトウェア音源の波形合成をなるべく小さい単位で実施してあげる必要があります。WebMidiLinkでは特に時間をケアしていませんので、音源はなるべく小さい単位で合成しないと、カクカクの演奏になってしまいます。
今回試してみた範囲では、時間方向の精度はほぼ気にならないレベルでした。

SMF再生デモ

下の黒い領域にSMF(MID)ファイルを放り込んで下さい。下の枠に表示されているWebMidiLink対応音源で再生されます。利用する音源はドロップダウンメニューから選択できます。標準ではg200kgさんのGMPlayerがロードされています。
* * * * * * * * * * * * * * * *
DRAG SMF FILE TO HERE






デモの説明

デモを見て技術的な部分に興味を持った方、ぜひ以下を読んでみて下さい。

ライブラリについて

T'SoundSystemという自前ライブラリのJavaScript版に追加機能としてSMF再生やWebMidiLinkを実装しました。元々はネイティブ実装されてTSSCPなどに使われていた、MML処理系一式+チップチューンエミュレーションのライブラリです。Google Codeにてソース一式公開しています。
T'SoundSystemでは、MasterChannel、Channel、Playerという概念があります。一番わかり易いのがPlayerで、各種ファイルフォーマットを解析して再生する役目を担います。今回はSMF対応のSmfPlayerを利用します。Channelは音源を表し、Playerにより操作されます。SmfPlayerからの操作を意図したMidiChannelがあったのですが、今回はMidiChannelから派生したWebMidiLinkMidiChannelを用意しました。最後のMasterChannelは波形合成を管理します。波形合成のストリーム管理と合成粒度を制御しつつ、Playerへのタイマーを提供しています。波形合成の粒度をPlayerが求める粒度と一致させることができるので、時間にブレのない演奏を実現します。また、複数のChannelを登録した場合には、ミキサーの役目も担います。WebMidiLinkでは、ソフトウェア音源のみを仮定しているわけではなく、また波形合成も各音源の責任によって行われます。よって、今回はPlayerへのタイマーのみを提供する、TimerMasterChannelを用意しました。

利用の仕方

以下にサンプルコードを掲載しますが、とっても簡単。WebMidiLink対応音源をiframeで埋め込む場合の例を示します。

<iframe id="wml" src="[WebMidiLink対応音源のURL]"></iframe>
// まずはWebMidiLinkMidiChannelを作成します。
// 引数にはMIDI信号を送るためのメッセージポートの口を指定します。
// これにより、受け取った演奏信号をWebMidiLinkに変換して出力します。
var midi = new WebMidiLinkMidiChannel(document.getElementById("wml").contentWindow);
// SmfPlayerを作成し、デフォルト音源として先ほど作成したmidiを登録します。
var smf = new SmfPlayer();
smf.setDevice(SmfPlayer.TRACK_DEFAULT, midi);
// TimerMasterChannelを作成します。
// SmfPlayerのsetMasterChannelで登録してあげると、登録されたMidiChannel
// 全てを指定されたMasterChannelに登録します。
// またPlayerのタイマーとしても自動的にMasterChannelを利用するようにします。

smf.setMasterChannel(new TimerMasterChannel(TimerMasterChannel.MODE_DEFAULT));
// 最後に再生。引数はMIDIデータを含むArrayBufferを与えて下さい。
smf.play(midi_data);

ArrayBufferについて

比較的最近に導入された仕様なので、知らない人向けに簡単に説明しておきますと、要するにJavaScriptで効率的にバイナリを扱うための仕組みだと思って下さい。例えば、Web経由で取得したSMFファイルをArrayBufferとして読み込むためには、以下の様なコードを書きます。簡単ですね!
var xhr = new XMLHttpRequest();xhr.open("get", "foo.mid", true);
xhr.responseType = "arraybuffer";
xgr.onload = function () {
    smf.play(xhr.response);
};
xhr.send(); 

バックグラウンドでの演奏について

このページ上でのデモはTimerMasterChannelの動作モードがMODE_INTERVALになっています。つまり、古典的なsetIntervalを使ってタイマーを実現しているのですが、1つ問題があります。Chromeで実行しているとタブを切り替えた際に演奏が極端に遅くなります。これを回避する方法はいくつかあり、TimerMasterChannelにも実装されています。引数として、MODE_TIMER_WORKERを指定すれば、バックグラウンドじの動作も安定します。MODE_DEFAULTでも現在はMODE_TIMER_WORKERが選ばれるようになっています。

まとめ

以上、駆け足でしたが、Web Audio APIと、それを使ったMIDIベースのソフトウェア音源の取り組みWebMidiLinkを紹介させて頂きました。また、どさくさに紛れて拙作ライブラリのT'SoundSystemも紹介しました。
これをきっかけにブラウザ上での音系アプリ開発に興味を持ってくれる人が1人でもいますように・・・。
なお、この記事はWeb Music Developers JP Advent Calendar 2012の一環として執筆されました。

2012年6月3日日曜日

ネットワーク関連の本、下から上まで


最近、面白そうなネットワーク本を見つけたので、それを含めて蔵書の紹介。どれも名著と呼ばれるものばかりのはずです。ただ、書いてみて気づいたんだけど、ここで一番上のレイヤーって言ってる本ですら、今時のほとんどの人にとっては目に触れる事のない最下層レイヤーかも・・・。それでも気になるって人だけ読んでください。

Principles and Practices of Interconnection Networks

京のネットワークコントローラを設計する際に散々お世話になった教科書。ルーティング、フロー制御、トポロジについて論理からハードウェア設計まで丁寧に説明されています。シミュレーションによる性能評価のノウハウも書かれてるので、この分野(インターコネクトアーキテクチャ)で研究しようと思ったら、これ一冊読むだけでスタート地点まで行けます。

Interconnections

古本が安く出てたので気になって購入。まだ読んでないんだけど、ハードウェアとIPの間を埋めてくれそう。ようするに、ひたすらL2中心の分厚い書籍(笑)。この本でようやく上から下まで繋がる気がします。

詳細TCP/IP (TCP/IP Illustrated, Volume 1: The Protocols)

日本語だと初版しか出てないのかな。SOFTBANK BOOKS版とピアソンの新装版があって、僕は古いSOFTBANK BOOKS版の頃に買って読みました。TCP/IPの基礎がすべて詰まっていて、ソフトの人が必要になるであろう知識としては一番下のレイヤーから書かれてます。たぶん、自作ウェブブラウザーを開発しようと思って買ったんじゃなかったかなぁ? 1997年です・・・。
有名なプロトコルについては簡単に説明が書いてあるのでRFC読むのが面倒な時とか、時々振り返って読んでます。会社の人に2版を進められてるので、そのうち買うかも。現在僕にとって一番勉強しておかないといけないレイヤー。

マスタリングTCP/IP SSL/TLS編

仕事でWebSocketに携わることになって。SPDYとの関係もあったのでSSLの理解は避けて通れない予感がして覚悟を決めて読んだ一冊。すべてを理解したとは言い難いかもしれないけど、だいぶ見通しは良くなったかな。なんだかんだでSSL周りのコードをいじる事もあるんですよね。上記TCP/IP本のセキュリティに関する補遺的な位置づけで読むべき本です。

UNIXネットワークプログラミング第2版 Vol.1 ネットワークAPI: ソケットとXTI

10年以上前に働いてた会社で初版を読みました。当時は会社で唯一のWindowsプログラマだった事もあり、WinSock2の本も読んでましたけど・・・あまり覚えてないなぁ。で、会社を辞めて大学に戻ってから、手元にも一冊ないと不便だなぁ・・・と買ったのが第2版。なので、結構読んでないところもあります。
ソフトウェア屋さんにとっては上の2冊が理論で、この本が実践。やっぱりソフトの方がハードより勉強する事多いのかなぁ。