<<Back To index
CEasyMusicクラス リファレンスマニュアル

概要
 DirectMusicを簡単に使うためのクラスです。初期化、データの読み込み、再生を簡単に出来るようになっています。MIDIを実際に読み込むセグメントは、外部に作るため、ユーザーが自由に使える設計になっています。また、多重再生用に、ミュージックパフォーマンスを追加することも出来ます。

用語説明

セグメント
 DirectMusicでは、再生のための1曲分のバッファをセグメントと呼びます。DirectDrawで言うところの、オフスクリーンサーフェスです。ゲーム中で使う曲の分だけセグメントを用意すると便利です。セグメントをパフォーマンスに渡して曲の再生を行います。

 EasyMusicでは、セグメントはクラスの外部に作ることになっています。内部に持つと、セグメント数に制限がでますから(初期化時に個数を指定するのもなんだかね・・)。プログラマは、クラスと一緒にセグメントも定義し、初期化をします。

パフォーマンス
 セグメントの再生等を管理します。複数のセグメントを正しく同時再生するには、パフォーマンスが複数必要になります(一つのパフォーマンスでも複数のセグメントを再生できますが、テンポや音が狂います)。MIDIの多重再生をしない場合は、パフォーマンスは一つでOKです。

 EasyMusicでは、パフォーマンスを一つだけ内蔵します。MIDIの多重再生をしないのであれば、プログラマはパフォーマンスの存在を意識する必要はありません。もし、多重再生をしたいのであれば、パフォーマンスを自分で定義し、AddMusicPerformance()でパフォーマンスを初期化し、ポインタを得ます。そのポインタを使い、LoadMusic()、PlayMusicEx()を呼び出してMIDIのロード、再生を行います。追加した分のパフォーマンスは自分で解放する必要があります。

メンバ関数

初期化
 bool InitDxMusic(LPDIRECTSOUND lpDxSound,char *strSerchPath,bool bDefault);
追加パフォーマンスを作る
 IDirectMusicPerformance* AddMusicPerformance();
MIDIファイルをロード
 IDirectMusicSegment* LoadMusic(IDirectMusicPerformance *lpDMPer,char *strFileName);
再生(プライマリ)
 bool PlayMusic(IDirectMusicSegment *lpDMSegment,int nLoopCount,MUSIC_TIME StartTime,MUSIC_TIME MinusEndTime);
再生(追加パフォーマンスを使う場合)
 bool PlayMusicEx(IDirectMusicPerformance *lpDxPer,IDirectMusicSegment *lpDMSegment,int nLoopCount,MUSIC_TIME StartTime,MUSIC_TIME MinusEndTime);
曲の停止
 bool StopMusic(IDirectMusicPerformance *lpDMPer);
セグメントの開放
 bool ReleaseMusic(IDirectMusicPerformance *lpDMPer,IDirectMusicSegment *lpDMSegment);

初期化
bool InitDxMusic(LPDIRECTSOUND lpDxSound,char *strSerchPath,bool bDefault);

引数
LPDIRECTSOUND lpDxSound
 DirectSoundのポインタです。同時にDirectSoundも使う場合は指定してください。DirectSoundを使わず、DirectMusicだけの場合はNULLを指定してください。

char *strSerchPath
 MIDIファイルの検索パスです。ここで指定したパスを基準に、MIDIファイルを読みに行きます。空白を指定すると、実行パスが基準になります。

