mciSendStringによるMIDIファイルの演奏

Windows では、音楽やビデオなどさまざまな「マルチメディア」(死語?)機能を利用する事ができます。特に、MCI(Media Control Interface)は、メディアプレイヤーと同じような感覚で簡単なコマンドを使ってMIDIやCD、ビデオを再生できるので、プログラムにちょっとした音楽やビデオを入れるのに適しているでしょう。
今回は、このMCIを利用してMIDIファイルを演奏してみます。

MCIによるファイル再生

MIDIファイル(拡張子mid)とは、一言で言うと音楽の「楽譜」と楽器構成や演奏の仕方などの情報を、そのままファイルにしたものです。

オクターブ4のA(ラ)の音を4分音符一つ分ピアノの音で、とかテンポは100、ボリュームはどれだけという感じで情報が記録されています。インターネットなどでも多数のファイルが公開されていますから、すでに多数のファイルを集めてBGMとして利用している方も多いでしょう。

この形式のファイルは音符のアイコンで表示され、ダブルクリックすると「メディアプレイヤー」が起動し自動的に演奏されます。この「メディアプレイヤー」と同等の機能は、MCIを使うと簡単に利用する事ができます。

メディアプレイヤーの「再生」や「ポーズ」や「巻き戻し」などの機能も、プログラムの中でMCIのコマンドを使うと同様の事ができるのです。しかも、コマンドはopenplayといったわかりやすいコマンドとパラメータの文字列なので、単にファイルを再生するだけならそれほど戸惑う事もありません。

とりあえず、MIDIファイルを扱うにはopenplayseekstopclose の各コマンドを扱えるようになれば十分でしょう。

いずれも機能は名前からすぐに想像できますね。MCIでファイルを再生する時は、まずopenでファイルとデバイスの種類を指定してデバイスを初期化してからplayで再生し、stop で終了してcloseでデバイスを閉じる、という流れになります。

その一連のコマンドを送るのがmciSendString関数です。

MCIERROR mciSendString( LPCTSTR lpszCommand, 
LPTSTR lpszReturnString, 
UINT cchReturn, 
HANDLE hwndCallback 
); 

各引数の意味は、lpszCommand がコマンドの文字列、lpszReturnStringcchReturn には、何か情報を返すコマンド(status など)を指定した時に返される情報を収める文字列とその長さを入れます。

また最後の引数は、コマンドが終了するとメッセージを送るように指定する(NOTIFYフラグ)時に、メッセージを受け取るウインドウのハンドルを指定します。ただし、今回は情報を受け取るようなコマンドは使わないので、lpszReturnString にはNULLcchReturn には0を入れておきました。

このmciSendStringからは、エラーや正常終了などの結果が数値で帰ってきますが、その数値をmciGetErrorStringに渡すとその結果を文字列(しかも日本語!)で得る事ができます。

・コマンドの使い方

まず、ファイルを開くにはopenコマンドに開くファイル名とデバイスの種類(MIDIやCD、ビデオなど)を指定します。ただし、ファイルの場合はファイル名(拡張子)で自動的に判別されるため、MIDIを演奏する場合はデバイスの種類を指定する必要はありません。
また、デバイスにはalias で名前をつける事ができ、名前をつけておくと以後この名前でデバイスを操作できるので便利でしょう。

・openの例

mciSendString("open test.mid alias music",NULL,0,NULL);

上の例では、デバイスにtest.mid を読み込んで、以降music というデバイス名で操作できるようになります。そして、このtest.mid (デバイス名music)を再生するには、

mciSendString("play music",NULL,0,NULL)

このように"play music" というコマンドを送るだけです。この時、

mciSendString("play music NOTIFY",NULL,0,hwnd)

のようにNOTIFY フラグを指定してやると、再生が終わった時にhwnd ウインドウにMM_MCINOTIFYメッセージが送られて来ます。メッセージを処理する時にまたmciSendStringでplayコマンドを送ると、連続再生が可能になるわけですね。

また、MIDIの場合はopen しないでもファイル名を指定してplayするだけで再生できますが、その場合はNOTIFYを指定できないみたいですね。

最後に演奏を中止するには、

mciSendString("stop music",NULL,0,NULL);
mciSendString("close music",NULL,0,NULL);

としてデバイスを閉じます。

デバイスを開いている間は、他のプログラムなどからそのデバイスを利用できなくなるので、デバイスを使い終わったら必ずclose してください。

・プログラム

今回のプログラムは、選択またはドラッグ&ドロップされたMIDIファイルを連続再生します。連続再生するためには、MM_MCINOTIFYメッセージの処理を以下のようにすればよいですね。

case MM_MCINOTIFY: // 演奏終了時の処理

	if (!play)
		return 0;

	// 最初に巻き戻して再度演奏開始
	mciSendString("seek music to start",NULL,0,hwnd);
	mciSendString("play music NOTIFY",NULL,0,hwnd);

	return 0;

なお、MCIを使うためにはmmsystem.hをインクルードしてwinmm.libをライブラリに加える必要があるので注意してください。

winmm.libの追加は、VC++メニューの「プロジェクト」−「設定」で出てくるダイアログの「リンク」を選び、「オブジェクト/ライブラリモジュール」にwinmm.libを追加します。

プログラムソース表示


プログラミング資料庫 > Windowsプログラミング研究室