February 2010 Archives

lemurがほしい

| No Comments | No TrackBacks

JazzMutant LemurというマルチタッチのOSCサウンドコントローラがある。パラメータをタッチインターフェースで入力して送信できる。こんな便利なものがあったら、市販されているMIDIコントローラの類はこれでほとんど汎用的に実現できてしまいそうだ。

しかしこのLemur、25万円もする。まともなノートPCが5万ちょいで買えるこの時代に、さすがに気軽に出せる価格ではない。そんなわけで、タッチパネルを使ったハックなどもいろいろ模索したのだけど(reactivisionみたいなやつ)、一方さすがにそこまで深入りしようとまでは思わなかった。

今年の春あたりから、その辺の状況が変わってくる。Windows 7のマルチタッチUIがSilverlightでサポートされるようになる。iPadが発売されたら、iPhoneのちっこい画面では実現できなかった大画面でのタッチUIが実現する。Lemurみたいな製品は、ソフトウェアだけ書けば実現できる時代になるというわけだ。実際、iPadでも、Windows7+Silverlightでも、Lemurみたいなのがほしいという声はネット上で散見される。

そんなわけで、ちょっとそれっぽいものを作ってみようかなあなどと思っている。本当はAndroidのようなオープンな端末で開発したいと思うのだけど、とりあえずiPhone SDKでプロトタイプのようなものを作ってみようかと思っている。「それならbeagleboard+タッチパネルでhackしましょう」みたいな話もされたのだけど、さすがに茨の道すぎてハードウェアに資金投入する気が起きない。

まあ、Lemurがどんなものなのか、Lemurにどんな機能があるのか、全然知らないのだけど。

ほしいといっても、それは今のところおもちゃにしかなる予定が無い。真剣な打ち込みをやろうと思ったら、OSCの入力を、処理可能な命令群として保持しておきたいのであって、ライブレコーディングのようなことをやりたいわけではない。(この辺の意識は、操作を記録するというGoogle Waveへの関心とかぶってくるところがあるのだけど、その辺は特別に考えがまとまっているわけではないので今日はこの辺にしておこうと思う。)

android hacking 5日目 (ende)

| No Comments | No TrackBacks

4日目のMidiPlayerは、パフォーマンスや同期性に問題はあるものの、それなりにすんなり動かすことができ、他の部分をいろいろやっつけることで、とりあえず鍵盤をちらちらと演奏表示できるMIDIプレイヤのプロトタイプのようなものは出来た。何とか1週間でできた。コードはgithubに置いた

ファイル操作は外部アプリケーション(OI File Manager)をインストールしてIntentを使って通信することで実現した。これが微妙にハマりどころで、結果がonActivityResult()で返ってくるよりも、startActivityForResult()のダイアログ呼び出しの次のコード行が先に実行されたりする(要するに別スレッドで行われている)。バグなのかもしれないが、これでは別ウィンドウを開いて手動でスレッド同期するのと同様の煩雑な手順が必要になる。

ちなみに、Intentで必要になる外部コンポーネントについて、他人にインストールさせる手段はあるようなのだけど、まだ分かっていない。

スレッドモデルがCLIとJavaでは大分違って、特にCLIでいうWaitHandleの通知まわりは、状態のチェックが厳格で(たとえばThread.wait()していないところにThread.notify()することができない)、いろいろ移植での問題が発見された。今でも演奏のための最低限の部分は何とか動いてはいるものの、一時停止や停止が動かないなど、不安定な部分が少なからず残っているようだ。さすがにMidiPlayerを安定的に動くようにさせるには至らなかった。

あと、MidiPlayerでイベントごとに描画をコールバックするようにしたら、さすがに描画が追いつかなくなってきたようだ。というより、800x480の画面では遅延だらけで話にならない。アプリケーションの遅延の原因が描画にあると気付いたのは、HT03Aなど古い端末でも動かせるようにしようと思ってのことだったのだけど、そのやっつけ作業が終わって動かしてみたらほとんど遅延が無いことに気付いたのだった。

現在は、SurfaceViewのプロトタイプサンプルにあった、別スレッドで描画の更新を行うモデルをそのまま残してあって、その中で画面全体をCanvas.drawBitmap()で更新するのだけど、必要な部分だけ毎回lockCanvas()して更新した方が良いのかもしれない。各種の最適化方法を試した方が良さそうだ。