bool bDefault
 デフォルトのポートを使うかどうかを設定します。一般的なシステムの場合、デフォルトはMSのソフトウェアシーケンサだったりします。これを使いたくない場合は、falseを指定してください(ただし、ポート選択部分が若干いい加減なので、そのうち直します(^;)。trueにすると、ポート選択のとき、デフォルトのポートを使います。

戻り値
 bool型 失敗>false 成功>true

解説
 DirectMusicの初期化をします。DirectXは6.1以降が必要です。初期化をしないと他のメンバ関数は使えませんので、必ず実行して下さい。

使用例
MySound.InitDxSound(hWnd,2,22050,16);//DirectSoundを初期化(EasySoundクラスを使用)
MyMusic.InitDxMusic(MySound.GetDirectSound(),"",true);//DirectSoundと併用、検索パスを空白でEasyMusicを初期化


追加パフォーマンスを作る
IDirectMusicPerformance* AddMusicPerformance();

引数
 なし

戻り値
 ミュージックパフォーマンスのポインタ。作成に失敗するとNULLを返します。

解説
 追加のミュージックパフォーマンスを作ります。MIDIを正しく多重再生するのに必要です。ひとつのパフォーマンスで、多重再生をすると、テンポやチャンネルを共有するので、音が狂います(作曲から考慮しなければならない)。ここで作ったミュージックパフォーマンスは、自分で解放する必要があります。EasyMusicは、内部にひとつだけパフォーマンスを持っています。

使用例
IDirectMusicPerformance *lpDMPerf2nd = NULL;//多重再生用パフォーマンス定義
lpDMPerf2nd = MyMusic.AddMusicPerformance();//パフォーマンスを追加

//解放
lpDMPerf2nd->CloseDown();
RELEASE(lpDMPerf2nd)

MIDIファイルをロード
IDirectMusicSegment* LoadMusic(IDirectMusicPerformance *lpDMPer,char *strFileName);

引数
IDirectMusicPerformance *lpDMPer
 追加した外部のパフォーマンス。外部の追加パフォーマンスを使用しないのであればNULLを指定してください。

char *strFileName
 ロードするMIDIファイルの名前です。検索パスを基準に書きます。

戻り値
 IDirectMusicSegmentのポインタを返します。

解説
 DirectMusicでは、MIDIファイルをセグメント呼ばれるバッファ(?)に格納して再生します。この関数では、セグメントの作成と、そこへのファイル読み込みを行っています。返ってきたポインタは、保存しておく必要があります(でないと再生とか出来ませんし)。

使用例
DirectMusicSegment *lpMidi01 = NULL;//セグメント宣言
//初期化とか・・・
lpMidi01 = MyMusic.LoadMusic(NULL,"rank.mid");//ロード
.....
lpMidi01 = MyMusic.LoadMusic(lpDMPerf2nd,"rank.mid");//追加パフォーマンスを使う場合


再生(プライマリ)
bool PlayMusic(IDirectMusicSegment *lpDMSegment,int nLoopCount,MUSIC_TIME StartTime,MUSIC_TIME MinusEndTime);

引数
IDirectMusicSegment *lpDMSegment
 ロードの時に返ってきた、セグメントのポインタを指定します。

int nLoopCount
 ループの回数です。

MUSIC_TIME StartTime
 曲の開始時間をミリ秒で指定します。5000を指定すると、曲の頭から5秒の所から再生します。

MUSIC_TIME MinusEndTime
 曲の最後から何秒手前で終わるかの指定です。5000を指定すると、終わりから5秒の位置で先頭に戻ります。

戻り値
 bool型 失敗>false 成功>true

解説
 MIDIをロードしたセグメントの内容を再生します。

使用例
lpMidi01 = MyMusic.LoadMusic(NULL,"rank.mid");
MyMusic.PlayMusic(lpMidi01,100,3000,0);//100回リピートで先頭から3秒の位置から再生


再生(追加パフォーマンスを使う場合)
bool PlayMusicEx(IDirectMusicPerformance *lpDxPer,IDirectMusicSegment *lpDMSegment,int nLoopCount,MUSIC_TIME StartTime,MUSIC_TIME MinusEndTime);

引数
IDirectMusicPerformance *lpDxPer
 セグメントの初期化に使ったパフォーマンス。外部の追加パフォーマンスを使用しないのであればPlayMusic()を使ってください。

IDirectMusicSegment *lpDMSegment
 ロードの時に返ってきた、セグメントのポインタを指定します。

int nLoopCount
 ループの回数です。

MUSIC_TIME StartTime
 曲の開始時間をミリ秒で指定します。5000を指定すると、曲の頭から5秒の所から再生します。

MUSIC_TIME MinusEndTime
 曲の最後から何秒手前で終わるかの指定です。5000を指定すると、終わりから5秒の位置で先頭に戻ります。

戻り値
 bool型 失敗>false 成功>true

解説
 MIDIをロードしたセグメントの内容を再生します。プライマリバッファですでにMIDIを再生している場合、効果音のような音楽を再生するのに使います。

使用例
lpMidi01 = MyMusic.LoadMusic(lpDMPerf2nd,"rank.mid");
MyMusic.PlayMusicEx(lpDMPerf2nd,lpMidi01,1,3000,0);//1回リピートで先頭から3秒の位置から再生


曲の停止
bool StopMusic(IDirectMusicPerformance *lpDMPer);

引数
IDirectMusicPerformance *lpDMPer
 セグメントの初期化に使ったパフォーマンス。外部の追加パフォーマンスを使用しないのであればNULLを指定してください。

戻り値
 bool型 失敗>false 成功>true

解説
 再生中のパフォーマンスを停止します。

使用例
MyMusic.StopMusic(NULL);//追加パフォーマンスを使わない
.....
MyMusic.StopMusic(lpDMPerf2nd);//多重再生に追加パフォーマンスを使う場合


セグメントの開放
bool ReleaseMusic(IDirectMusicPerformance *lpDMPer,IDirectMusicSegment *lpDMSegment);

引数
IDirectMusicPerformance *lpDMPer
 セグメントの初期化に使ったパフォーマンス。外部の追加パフォーマンスを使用しないのであればNULLを指定してください。

IDirectMusicSegment *lpDMSegment
 ロードの時に返ってきた、セグメントのポインタを指定します。

戻り値
 bool型 失敗>false 成功>true

解説
 セグメントを解放します。再生中の場合でも停止してから解放するので、明示的に停止する必要はありません。が、オブジェクトそのものの解放は、外でやる必要があります。サンプルコードのように書いてください。

使用例
MyMusic.ReleaseMusic(NULL,lpMidi01);//追加パフォーマンスを使わない
if(lpMidi01) lpMidi01->Release();//解放
.....
MyMusic.ReleaseMusic(lpDMPerf2nd,lpMidi01);//追加パフォーマンスを使う場合
if(lpMidi01) lpMidi01->Release();//解放


サンプルソース

//------------------------------------------------------------------
// music.cpp : CEasyMusicサンプルプログラム
//
//------------------------------------------------------------------
//内容
// DirectMusicの初期化、MIDIのロード、再生、停止、
//多重再生、解放ののサンプルです。
//------------------------------------------------------------------

#include "stdafx.h"
#include "EasyMusic.h"

HRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM);//メッセージ処理

