2011-07-30 12 views
1

私はMIDIファイルリーダーをJavaで作成しています(主に、Androidプロジェクトではjavax.sound.midiライブラリが含まれていないため、練習問題として使用しています)。私はthis仕様に従っています。未知のMIDIイベントのデコード

実際の読書はイベントごとに進んでいますが、私のプロジェクトでは仕様の詳細がうまく実装されています。 InputStreamがファイル上で開かれ、同じオブジェクトが渡され、イベントが解析されたときにストリームが次のイベントに配置されるように、さまざまなイベントオブジェクトを解析します。これはすごくうまくいきます。

私の最初のテストファイルは、単にソナー8で作成された空のデータトラックを持つテンポマップです。テンポトラックは完全に解析されています。空のトラックは、そのチャンクの識別子とトラック名の後に次のデータがあります。

00 B0 07 47 00 0A 40 00 FF 2F 00

最初のバイトが正常に解析されています。 00 = 0のデルタ時間は、チャネル0上B0 =コントローラーイベント、07 =メインボリューム制御、71

47 =ボリューム値の次のバイトは私を混乱されています。 00 0A 40最も可能性の高いケースは、値が64のPanイベントです。0Aは、ボリュームイベントと同様に、コントローライベントの前には、B0と予想されます。しかし、既知のイベント識別子バイトの前にはないので、読者はこのイベントを解析できません。

私の疑問は、このタイプのイベントをどのように説明できるかということですね。このような文字列のコントローライベントを単一のB0識別子でファイル形式で受け入れることは可能ですか?さらに、ファイル内で識別できないイベントタイプが発生した場合、実際にイベントがどのようなものになるのか分からないと、どのくらいのデータをスキップできるかを知る方法がありますか?私は未知の出来事を飛ばして読者が失敗しないようにしたいと思っていますが、私がその出来事を特定できないと、私はそれをスキップする方法がわかりません。これらの特定の事例についてのいくつかの洞察が大好きです。

+0

私は、空でないデータトラック(実際の音符のトラック)を見て、いくつかの洞察を得ました。私がノートオンイベント(0x9)の束を期待している間、私は1つのノートオンイベントの後にトラックのすべてのノートが続きます。また、ノートオフイベントがなく、ノートが終了するベロシティ0のノートオンイベントもあります。だから私は、イベント識別子が次のイベントを特定するだけでなく、別のイベント識別子が見つかるまで、そのタイプのイベントとしてイベント識別子に続くすべてのバイトを識別すると信じるようになりました。私はまだこれについての確認またはさらなる説明を感謝します。 – LeffelMania

+0

[midiファイルの解析、認識できないイベントの種類]の複製があります(http://stackoverflow.com/questions/7719366/midi-file-parsing-unrecognised-event-type) – Arhad

答えて

3

これは、実行状態と呼ばれます。これはMIDI仕様の一部です。あなたがやっていることはまさに正しいことです。申し訳ありませんが、MIDIデータストリームをリバースエンジニアリングすることでそれを把握しなければなりませんでした。Here is a longer explanation of running status.

また、ベロシティ0のノートオンイベントはノートオフです。実際のノート・オフ・イベントには関連するベロシティがありますが、ノート・オフ・ベロシティを実装しているデバイスはほとんどありませんので、Note Onをゼロ・ベロシティで見るのがより一般的です。

+0

これははるかに洗練された仕様です。 。多くのありがとうございます。 – LeffelMania

+0

大歓迎です。私はMIDIの夜明けに多くのMIDI関連のプログラミングをやりました。 – SSteve

0

誰かが同様の問題を抱えている場合に私は自分の質問に答えます。 (しかしそうかもしれない)

私の上記のコメントは保持されているようだ。最初に識別されたイベントを読み取った後、後続のイベントにイベント識別子がない場合、それは前のイベントと同じタイプのイベントとして扱うことができます。だから私の例では

00 B0 07 47 00 0A 40 00 FF 2F 00

は唯一のイベント識別子が存在するにもかかわらず、二つの連続コントローライベントとして解釈することができます。したがって、これは実際にボリュームイベント07とそれに続くPanイベント0Aであり、トラックの終了イベントFF 2F 00に続いて行われます。

私のコードの解決策は、最後に見られた識別子を覚えておくことです。ストリームの次のバイトが有効な識別子でない場合、次のバイトのバイトは前のイベントと同じタイプのイベントとして解釈されます。意味を成していると思われ、もっと重要なのは、読者が正常に完了したことです。