DirectXプログラミング講座 〜Vol9. DirectMusicを利用したWAVE/MIDIの再生〜

DirectXの機能の1つでもある、DirectMusic。このDirectMusicを利用すれば、サウンド関連のハードウェアを独占したハイパフォーマンスなサウンド処理を実現できます。まずは初歩的なWAVE/MIDIファイルの再生に挑戦してみましょう。


実践の前に…。何でDirectMusicを利用する必要があるの!?

3Dグラフィックスを描画するなら、Win32APIが提供する描画関数よりも、断然DirectXを利用したほうが高度な処理ができることは、皆さんご存知のとおりでしょう。では、Windowsが標準で提供しているMCIコマンドとDirectMusicとを比較した場合、どのような特徴をDirectMusicが持ち合わせることになるのでしょうか。また、どのような処理を行う場合にDirectMusicを取り入れたほうがよいのか、少し考えてみます。

高精度なタイムスケジューリングシステム

DirectMusicはハードウェアをフル活用してサウンドの再生を行います。よって、MCIコマンドと比較するとサウンド再生の際に生じる時間的な誤差が少なくて済みます。これは、サウンドのテンポがキャラクタの動作に深く関係する場合などに要求されます。キャラクタの動きとサウンドテンポのズレを最小限に押さえる目的であれば、DirectMusicを活用しない手はないでしょう。

3D空間におけるサウンド処理

何かしらのサウンドを発しながら3D空間を動き回る物体を再現するためには、どのような処理を行う必要があるのでしょうか。左右(もしくは更に前後)のスピーカーの音量を計算することや、ドップラー効果に対するサウンド周波数の変化を考慮する必要があります。これらすべてを自動的に行ってくれるのがDirectMusic(厳密にはそれに関わるDirectSound)です。例えば、3D空間の中を救急車が疾走するプログラムは、DirectMusicを利用することで簡単に再現できます。

CAudioクラス

ABDXはDirectMusicを簡単に扱うためのCAudioクラスを提供しています。このクラスでは、以下のメンバ関数を呼び出すことで基本的なサウンド制御を行うことができます。


'WAVE形式またはMIDI形式のファイルを読み込み、メモリ上に展開します。
CAudio::Load(
    pszFileName As BytePtr    'サウンドファイルパス
) As Long

'サウンドイメージを再生します。
CAudio::Play() As Long

再生中のサウンドを停止します。
CAudio::Stop() As Long

※より詳しい仕様はヘルプファイルに記載されています

サウンドを再生するサンプルプログラム

プロジェクト名を "dmtest" にセットして、DirectXアプリケーションのプロジェクトを新たに作成します。ここから、dmtest.abpに対してコーディングをしていきます。

●dmtest.abpの先頭部分のコーディング

CAudioオブジェクトポインタの定義を行います。

#include "dmtest.idx"


Dim ScreenX=640 As Long    'ディスプレイの幅  (ピクセル単位)
Dim ScreenY=480 As Long    'ディスプレイの高さ(ピクセル単位)

' TODO: この位置にグローバル変数を定義してください。
Dim pAudio As *CAudio

●InitProc関数のコーディング

CAudioオブジェクトの生成を行います。Load関数には適当なWAVE/MIDIファイルを指定しておきます。

Function InitProc()
    'DirectXを初期化
    If dx_Init(hMainWnd,ScreenX,ScreenY,FALSE)=0 Then
        InitProc=0
        Exit Function
    End If

    'マウスカーソルを非表示にする
    ShowCursor(FALSE)

    ' TODO: この位置にアプリケーションの初期化コードを記述してください。

    'CAudioクラスの生成
    pAudio=New CAudio

    'サウンドファイルをロード(適当にWAVE/MIDIファイルを指定します)
    pAudio->Load("C:\Winnt\Media\The Microsoft Sound.wav")

    '再生
    pAudio->Play()

    InitProc=1
End Function

●QuitProc関数のコーディング

pAudioオブジェクトを解放します。

Sub QuitProc()
    ' TODO: この位置にアプリケーションの終了処理を記述してください。

    '停止
    pAudio->Stop()

    'pAudioオブジェクトを破棄
    Delete pAudio

    'DirectXの終了処理
    dx_Quit()
End Sub

実行してみると、真っ黒な画面に切り替わると同時に指定したサウンドが再生されます。プログラム終了の際に、サウンドは停止します。

DirectGraphicsを使わずにDirectMusicだけを利用するための小技

上記のサンプルのように、DirectMusicのサウンド機能だけを利用したいのに、DirectGraphicsの初期化が自動的に行われてしまい、結果的に真っ黒な画面が映し出されてしまいます。そこで、InitProc関数及びメインループの部分を以下のように書き換えることで、このDirectGraphicsの初期化処理をキャンセルすることができます。

●InitProc関数のコーディング

Function InitProc()
    'COMを初期化
    CoInitialize(NULL)

    'DirectMusicを初期化
    If dx_InitDMusic()=0 Then
        InitProc=0
        Exit Function
    End If

    ' TODO: この位置にアプリケーションの初期化コードを記述してください。

    'CAudioクラスの生成
    pAudio=New CAudio

    'サウンドファイルをロード(適当にWAVE/MIDIファイルを指定します)
    pAudio->Load("C:\Winnt\Media\The Microsoft Sound.wav")

    '再生
    pAudio->Play()

    InitProc=1
End Function

●メインループのコーディング

'------------------------------------------------
' メインループ
'------------------------------------------------
Dim msgMain As MSG, iResult As Long
Do
    If PeekMessage(msgMain,0,0,0,PM_REMOVE) Then
        '----------------------------------
        ' メインウィンドウのメッセージ処理
        '----------------------------------

        If msgMain.message=WM_QUIT Then Exit Do
        TranslateMessage(msgMain)
        DispatchMessage(msgMain)
    Else
        '---------------------------
        ' DirectXによる入力及び描画
        '---------------------------

        InputActionProc()        '入力

        RenderProc()             'レンダリング(描画)
    End If
Loop


講座インデックスへ戻る ©2005 Discoversoft