他人の空似自作物置場

midiを読み込んだり書きだしたりCPU上で再生したり、習作なので何かに役立つことはないでしょう。

プログラム名:midi

用途:なし(midiに関する習作)

使い方:
midiファイルをドラッグ&ドロップで読み込んでからファイル名に.midを足したmidiに再出力し
フォーマット形式が0だった場合のみ再生します。

ファイル解説:
midi.exe		プログラム本体
midi.c			プログラムのソース、midiに関する処理をしたい人は参考にどうぞ
midiplay.exe		midi.exeから書き出し機能を外した物
Readme.txt		今読んでいるこれ

免責事項:
これに同梱されたプログラムその他が原因で発生したいかなる損害も当方は一切関知しません
自己責任でお使いください。

Q&A:
	Q:用途無しとあるけど、これは何用のプログラム?
	A:midiに関わる必要が出てきたプログラマーに対する参考資料です、それ以上でもそれ以下でもありません。

	Q:再生できないmidiがあるんだけど
	A:フォーマット0のmidiのみ対応しています、それ以外を再生するにはさらに手間隙をかける必要があります。

	Q:読み込んでから同じファイル書き出しって意味あるの?
	A:処理内容自体に意味はありません。
	内部的にはきっちりmidiファイルの解釈をし構造体にばらしてから、それを元に再出力していますので
	元ファイルと同一であるなら少なくともそのmidiに対しては付属のコードの読み書き処理で問題がないということがわかります。

	Q:出力されたmidiがおかしい
	A:いくつか既知のバグが修正されていません、それらに引っかかった恐れがあります。

	Q:これだけはしちゃいけないって禁止事項は?
	A:x86以外のPCでコンパイルしなおした場合は絶対に動きません、絶対にやらないでください。
	理由:intは4バイト、shortは2バイト、charは1バイトだと決め付けたコーディングがされているため。

	Q:ソースだけ読んでもわからねーよ!
	A:中の人がコードを書く際に参考にした各種ページの方へどうぞ
	http://eternalwindows.jp/sound/midi/midi00.html
	http://www2s.biglobe.ne.jp/~yyagi/material/smfspec.html
	http://www.pluto.dti.ne.jp/~daiki/Midi/AboutSMF_Inside.html

	Q:自己満?
	A:ですね

	Q:なんでこんなコードなんて書く気になったの?
	A:某動画サイトでmidiの楽譜が弾幕に見えた、ならいっそmidiから弾幕を作ってやれと思った、今は公開(誤字にあらず)している。

	Q:midiはおろか音楽の知識が欠片もないんだけど、midi使うなんて無謀?
	A:中の人もありませんでしたがこれぐらいならできました、これ以上を狙うなら若干厳しいかもしれません。


作者:sweetie
著作権など:
めんどうなので全放棄、再配布でも何でもお好きにどうぞ


技術情報(という名のどうでもいい話):
既知のバグ三種
	midiイベント以外のイベント直後データが破損していてもランニングステータスと誤認識して読み込んでしまう可能性があるバグ
	SysExイベントのデータ長が127バイト以上であったときに正常に読み書きできないバグ
	midiヘッダの時間単位が実時間指定であった場合に正常に読み書き再生できないバグ

フォーマット1を再生するには一度デルタタイムを相対から絶対に計算しなおし、それを元にフォーマット0形式に直す必要がある。
フォーマット2は単純に順繰りに再生してやるだけでよい、その合間にresetをかける必要があるかは不明。

このコードはいわゆるバッファ形式で再生しています、プログラムが止まれば演奏もとまり、CPUやメモリー使用率によって遅延することもあります。
黒窓の横についているスクロールバーをドラッグしてみれば一目瞭然(一聞瞭然?)です
これを避けたいならばストリーム方式にて書き直してください。

MidiPlayの時間管理は大分いい加減です、小数点以下の処理や処理中に経過した時間を含めていません。
なので実際の時間よりもずれることはよくあります。

MidiPlayの第二引数を弄れば途中再生もできます、MidiPlay内部のwhileのコメントアウトを外せば(無限)ループ再生もできます。

デバイスを選べるので、デフォルトデバイスでしか再生できないプレイヤーよりは使えるかもしれません。

midiはデバイスがかぶると再生できないなどの問題があります。
なので既にmidiプレイヤーが立ち上がっている環境では正常に動作しないことがあります。

コンパイル環境はコマンドライン版VC++14.00.50727.762、CodeGear付属のBCC32で動作することを確認しています。

        
2016/05/18 ver2.01
音量調整がmidiデバイス任せだったのをアプリ別音量を使用するように変更

2016/05/17 ver2.00
内部コードを大幅リファクタ
大量にあったメモリーリークを修正
再生時間表示を正確に表示するようにした
ループ再生、再生デバイス指定、再生速度指定などの機能を追加
F7キーで再生の一時停止ができるように
timidityなどSIGINTを握りつぶすドライバー対策を追加
その他些末な修正をいろいろ

2009/02/09 ver1.00
再生時時間管理の制度を向上

2008/09/26 ver0.04
MidiPlayを新設、それに伴ってmainにデバイス関連処理を追加
atoi2新設
loadtrackの再生時間計測でセットテンポに対応
loadtrackのデータ受け渡し方法を変更
TRACK構造体に再生時間を追加
err関数の出力内容を変更

2008/09/25 ver0.03
エラーするまま放置されていたplaytrackを撤去
上記に伴って不要な構造体の削除
loadtrackのランニングステータスが正常に動作していなかったバグ修正
loadtrackでメタイベントの処理が正常に行われていなかったバグ修正
loadtrackでエンドオブトラックがない場合に正常に読み込めていなかった不具合の修正
loadtrackでデルタタイムを正常に計算できていなかった不具合の修正
loadmidi内でなぜかMTrkのlenを4倍していた不具合を修正
loadtrackの処理順を整理、不要なローカル変数の撤去
loadmidiのエラー処理を若干変更
print_dev_infoの出力形式を若干変更
errとmainにおいてgetchar()関数でストップをかけるように変更
カレントディレクトリをexeが置かれているフォルダになるよう変更、それに伴いSetAppDir新設
revのループ条件を変更、不要な変数撤去
savemidi、track2binを新設

2008/02/12 ver0.02
playtrack新設

2008/02/11 ver0.01
loadtrack、print_dev_info新設
上に伴ってloadmidiとmainに若干の修正と追加

2008/02/1 ver0.00
各種構造体を定義
main、loadmidi、err、revを新設