MIDI を演奏する

DirectX の IDirectMusicLoader8 を使って PlaySegmentEx で MIDI を演奏する基本プログラムです。

前田稔(Maeda Minoru)の超初心者のプログラム入門

プロジェクトの作成

  1. プライベートライブラリを使わないで DirectX9 の標準ライブラリだけで作成します。
    [ファイル] [新規作成] [プロジェクト] から空のプロジェクト(Midi)を作成して下さい。
    プロジェクトのフォルダーに次のファイルを格納して下さい。
    プロジェクト/既存項目の追加から Midi.cpp をプロジェクトに追加して下さい。
    ファイル名 ファイルの説明
    Midi.cpp 「プログラムの説明」を参考に作成して下さい
    midi1.mid ネットから適当な MIDI を調達して名前を変更して下さい
    midi2.mid ネットから適当な MIDI を調達して名前を変更して下さい
  2. このプログラムは、カレントフォルダーに格納されている midi1.mid と midi2.mid を DialogBox のボタン操作で切り替えます。
    次の DialogBox を作成して下さい。
  3. DialogBox のキャプションとIDです。
    BOX キャプション ID
    DialogBox MIDI Program IDD_DIALOG1
    Button LOAD MIDI-1 IDC_BUTTON1
    Button LOAD MIDI-2 IDC_BUTTON2
    Button MIDI 演奏 IDC_BUTTON3
    Button MIDI 停止 IDC_BUTTON4
    Button CLOSE IDC_CLOSE
  4. MIDI のプログラムでは、特にリンクするライブラリはありません。
    dxguid.lib は #pragma でリンクしているので特に操作は不要です。
        #pragma comment(lib,"dxguid.lib")
        #pragma comment(lib,"dxerr9.lib")
        #pragma comment(lib,"winmm.lib")
        
  5. ビルドから実行を選ぶと midi1.mid がロードされて演奏の準備が整います。
    「MIDI 演奏」をクリックすると演奏が始まります。
    演奏は繰り返し100回演奏されるので、停止するときは「MIDI 停止」ボタンを押して下さい。
    「LOAD MIDI-2」をクリックすると、演奏が停止して midi2.mid がロードされます。

