◆音楽再生 その1

[ ホーム ] [ 上へ ] [ 音楽再生 その2 ]

・音楽再生の方法

Audio、Visualなどのマルチメディア関係はあんまり興味もないですし、 もちろん詳しくもないですが、音楽の再生くらいはできるようにしたかったので、 ちょっと調べたら真っ先にPlaySoundというAPIがあることを知りました。 使い方も割と簡単です。ところがWAVE形式しかサポートしてないんですね。 買ってきたCDで気に入ったものはPCに溜め込んでいますが、WAVE形式では保存してないです。 全部MP3形式です。ファイルサイズのことを考えたらほとんどの方がそうだと思います。 曲の再生ということだけ考えたらこれはほとんど使えないです。

それでもうちょっと調べたらMCI系のAPIがあることが分かったのですが、 WAVEやMP3などいろいろな形式に対応している代わりに使い方が少なくとも私にとっては とっても難しかったです。しかも、MSDNではこのAPIに使う構造体のドキュメントも 英語しか見当たらなくてさらに凹みました。
(MSDNで日本語の解説があれば教えてください)

MCI系APIで音楽を再生するのはmciSendCommandmciSendStringの2つのAPIがあります。 前者は音楽の再生や停止などの命令をする場合、必要なパラメータを構造体などに設定して、 Mmsystem.hで定義されている定数を指定して引数に与えることで実行します。
後者は 前者の定数や構造体の設定部分を文字列に置き換えて引数に渡すのですが、命令を 文字列を生成することで実行するので野暮ったく感じます。ということで以後は mciSendCommandでの音楽再生方法を書いていきます。

・mciSendCommandの使い方

このAPIの定義はMmsystem.hで次のようになっています。

WINMMAPI MCIERROR WINAPI mciSendCommandA( IN MCIDEVICEID mciId,
                                          IN UINT uMsg,
                                          IN DWORD_PTR dwParam1,
                                          IN DWORD_PTR dwParam2);

<第二引数 uMSG>

音楽を再生するにはファイル(デバイス)をOpen、再生(Play)して、途中で一時停止(Pause)、 一時停止解除(Resume)や停止(Stop)の場合があり、最後にファイルを閉じる(Close)ことになります。 これらの命令はmciSendCommandの第二引数で指定します。

<第四引数 dwParam2>

第二引数で指定したコマンドを実行する際にパラメータが 必要になることがあるのですが、これは構造体へのポインタとして第四引数に指定します。
例えば最初に第二引数でMCI_OPENを指定して音楽ファイルの初期化を行いますが、 どの音楽ファイルを初期化するかは、MCI_OPEN_PARMS構造体のlstrElementNameメンバに ファイル名を指定してOpenします。(下表参照)

<第三引数 dwParam1>

第二引数に指定するコマンドの追加のフラグです。
例えばMCI_PLAYを第二引数に指定する場合、第四引数にはMCI_PLAY_PARMS構造体を 指定しますが、この構造体のdwFromメンバとdwToメンバに値を設定してmciSendCommand を実行すると2つの値の区間を演奏します。ところが、dwFromとdwToメンバに値を設定した だけでは効果がないです。この2つのメンバが設定されているよということをmciSendCommand に知らせなければなりませんが、そこでこの引数にMCI_FROMとMCI_TOを論理和で設定 してやることで構造体にdwFromとdwToメンバが設定されているよということを教えています。

以下が第二引数に指定できる主な定数、 対応する第四引数の構造体名、第三引数に設定できる主なフラグの一部と構造体のメンバの一覧です。

主な第二引数 第四引数 主な第三引数の定数 第四引数の構造体のメンバ
MCI_OPEN MCI_OPEN_PARMS MCI_OPEN_TYPE DWORD_PTR dwCallback A
MCIDEVICEID wDeviceID B
MCI_OPEN_TYPE_ID
LPCSTR lpstrDeviceType C
LPCSTR lpstrElementName D
MCI_OPEN_ELEMENT
LPCSTR lpstrAlias E
MCI_PLAY MCI_PLAY_PARMS MCI_FROM DWORD_PTR dwCallback A
DWORD dwFrom F
MCI_TO
DWORD dwTo G
MCI_PAUSE MCI_GENERIC_PARMS   DWORD_PTR dwCallback A
MCI_RESUME MCI_GENERIC_PARMS   同上 A
MCI_STOP MCI_GENERIC_PARMS   同上 A
MCI_SEEK MCI_SEEK_PARMS MCI_SEEK_TO_END DWORD dwCallback A
MCI_SEEK_TO_START
DWORD dwTo G
MCI_TO
MCI_SET MCI_SET_PARMS MCI_SET_TIME_FORMAT DWORD_PTR dwCallback A
DWORD dwTimeFormat H
DWORD dwAudio I
MCI_STATUS MCI_STATUS_PARMS MCI_STATUS_ITEM DWORD_PTR dwCallback A
DWORD dwReturn J
MCI_TRACK DWORD dwItem K
DWORD dwTrack L

<第一引数 wDeviceID>