CEasyMusic MyMusic;//EasyMusicクラス定義
IDirectMusicSegment *lpMidi01 = NULL,*lpMidi02 = NULL,*lpMidi03 = NULL;//セグメント定義
IDirectMusicPerformance *lpDMPerf2nd;//多重再生用パフォーマンス定義

//---------------------------------------------------
//関数名  WinMain()
//機能   メイン関数
//---------------------------------------------------
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow )
{

  WNDCLASSEX wndclass;//ウィンドウクラス
  HWND hWnd;     // ウインドウハンドル
  MSG msg;      //メッセージ

  // ウインドウクラスの生成
  ZeroMemory( &wndclass, sizeof( wndclass));
  wndclass.style = 0;
  wndclass.lpfnWndProc = WinProc;
  wndclass.cbClsExtra = 0;
  wndclass.cbWndExtra = 0;
  wndclass.hInstance = hInstance;
  wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  wndclass.lpszClassName = "Easy Lib Test";
  wndclass.cbSize = sizeof(WNDCLASSEX);

  if( !RegisterClassEx( &wndclass)) {
    MessageBox(NULL,"ウィンドウのレジストに失敗。","Error",MB_OK|MB_ICONEXCLAMATION);
    return 0;
  }
  // ウインドウの生成
  hWnd = CreateWindowEx(WS_EX_APPWINDOW,"Easy Lib Test","Easy Lib Test",WS_OVERLAPPEDWINDOW,
    CW_USEDEFAULT,CW_USEDEFAULT,640,480,HWND_DESKTOP, NULL,hInstance, NULL);

  ShowWindow( hWnd,SW_SHOW);
  UpdateWindow( hWnd);

  //EasyMusic初期化
  MyMusic.InitDxMusic(NULL,"",true);//初期化
  //MIDIをロード
  lpMidi01 = MyMusic.LoadMusic(NULL,"Music1.mid");
  lpMidi02 = MyMusic.LoadMusic(NULL,"Music2.mid");
  MyMusic.PlayMusic(lpMidi01,100,0,0);//再生

  //多重再生処理
  lpDMPerf2nd = MyMusic.AddMusicPerformance();//パフォーマンスを追加
  lpMidi03 = MyMusic.LoadMusic(lpDMPerf2nd,"xg054.mid");//パフォーマンス指定でロードMIDIを
  // メイン メッセージ ループ:
  while(TRUE) {
    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
      if (msg.message == WM_QUIT){
        PostQuitMessage(msg.wParam);
        return 0;
      }
      TranslateMessage( &msg );
      DispatchMessage( &msg );
    }
  }
  return 0;
}