プログラムの説明

  1. Dmusici.h をインクルードすると、DirectMusic と DirectSound で必要な他のヘッダーファイルもインクルードされます。
    MIDI の演奏に必要な、3つのインターフェイスポインタを宣言します。
    DirectX9 でも DirectX8 と同じインターフェイスが使われています。
    AudioFile[MAX_PATH] がロードする MIDI ファイルです。
    LOAD ボタンで Midi1[] または Midi2[] がコピーされます。
        #include    <dmusici.h>
        #include    "resource.h"
        #define     SAFE_RELEASE(p) { if (p) { (p)->Release(); (p)=NULL; } }
        #define     ERRMSG(x)  MessageBox(NULL,x,"Audio",MB_OK);
        #pragma     comment(lib,"dxguid.lib")
        #pragma     comment(lib,"dxerr9.lib")
        #pragma     comment(lib,"winmm.lib")
    
        IDirectMusicLoader8*      g_pLoader         = NULL;
        IDirectMusicPerformance8* g_pPerformance    = NULL;
        IDirectMusicSegment8*     g_pSegment        = NULL;
    
        WCHAR       AudioFile[MAX_PATH];
        char        Midi1[24]=  "midi1.mid";
        char        Midi2[24]=  "midi2.mid";
        
  2. WinMain() は DialogBox を表示するだけです。
  3. DialogBox の CALLBACK 関数です。
    WM_INITDIALOG: でアプリケーションを初期化して Midi1 をロードします。
        switch(msg)
        {   case WM_INITDIALOG:
                if (FAILED(InitDirectAudio()))
                {   EndDialog(hDlg,TRUE);
                    return (TRUE);
                }
                Load(Midi1);
                break;
        
  4. Button がクリックされたときの処理です。
    IDC_BUTTON1 と IDC_BUTTON2 で MIDI をロードします。
    IDC_BUTTON5 で MIDI を繰り返し演奏します。
    IDC_BUTTON6 で MIDI の演奏を停止します。
    IDC_CLOSE でプログラムを終了します。
            case WM_COMMAND:
                switch(LOWORD(wParam))
                {   case IDC_BUTTON1:
                        Load(Midi1);
                        break;
                    case IDC_BUTTON2:
                        Load(Midi2);
                        break;
                    case IDC_BUTTON3:
                        Play(100);
                        break;
                    case IDC_BUTTON4:
                        Stop();
                        break;
                    case IDC_CLOSE:
                        PostMessage(hDlg,WM_CLOSE,0,0);
                        break;
                }
                break;
        
  5. プログラムの終了処理です。
    全てのオブジェクトを開放して終了します。
            case WM_CLOSE:
                FreeDirectAudio();
                EndDialog(hDlg,TRUE);
                return (TRUE);
        
  6. InitDirectAudio() でアプリケーションを初期化します。
    CoInitialize() で COM を初期化して、2つのオブジェクト(ローダーとパフォーマンス)を作成します。
    作成が終わると InitAudio() でパフォーマンスを初期化します。
        HRESULT InitDirectAudio()
        {   HRESULT hr;
    
            hr= CoInitialize(NULL);
            if (FAILED(hr))
            {   ERRMSG("Could not initialize COM");  return hr;   }
            hr= CoCreateInstance(CLSID_DirectMusicLoader,NULL,CLSCTX_INPROC, 
                                 IID_IDirectMusicLoader8,(void**)&g_pLoader);
            if (FAILED(hr))
            {   ERRMSG("Could not create DMusic Loader");
                FreeDirectAudio();
                return hr;
            }
            hr= CoCreateInstance(CLSID_DirectMusicPerformance,NULL,CLSCTX_INPROC,
                                 IID_IDirectMusicPerformance8,(void**)&g_pPerformance);
            if (FAILED(hr))
            {   ERRMSG("Could not create DMusic Performance");
                FreeDirectAudio();
                return hr;
            }
            hr= g_pPerformance->InitAudio(NULL,NULL,NULL,DMUS_APATH_SHARED_STEREOPLUSREVERB,
                                          64,DMUS_AUDIOF_ALL,NULL);
            if (FAILED(hr))
            {   ERRMSG("Could not initialize performance");
                FreeDirectAudio();
                return hr;
            }
            return S_OK;
        }
        
  7. MIDI をロードする関数です。
    現在演奏されているときは演奏を中止してアンロードします。
    指定された MIDI ファイルを AudioFile[] に格納して LoadSegment() 関数を呼び出します。
    MIDI を演奏する前にシンセサイザにダウンロードしておきます。
        HRESULT  Load(LPSTR midi)
        {   HRESULT hr;
            WORD    i;
    
            if (g_pPerformance != NULL)
            {   Stop();
                if (g_pSegment != NULL)
                {   g_pSegment->Unload(g_pPerformance);
                    g_pSegment= NULL;
                }
            }
            for(i=0; i<strlen(midi); i++)  AudioFile[i]= midi[i];
            AudioFile[i]= 0;
            hr = LoadSegment();
            if (FAILED(hr))
            {   ERRMSG("Could not load segment");  return hr;  }
            g_pSegment->Download(g_pPerformance);
            return S_OK;
        }
        
  8. LoadSegment() で MIDI を Segment にロードします。
        HRESULT LoadSegment()
        {   HRESULT     hr;
    
            hr= g_pLoader->LoadObjectFromFile(CLSID_DirectMusicSegment,IID_IDirectMusicSegment8,
                                              AudioFile,(LPVOID*)&g_pSegment);
            return hr;
        }
        
  9. 全てのオブジェクトを開放して終了する関数です。
        HRESULT FreeDirectAudio()
        {   Stop();
            SAFE_RELEASE(g_pSegment);
            if (g_pPerformance != NULL)
            {
                g_pPerformance->CloseDown();
                SAFE_RELEASE(g_pPerformance);
            }
            SAFE_RELEASE(g_pLoader);
            CoUninitialize();
            return S_OK;
        }
        
  10. 演奏を開始する関数です。
        void  Play(int rep)
        {
            g_pSegment->SetRepeats(rep);
            g_pPerformance->PlaySegmentEx(g_pSegment,NULL,NULL,0,0,NULL,NULL,NULL);
        }
        
  11. 演奏を停止する関数です。
        void  Stop()
        {   if (g_pPerformance != NULL)
                g_pPerformance->Stop(NULL,NULL,0,0);
        }
        
  12. ボリュームの設定などは Audio(MIDI,WAVE) のプログラム を参照して下さい。

プログラムは各自で作成して下さい

前田稔(Maeda Minoru)の超初心者のプログラム入門

超初心者のプログラム入門(DirectX9 game program)

超初心者のプログラム入門(DirectX10 game program)