演奏(Play)などのコマンドを実行する対象のデバイスIDです。 これはMCI_OPENmciSendCommandを実行すると MCI_OPEN_PARMS.wDeviceIDに返ってくる値を以降の操作で指定します。

<各構造体メンバ>

  1. 上記の第四引数に指定できる構造体のすべてにこのメンバがあります。ここにはウィンドウのハンドル を指定します。
    上表の第三引数には記載してないですが、すべての場合で第三引数にMCI_NOTIFYという値を設定 できます。この値を設定してmciSendCommandを実行すると、実行結果がMM_MCINOTIFYメッセージ として各構造体のdwCallbackメンバに指定したウィンドウに送られるので、dwCallbackのウィンドウで コールバック関数を用意することができます。
    例えば、第二引数でMCI_PLAYを指定して曲を演奏する時、第三引数にMCI_NOTIFY、第四引数の MCI_PLAY_PARMSのdwCallbackにアプリケーションのウィンドウハンドルを指定してmciSendCommandを 実行すると演奏が始まります。その後、演奏が終わるとdwCallbackに指定したウィンドウに MM_MCINOTIFYメッセージが送られます。途中で中断しても送られますがAPIの実行状態は メッセージとともに送られるwParamで判定します。
  2. デバイスが初期化・Openできた時はこのメンバにデバイスIDが返されてきます。 以降このデバイスIDをmciSendCommandの第一引数に設定して各コマンドを実行します。
  3. Openするデバイスの種類です。mciSendCommandの第三引数にMCI_OPEN_TYPEを設定して、 このメンバが使われていることを知らせます。例えば、Wave形式は"WaveAudio"、 mp3形式は"MPEGAudio"、MIDI形式は"Sequencer"を指定します。 その他の値はレジストリの
    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\MCI Extensions
    にあります。ここには、文字列以外にもデバイス形式を表す定数を指定することもできます。 MCI_DEVTYPE_WAVEFORM_AUDIOなどがありますが、設定できる値はMSDNでMCI_OPEN_PARMSの lpstrDeviceTypeを参照してもらうとして、ここに定数を設定したい場合はmciSendCommandの 第三引数にMCI_OPEN_TYPEに加えてMCI_OPEN_TYPE_IDも 論理和で設定する必要があります。
  4. Openするファイル名を設定します。mciSendCommandの第三引数にMCI_OPEN_ELEMENT を設定してこのメンバが使われていることを知らせます。ここにはファイル名以外にも デバイス内部にこの要素をもって いる場合はDWORD値を指定できます。その場合は MCI_OPEN_ELEMENT_IDも論理和で MCI_OPEN_ELEMENTに加えてください。
  5. デバイスのエイリアスを設定します。mciSendCommandの第三引数にMCI_OPEN_ALIAS を設定してこのメンバが使われていることを知らせます。
  6. ここで設定した値から演奏(Play)を始めます。mciSendCommandの第三引数にMCI_FROM を設定してこのメンバが使われていることを知らせます。ここに指定する値の単位ですが MCI_SETで設定します。次のセクションで示す例ではミリ秒単位で設定しています。 このメンバを使わなかったら最初から演奏します。
  7. 第二引数にMCI_PLAYを設定した場合は演奏を終わる(Stop)位置を指定します。 MCI_SEEKを設定した場合はデバイスの移動位置をこのメンバで指定します。 mciSendCommandの第三引数にMCI_TOを設定してこのメンバが使われていることを知らせます。 値の単位はMCI_SETで設定します。
  8. MCI_SET_TIME_FORMATを第三引数に指定して、(F)や(G)で設定する値の単位や後述する 曲の長さを取得する際などの単位をこのメンバに設定します。
  9. オーディオのチャンネル関係の設定項目です。
  10. この構造体のdwItemメンバに関する現在のデバイスの状態の結果を受取ります。
  11. デバイスの現在の状態の種類を指定するメンバです。mciSendCommandの第三引数に MCI_STATUS_ITEMを設定してこのメンバが使われていることを知らせます。例えば以下のような 現在の状態を調べることができ、結果が(J)のdwReturnに返されます。
    このメンバに設定する定数 返される状態の説明
    MCI_STATUS_LENGTH 音楽ファイルの全体の長さ
    MCI_STATUS_MODE 現在の演奏状態(Play,Pauseなど)
    MCI_STATUS_POSITION 現在の演奏位置(単位はMCI_SETで設定)
    MCI_STATUS_TIME_FORMAT 位置や長さなどの単位
  12. トラックがあるデバイスに関してトラック番号を指定してそのトラックの長さや開始位置をdwReturnに 受取ります。mciSendCommandの第三引数にMCI_TRACKを指定してこのメンバが使われていることを 知らせます。

このAPIはちょっと使い方がややこしくて、音楽の再生に関係する内の 基本的な部分を書いただけなので詳しく知りたい方はMSDNをお調べください。
長々と書きましたが文章だけでは使い方がいまいちよく分からないと思いますので、 実際にごく簡単な音楽プレーヤをVC++ 2005で作成して使い方を書きます。