現在は、JetPlayerによるMIDIの再生とMidiPlayerによる画面の更新という、2つの演奏ドライバが併走している状態なのだけど、描画の遅延はここで非同期の問題をもたらしている。とはいえ、本来はMidiPlayerが遅延を吸収できるべきところだ。現在は遅延を一切考慮せずひたすらThread.sleep()しているので(これはC#版からそうだ)、定期的に現在時刻からの差分を吸収するように直す必要がある。

これとは別に、SmfReaderにもパフォーマンス上の問題があって、これは純粋に自分のライブラリの問題なのだけど、これは別途プロファイルしてみないと分からない。C#からJavaに移植する過程で、さまざまなbyte->short変換を追加せざるを得なかったのだけど、それが問題になっている部分もあるかもしれない。まあもともと処理効率の良いライブラリだったわけでもないが...

アプリケーションのパッケージングなどは、全てeclipse上で行っていたので、その下回りで何が行われているかはよく分かっていない。Android開発そのものに大きな興味があるわけではないので、その辺を見てみようという気は今のところ無い。

ところで、Intentを使ってアプリケーション間通信を行えるというところで気付いたのだけど、エディタ上でMMLを記述して、それをandroidmono経由でmugeneを呼び出してSMFに変換するようなことが出来るのではないかと思った。UI方面は実質的にまだバインディングが存在しないので、C#で全体を書き直すのは現時点では無理だと思うが、そういういじり方でJavaコードを減らしていくのは、悪くないアプローチかもしれない。ちなみに、Javaコードは書きたくなかったものの、Jythonなどを使うとSMFライブラリのパフォーマンスに問題が生じそうだったので、今回は回避した。

とりあえず今日で一連のandroid hackingネタは終わり。

android hacking 4日目

| No Comments | No TrackBacks

昨日は長い1日だった...他にも雑事があったので、コードを書いた時間が長大だったわけではないけど。

4日目にして初めて気付いた事実がある。JetPlayerがOnJetEventListener.onJeyEvent()に乗せて送信するイベントはcommon controlだけだった(!) ノートオンやノートオフが一切送信されてこない。そもそも引数の数が足りない(ということで気付いた)。これではこのプロジェクトそのものが実現不可能だ。

普段ならこれで諦めているところだけど、昨日はどうやら妙なスイッチが入っていたらしく、それならばもうJetPlayerの制限を超える独自のMIDIプレーヤを作ってしまえ、と考えたのだった。portmidi-sharpで作ったMidiPlayerを移植すれば難しくないだろうと。

そこで早速移植作業を開始したのだけど、ほどなくSMFライブラリも移植しないといけないことに気付いた。そしてこれがハマりどころだった。SMFライブラリの移植はけっこう大変だった。C#のunsignedなbyteを前提に書かれたコードは、Javaに持って行くにあたって全面的に修正を余儀なくされた。

昨日の作業のほとんどはこれに持って行かれたのだけど、ファイルを食わせて解析中にエラーが出ることはない、というところまでは持って行けた。これが動作するかどうかは分からない。あとMidiPlayer自体も、CLIのスレッドのAPIとは全然違うJavaのスレッドAPIに書き換えた部分がちゃんとうまく動くかどうかも全く分からない。

昨日といい今日といい、そこそこ再利用性のあるコードを書いているような気がする。内容はぐちゃぐちゃだけど。

とりあえず、それまでは/sdcardにコピーしてあったjetファイルを直接読み込んでいたのを、midファイルを3日目のsmf2jetでdalvik上で変換して読み込ませるようにした。ファイル操作のAPIも分からなくていろいろハマったのだけど、とりあえずgetContext()してごにょごにょやる方法があることを把握した。これでSMFを渡すだけで再生できるようになった。

あとはMidiPlayerがうまく動いて、イベントディスパッチがうまくいって、描画が出来て、ファイルが選択できるようになれば(今は固定のファイルを読んでいる)、proof of conceptとしては十分だろうか。今日中にうまくできると良いのだけど...

android hacking 3日目

| No Comments | No TrackBacks

MIDIプレイヤを作る以上、JetPlayerが前提にしているような「JetCreatorで.midを.jetに変換する」というモデルは採用できない。SMFをそのまま再生できるようにしなければならない。

JetCreatorはPythonアプリだし、wxPythonまで使っている。Pythonクラスなら、サーバサイドに持っていって変換サービスを呼び出す形にもできるのではないかと考えたが、JetCreatorで使われている各種PythonクラスのAPIは公開されていない。読んですぐ使えるようだったらその辺は気にせず使おうかとも考えたが、ソースがごちゃごちゃしていたのでやめた。

というわけで、次に.jetファイルのフォーマットを(バイナリエディタで)眺めて、単純な.jetファイルならコードで作れそうだと判断して、javaでコンバータを書いてみた。基本的に、1つだけのセグメントをもつ.jetファイルというかたちで、単純なヘッダ部分を付け加えただけのものだ。

これを今度はファイルシステムから読み込んで再生できるようにしなければならない...というところで昨日はさらにあれこれ試行錯誤していたのだけど、結局再生までテストできたのは今日になってからだった。web上にはJetPlayerはエミュレータ上では再生までしてくれないみたいなことが書かれているのも見かけたのだけど、ちゃんと再生してくれた。

ちなみに、エミュレータにも入っている音楽プレイヤーは、どうやらSMFの再生もサポートしているようだ。再生してみたら、JetPlayerと同じように再生した。MediaPlayerのAPIで再生できるということかもしれないが、標準でそこまで出来るのならMIDIデバイスに命令を直接送信するAPIも用意してもらいたいところだ...

android hacking 2日目

| No Comments | No TrackBacks

昨日も時間があったのでandroidをいじってみた。やはりJavaは面倒くさい。というより、リソースファイルとか多すぎて面倒だ。1週間でそれっぽいアプリが作れるかどうか、だんだん希望が見えなくなってきた。

昨日はAndroidに詳しい知人もいたので、いろいろ聞きながら作業をすすめていた。2日目はそれほどコードが増えたことは無かったのだけど、分かったこともそれなりにある。

  • 初日の時点ではSurfaceViewのUIが点滅していて、原因が分からなかったのだけど、どうやらSurfaceView.getHolder().lockCanvas() で返ってくるCanvasがひとつではないようだ。androidのlockCanvasは、単なる描画ロックというより、ダブルバッファリングを用いた実装になっていると説明されているのだけど(あくまで現在の実装の話)、具体的には、onSurfaceCreated()のコールバック時にlockCanvas()で返されるCanvasと、アプリケーションが開始されてから(独自スレッド内で呼び出された時に)返されるCanvasとでは、インスタンスが違っているようだ。新しいCanvasにも画面全体を描画するようにしたら解決した。
  • android端末の画面はずいぶん小さいなと思っていたら、avdを作成する時にカスタマイズすることができた。NexusOneは800x480とかあるらしいけど、十分すぎる。HT03Aなど古い端末では見えなくなりそうなので、多少は対応しようとも思うけど、そもそも大量のJetPlayerから飛んでくる大量のMIDIメッセージ(になるはず)を処理できるかどうか、かなり疑わしい。
  • androidにはファイルシステムが存在するのに、標準的なファイルダイアログが存在しない(!)。どうやっているかというと、ファイル選択用のアプリケーションとIntentというものを使ってアプリケーション間通信のようにして行ったりするらしい。ファイル選択を実装しているopen-data-kitというプロジェクトを発見したので、このソースを再利用しようかとも思ったのだけど、単なる.javaソースの移動だけでは足りず、プロジェクトファイル全体の構成がややこしいことになりそうなので躊躇している。Intentを使うやっつけで対応した方が、とりあえずは良いのかもしれない。
  • JetPlayerではmidiファイルをそのまま再生することができない。JetCreatorなどのツールを使うことになるのだけど、これがwxPythonで書かれたGUIツールで、android上で呼び出せるAPIのようなかたちにはなっていない。これでは困る。
  • alsa-rawmidiはandroidに含まれているようだけど、どうやら標準のNDKにはヘッダファイルもライブラリも含まれていないようだ。ヘッダファイルはalsaのソースから拾ってくればいいし、ライブラリは実機から吸い出してしまえば良いのではないか...というのが友人の弁だった(!)

というわけで、まずJetPlayerで再生できるファイルをどうにかして作れるようにする必要がある。それが出来たら、今度はそれをプレイヤの画面でファイル選択ができるようにしなければならない。どちらもmidiプレイヤを作るための本来のタスクではないような気がしてきた。

あと、TouchDownは取得できるのにTouchUpが取得できないという(たぶん初歩的な)問題にぶつかって、早送りが実現できるようになったら困る予定だ(JetPlayerではテンポが変更できないので、早送りが実現できる予定は今のところ無い)。

いろいろ壁もあるけど、楽しい部分は楽しい気がしてきた。

android hacking 1日目

| No Comments | No TrackBacks

先日はsdkをインストールしてドキュメントをちらほらと眺めて見た程度だったけど、昨日は初めてandroid SDKを実際に使って遊んでみた。ちょうど1年くらい前にもmacbookを買ってきてiPhoneアプリを作って遊んでみたりなどしていたのを思い出す。今回はさすがに1日でアプリが動くというところには至らなかった。

今試しにやろうと思っているのは、mldspの移植みたいなことだ。コードはJavaとandroid APIで書き直すことになるが、それなりに再利用は出来るのではないかと思っている。とりあえず再利用していろいろ書き換えたらこんな画面を出すところまではできた。コレは、高速描画できるようにと思って、SurfaceViewを使って、そのCanvasを拾っている。スレッドは独自に立ててあって、その中でMIDIメッセージに応じて描画を行うようにするつもりでいる。

今のところ単純なサンプルのモデルを援用しているのだけど、ちょっとパフォーマンス的に不安が大きい。たとえばCanvasのロックに関しては、独立スレッドが本当にベストソリューションなのか、怪しいと思っている。メインスレッドで行えばロックフリーでCanvasを操作できるようだし。

androidいじりは、実のところ1週間くらいちょろっとやって終わりにするつもりだったのだけど、何やら仕事の方面でもきな臭い動きがあって、思ったより長い付き合いになってしまうかもしれない。

ちなみにこれは昨日やったことを今日になってまとめている。今日はどうやらコードをいじる時間が無さそうだ。

androidを初めて眺めて見るの巻

| No Comments | No TrackBacks

今日はとあるwaveの勉強会とやらに参加してみたのだけど、waveそのものについては他の人たちも概ね同じくらいの理解度で、それほど勉強できたという感じではなかった(本当は実装するつもりで行ったのだけど、自ら無駄話をしていてそれどころでもなかった)。

その代わり(?)、妙にandroidをいじっている面子が多かったので、多少androidまわりの話を聞いてきた。オーディオ周りはalsaが動いていると聞いたので、もしかしたらNDKでfluidsynthが使えるのではないかと期待しているのだけど、donutやらeclairやらではビルドできなかったようなので、まだ先の話かとも思う。ちなみにビルドにはrawmidiも含まれていそうだ。

alsamidiが使えるならportmidiも多分ビルドできて、androidmonoを使えばportmidi-sharpも使えそうな気がする。まあUIをどうしようもないのでやらないけど。

で、むしろJetPlayerというものを使えばいいのではないかと教えてもらったので、そのAPIを眺めて見たのだけど、どちらかというとアリモノの音楽プレイヤという感じだ。それなりにいいところまでは作り込まれているが、これでは例えば早送りやスロー再生が出来ないし、MIDIメッセージを直接デバイスに送信してパラメータを調整することもできない。これでは単なる再生環境にしかならない。まあそれでもmldspの機能縮小版程度のことは出来るだろうと思うので、来週辺りちまちまといじってみようかと思っている。

ちなみにソースを書いてみるようなつもりでJavaをいじったのも、1.4系列以来で、すっかり浦島太郎状態だ。読むことはこれまでも多少はあったので、アノテーションやらジェネリクスやらが存在することは知っているのだけど。eclipseもたいへんひさしぶりだったので、昔遊んだおもちゃを振り返るような気持ちでいじってみた。androidをいじるのであれば、eclipseが無いと、XCodeなしでiPhoneアプリを書くのと同じくらい面倒そうだ。

About this Archive

This page is an archive of entries from February 2010 listed from newest to oldest.

January 2010 is the previous archive.

March 2010 is the next archive.

Find recent content on the main index or look in the archives to find all content.

Categories

Pages

OpenID accepted here Learn more about OpenID
Powered by Movable Type 4.23-en