<<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
|