読者です 読者をやめる 読者になる 読者になる

VS2005からMIDIファイルを出力する方法

はてなで質問した通り、

■■■■■■■■■■■■■■■■■■
プログラム言語で、midiファイルを出力するための方法を教えて下さい。 優先順位: C#>C++>C>VB>Java>その他の言語>prepmxを使う。>バイナリをごりごり書く。

http://gorry.haun.org/spice/

このあたりは利用できないでしょうか。


他にも色々あります。

http://lss.eternity.ne.jp/new/class.php?339

おーぷんMIDIぷろじぇくと

のMIDIDataライブラリ(LGPL)で出力できるようです(*試してません)

概要:

MIDIDataライブラリは、完全にフリーでオープンソースの、MIDIデータ作成・編集用ライブラリである。このライブラリは、MIDIデータの作成・ファイル入出力(SMFフォーマット0/1/2)、MIDIトラックの作成・追加・変更・削除、MIDIイベントの作成・追加・変更・削除など、 MIDIデータのあらゆる要素に迅速にアクセスする機能を提供している。

 MIDIDataライブラリは普通のC言語で書かれているが、ソースのほか、ダイナミックリンクライブラリ(*.dll)の形で提供される。ゆえに、C/C++からはもちろんのこと、Visual BasicDelphiから使用することもできる。最新のMIDIDataライブラリは、2007年現在おーぷんMIDIぷろじぇくとからダウンロードできる。


詳説MIDI規格

も参考になりそうです

[]
■■■■■■■■■■■■■■■■■■



何らかのプログラム言語(特に.net framework)でMIDIを出力するための方法がほしかった。
プログラミングの本はほんとに、演奏はあるのだが、出力はなかったのである。
昔昔林晴比古のVisual C++ 6.0入門 シニア編にのってたなぁ。くらいである。

でも、MIDIを生成したかった。
id:kujirahand
さんの回答ではjavaによる方法。
すぐにできた。javaは正式に採用されているところがうれしいところ。
しかし、このjavadocという人は便利である。

C++C#版のjavadocとかないのであろうか。A Hot Documentは、個人で買うには高すぎる。
Doxygenは設定が面倒。というかC#は正式にサポートしているのか?という不安がある。

で、C#で楽譜画像を読み込んで自動的に楽譜を認識してmidiに出力できたらいいなぁと思っていたので、
J#からやろうとするが、無理。J#はjavax.sound.midi.*;がないのである。

そこで、id:minesouta
さんのを採用することにする。
これはダウンロードしても、普通にVS2005で起動すると、設定ファイルがアップグレードされる。
で、ビルドはすぐに成功して、dllとlibが生成される。
なんだ大勝利ではないか。と思ったが泥沼にはまる。

これは、C#で読み込めないDLLだった。アンマネージコードがどうたら、という理由で、
DLLを参照しようとすると、アセンブリがどうのとか、comコンポーネントとかよくわからない単語が続いて
結局読み込めない。

ので、無理矢理 コンソールアプリケーションから、関数を呼び出す形で強引にする。
でも今度はエラーが130個くらいはいてくれる。
でも、そのほとんどは キャストできないエラーなので、
そこは手動で、キャストをしてあげる。

次のエラーは、min 関数が定義されていない。とか言われる。
これはどこを探してもmin関数が存在しないので、[もしかしたら.libファイルの中かも。]
多分minという名前なのだから、最小値を返せばいいのだと、無理矢理作ってしまえばOK。
こんな感じ。
long __stdcall min(long a, long b) {
if ( a > b ) {
return b;
} else {
return a;
}
}
a==bの時はどうなのだろうか。でもとりあえずこれで動いたのでOKとする。

次のエラーは、サンプルプログラムの

int _tmain(int argc, _TCHAR* argv[])
{
	MIDIData* pMIDIData = MIDIData_Create (MIDIDATA_FORMAT0, 1, MIDIDATA_TPQNBASE, 120); 
	if (pMIDIData == NULL) {
		printf ("MIDIStatusオブジェクトの生成に失敗しました。\n");
		return 0;
	}
	MIDITrack* pMIDITrack = MIDIData_GetFirstTrack (pMIDIData); /* 最初のトラックを取得 */
	MIDITrack_InsertNote (pMIDITrack, 0, 0, 60, 100, 120); /* ドの音(Key=60 Vel=10)を挿入 */
	/


	MIDITrack_InsertEndofTrack (pMIDITrack, 960); /* エンドオブトラックを挿入 */
	MIDIData_Save (pMIDIData, "Test1.mid"); /* ファイルに保存 */

	MIDIData_Save(pMIDIData, "Test1.mid"); /* ファイルに保存 */
		MIDIData_Delete (pMIDIData); /* MIDIデータをメモリ上から削除 */
	pMIDIData = NULL;
	return 0;
}

の、MIDIData_Save(pMIDIData, "Test1.mid");
である。なんとこれが、存在しない。
ソースのどこを探しても存在しない。
これは困りまくって見たが、やはり状況は変わらないので、ソースを読むことにする。
MIDIData_Saveで検索すると、それに近いのが、結構いる。
MIDIData_SaveAsBinaryとか、MIDIData_SaveAsSMFとかいう人。
Binaryでやってみたら、だめだった。
でもMIDIData_SaveAsSMFの場合うまくいったので、

MIDIData_SaveAsSMF(pMIDIData, "Test1.mid");
とすればOK.

最後の関門は、どうやって音を出すの?である。

これは、どう考えてもMIDITrack_InsertNoteしかありえない。
でも、引数が意味不明。なのでここに記述しておく。

MIDITrack_InsertNote (pMIDITrack, 480, 0, 67, 50, 240); /* ソの音(Key=67 Vel=10)を挿入*/
	/**つまり、 MIDITrack_InsertNote( pMIDITrack, 始まりの場所, MIDIチャネル, 音の高さ, ベロシティ, 音の長さ)ということか.*

ちなみに、始まりの場所とかのタイムラインは,四分音符一個分の長さが120である。、従って4/4の場合一小節で、480である。
今日はここまで。

このままでは無理なので、これを.net Frame Work上のC++からクラスライブラリを作成してから、
C#で読み込ませれば勝利できそう。
回答して下さった皆様ありがとうございました。
本当に感謝しております。