//---------------------------------------------------
//関数名  WinProc()
//機能   メイン ウィンドウのメッセージを処理します。
//---------------------------------------------------
HRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
  switch(message) {
    case WM_DESTROY://終了処理
      MyMusic.ReleaseMusic(NULL,lpMidi01);//セグメント1の解放
      RELEASE(lpMidi01)
      MyMusic.ReleaseMusic(NULL,lpMidi02);//セグメント2の解放
      RELEASE(lpMidi02)
      MyMusic.ReleaseMusic(lpDMPerf2nd,lpMidi03);//セグメント3の解放
      RELEASE(lpMidi03)

      //多重再生用パフォーマンスの解放
      lpDMPerf2nd->CloseDown();
      RELEASE(lpDMPerf2nd)

      PostQuitMessage(0);
      break;
    case WM_KEYDOWN:
      switch(wParam){
        case 'Z':
          MyMusic.PlayMusic(lpMidi01,100,0,0);//セグメント1再生
          break;
        case 'X':
          MyMusic.PlayMusic(lpMidi02,100,0,0);//セグメント2再生
          break;
        case 'S':
          MyMusic.StopMusic(NULL);//1,2停止
          break;
        case 'A':
          MyMusic.PlayMusicEx(lpDMPerf2nd,lpMidi03,1,3000,3000);//セグメント3再生
      }
      break;
    case WM_PAINT:{
      char strBuff[128];
      PAINTSTRUCT rPaintRect;
      HDC hDC = BeginPaint(hWnd, &rPaintRect);

      sprintf(strBuff, "セグメント1 再生[Z] 100回リピート");
      TextOut(hDC,0,0,strBuff,strlen(strBuff));

      sprintf(strBuff, "セグメント2 再生[X] 100回リピート");
      TextOut(hDC,0,20,strBuff,strlen(strBuff));

      sprintf(strBuff, "セグメント1 セグメント2 停止[S]");
      TextOut(hDC,0,40,strBuff,strlen(strBuff));

      sprintf(strBuff, "セグメント3 再生[A] リピート無し");
      TextOut(hDC,0,60,strBuff,strlen(strBuff));

      EndPaint(hWnd, &rPaintRect);
    }
    default:
      return DefWindowProc( hWnd, message, wParam, lParam );
  }
  return 0;
}


 タブは全角スペースになってます。ビルドするためには、プロジェクトにEasyMusic.hとEasyMusic.cppを追加して、dxguid.libをリンクしてください。当然ですが、DirectX7のSDKが必要になりますので、別途入手してください。

 stdafx.hでは、windows.h、stdlib.h、malloc.h、memory.h、tchar.h、stdio.h、time.hをインクルードしていますが、多分全部は必要ないです。

written by Matsumoto keizi