前回のDirectX Audioの続きです。今回は、複数のサウンドを同時に再生させるというものです。BGMとしてMIDIファイルを演奏させながら、効果音などとしてウェーブファイルを再生させる、といった使い方ができます。
MirectMusic(またはDirectX Audio)では、セグメントは演奏させる時の役割として、2つに分けられます。
1つはプライマリセグメントです。これは1つのパフォーマンス中で一度に1つだけ演奏でき、パフォーマンス全体のテンポなどを決定します。前回まで作成したスクリプトでは、すべてセグメントをプライマリセグメントとして再生させています。
もう1つはセカンダリセグメントです。これはプライマリセグメントと共に演奏されるサウンドのことで、通常は短いサウンドなどを演奏するのに使われます。
プライマリセグメントは同時に1つしか再生させることができませんが、セカンダリセグメントは同時に複数を再生させることができます。したがって、BGMとして演奏するサウンドをプライマリセグメントとして再生させ、効果音などをセカンダリセグメントとして再生させるということができます。
セグメントをプライマリセグメントとして演奏させるか、セカンダリセグメントとして演奏させるかは、演奏時に指定します。 IDirectMusicPerformance8::PlaySegment メソッドまたは IDirectMusicPerformance8::PlaySegmentEx メソッドを呼び出す際に、動作フラグ(dwFlags パラメータ)として、 DMUS_SEGF_SECONDARY フラグ (0x0080) を指定した場合にはセカンダリセグメントとして演奏されます。 DMUS_SEGF_SECONDARY フラグを指定しなかった場合にはプライマリセグメントとして演奏されます。
; pPerformance->PlaySegmentEx() ; セカンダリセグメントとして再生 pm.0 = pSegment pm.1 = 0 pm.2 = 0 pm.3 = 0x0080 ; DMUS_SEGF_SECONDARY pm.4 = 0, 0 ; 64ビット値は2つのパラメータとして扱う pm.6 = 0 pm.7 = 0 pm.8 = 0 icall pPerformance, IDirectMusicPerformance8_PlaySegmentEx, pm, 9
セグメントごとに、演奏の繰り返し回数を設定することができます。繰り返し回数を設定するには、 IDirectMusicSegment8::SetRepeats メソッドを呼び出します。
HRESULT SetRepeats( DWORD dwRepeats );
dwRepeats には、繰り返す回数を指定します。このパラメータに 0 を指定すると、一度だけ演奏します。また、 -1 (DMUS_SEG_REPEAT_INFINITE) を指定すると、繰り返し回数は無限回となり、明示的に停止されるまで演奏を繰り返すことになります。
; pSegment->SetRepeats( DMUS_SEG_REPEAT_INFINITE ); pm = -1 ; 繰り返し演奏させる場合は -1 を指定 icall pSegment, IDirectMusicSegment8_SetRepeats, pm, 1
IID Explorer から取得されたオブジェクトのクラス ID ・インターフェース ID や、インターフェースのメソッドのインデックス、また、その他の GUID の定義を行なっています。メインスクリプトでこのファイルをインクルードする必要があります。
; 定義用スクリプト def.as ; クラスIDの定義 #define CLSID_DirectMusicPerformance "{d2ac2881-b39b-11d1-8704-00600893b1bd}" #define CLSID_DirectMusicLoader "{d2ac2892-b39b-11d1-8704-00600893b1bd}" #define CLSID_DirectMusicSegment "{d2ac2882-b39b-11d1-8704-00600893b1bd}" ; インターフェースIDとメソッドインデックスの定義 #define IID_IDirectMusicPerformance8 "{679c4137-c62e-4147-b2b4-9d569acb254c}" ; IDirectMusicPerformance8 Methods in VTable Order #define IDirectMusicPerformance8_QueryInterface 0 #define IDirectMusicPerformance8_AddRef 1 #define IDirectMusicPerformance8_Release 2 #define IDirectMusicPerformance8_Init 3 #define IDirectMusicPerformance8_PlaySegment 4 #define IDirectMusicPerformance8_Stop 5 #define IDirectMusicPerformance8_GetSegmentState 6 #define IDirectMusicPerformance8_SetPrepareTime 7 #define IDirectMusicPerformance8_GetPrepareTime 8 #define IDirectMusicPerformance8_SetBumperLength 9 #define IDirectMusicPerformance8_GetBumperLength 10 #define IDirectMusicPerformance8_SendPMsg 11 #define IDirectMusicPerformance8_MusicToReferenceTime 12 #define IDirectMusicPerformance8_ReferenceToMusicTime 13 #define IDirectMusicPerformance8_IsPlaying 14 #define IDirectMusicPerformance8_GetTime 15 #define IDirectMusicPerformance8_AllocPMsg 16 #define IDirectMusicPerformance8_FreePMsg 17 #define IDirectMusicPerformance8_GetGraph 18 #define IDirectMusicPerformance8_SetGraph 19 #define IDirectMusicPerformance8_SetNotificationHandle 20 #define IDirectMusicPerformance8_GetNotificationPMsg 21 #define IDirectMusicPerformance8_AddNotificationType 22 #define IDirectMusicPerformance8_RemoveNotificationType 23 #define IDirectMusicPerformance8_AddPort 24 #define IDirectMusicPerformance8_RemovePort 25 #define IDirectMusicPerformance8_AssignPChannelBlock 26 #define IDirectMusicPerformance8_AssignPChannel 27 #define IDirectMusicPerformance8_PChannelInfo 28 #define IDirectMusicPerformance8_DownloadInstrument 29 #define IDirectMusicPerformance8_Invalidate 30 #define IDirectMusicPerformance8_GetParam 31 #define IDirectMusicPerformance8_SetParam 32 #define IDirectMusicPerformance8_GetGlobalParam 33 #define IDirectMusicPerformance8_SetGlobalParam 34 #define IDirectMusicPerformance8_GetLatencyTime 35 #define IDirectMusicPerformance8_GetQueueTime 36 #define IDirectMusicPerformance8_AdjustTime 37 #define IDirectMusicPerformance8_CloseDown 38 #define IDirectMusicPerformance8_GetResolvedTime 39 #define IDirectMusicPerformance8_MIDIToMusic 40 #define IDirectMusicPerformance8_MusicToMIDI 41 #define IDirectMusicPerformance8_TimeToRhythm 42 #define IDirectMusicPerformance8_RhythmToTime 43 #define IDirectMusicPerformance8_InitAudio 44 #define IDirectMusicPerformance8_PlaySegmentEx 45 #define IDirectMusicPerformance8_StopEx 46 #define IDirectMusicPerformance8_ClonePMsg 47 #define IDirectMusicPerformance8_CreateAudioPath 48 #define IDirectMusicPerformance8_CreateStandardAudioPath 49 #define IDirectMusicPerformance8_SetDefaultAudioPath 50 #define IDirectMusicPerformance8_GetDefaultAudioPath 51 #define IDirectMusicPerformance8_GetParamEx 52 #define IID_IDirectMusicLoader8 "{19e7c08c-0a44-4e6a-a116-595a7cd5de8c}" ; IDirectMusicLoader8 Methods in VTable Order #define IDirectMusicLoader8_QueryInterface 0 #define IDirectMusicLoader8_AddRef 1 #define IDirectMusicLoader8_Release 2 #define IDirectMusicLoader8_GetObject 3 #define IDirectMusicLoader8_SetObject 4 #define IDirectMusicLoader8_SetSearchDirectory 5 #define IDirectMusicLoader8_ScanDirectory 6 #define IDirectMusicLoader8_CacheObject 7 #define IDirectMusicLoader8_ReleaseObject 8 #define IDirectMusicLoader8_ClearCache 9 #define IDirectMusicLoader8_EnableCache 10 #define IDirectMusicLoader8_EnumObject 11 #define IDirectMusicLoader8_CollectGarbage 12 #define IDirectMusicLoader8_ReleaseObjectByUnknown 13 #define IDirectMusicLoader8_LoadObjectFromFile 14 #define IID_IDirectMusicSegment8 "{c6784488-41a3-418f-aa15-b35093ba42d4}" ; IDirectMusicSegment8 Methods in VTable Order #define IDirectMusicSegment8_QueryInterface 0 #define IDirectMusicSegment8_AddRef 1 #define IDirectMusicSegment8_Release 2 #define IDirectMusicSegment8_GetLength 3 #define IDirectMusicSegment8_SetLength 4 #define IDirectMusicSegment8_GetRepeats 5 #define IDirectMusicSegment8_SetRepeats 6 #define IDirectMusicSegment8_GetDefaultResolution 7 #define IDirectMusicSegment8_SetDefaultResolution 8 #define IDirectMusicSegment8_GetTrack 9 #define IDirectMusicSegment8_GetTrackGroup 10 #define IDirectMusicSegment8_InsertTrack 11 #define IDirectMusicSegment8_RemoveTrack 12 #define IDirectMusicSegment8_InitPlay 13 #define IDirectMusicSegment8_GetGraph 14 #define IDirectMusicSegment8_SetGraph 15 #define IDirectMusicSegment8_AddNotificationType 16 #define IDirectMusicSegment8_RemoveNotificationType 17 #define IDirectMusicSegment8_GetParam 18 #define IDirectMusicSegment8_SetParam 19 #define IDirectMusicSegment8_Clone 20 #define IDirectMusicSegment8_SetStartPoint 21 #define IDirectMusicSegment8_GetStartPoint 22 #define IDirectMusicSegment8_SetLoopPoints 23 #define IDirectMusicSegment8_GetLoopPoints 24 #define IDirectMusicSegment8_SetPChannelsUsed 25 #define IDirectMusicSegment8_SetTrackConfig 26 #define IDirectMusicSegment8_GetAudioPathConfig 27 #define IDirectMusicSegment8_Compose 28 #define IDirectMusicSegment8_Download 29 #define IDirectMusicSegment8_Unload 30
インターフェースメソッドの呼び出しをモジュールにまとめました。
#module "daudio" #include "def.as" ; ====================================================================== ; DirectX Audio の初期化(パフォーマンスの作成・初期化、ローダー作成) ; ====================================================================== #deffunc DA_Init mref stt, 64 ; ローダーの作成 createobj pLoader, CLSID_DirectMusicLoader, IID_IDirectMusicLoader8 if pLoader == 0 : stt = 1 : return ; パフォーマンスの作成 createobj pPerformance, CLSID_DirectMusicPerformance, IID_IDirectMusicPerformance8 if pPerformance == 0 : stt = 1 : return ; パフォーマンスの初期化 ; pPerf->InitAudio( NULL, NULL, NULL, DMUS_APATH_SHARED_STEREOPLUSREVERB, ; 16, DMUS_AUDIOF_ALL, NULL ); pm = 0, 0, 0, 1, 16, $3f, 0 icall pPerformance, IDirectMusicPerformance8_InitAudio, pm, 7 if dllret < 0 : stt = 1 : return stt = 0 return ; ====================================================================== ; サウンドファイルの読み込み(セグメント作成) ; ====================================================================== #deffunc DA_LoadFile val, str mref retSegment, 16 ; セグメントインターフェースを格納する変数 mref setfilename, 33 ; ファイル名 retSegment = 0 sdim filename, 260 : filename = setfilename ; ファイル名を Unicode に変換 sdim w_filename, 520 ; Unicode を格納する変数 to_uni w_filename, filename, -1 ; Unicode に変換 ; pLoader->LoadObjectFromFile( CLSID_DirectMusicSegment, ; IID_IDirectMusicSegment8, &w_filename, &pSegment ); clsidconv clsid, CLSID_DirectMusicSegment pm.0 = clsid iidconv iid, IID_IDirectMusicSegment8 pm.1 = iid getptr pm.2, w_filename getptr pm.3, retSegment icall pLoader, IDirectMusicLoader8_LoadObjectFromFile, pm, 4 if dllret < 0 : stt = 1 : return ; retSegment->Download( pPerformance ); pm = pPerformance icall retSegment, IDirectMusicSegment8_Download, pm, 1 if dllret < 0 : stt = 1 : return stt = 0 return ; ====================================================================== ; セグメントの演奏 ; ====================================================================== #deffunc DA_Play int, int mref pSegment, 0 ; セグメントインターフェースポインタ mref fSecondary, 1 ; 1 のときセカンダリセグメント ; pPerformance->PlaySegmentEx( pSegment, NULL, NULL, ***, (__int64)0, ; NULL, NULL, NULL); pm = pSegment, 0, 0, 0, 0, 0, 0, 0, 0 if fSecondary : pm.3 = 128 ; DMUS_SEGF_SECONDARY icall pPerformance, IDirectMusicPerformance8_PlaySegmentEx, pm, 9 if dllret < 0 : stt = 1 : return stt = 0 return ; ====================================================================== ; セグメントの演奏の停止 ; ====================================================================== #deffunc DA_Stop mref pSegment, 0 ; セグメントインターフェースポインタ ; pPerformance->StopEx(pSegment,(__int64) 0,0); pm = pSegment, 0, 0, 0 ; 64ビット値は2つのパラメータとして扱う icall pPerformance, IDirectMusicPerformance8_StopEx, pm, 4 if dllret < 0 : stt = 1 : return stt = 0 return ; ====================================================================== ; 繰り返し回数の設定 ; ====================================================================== #deffunc DA_Repeat int, int mref pSegment ; セグメントインターフェースポインタ mref nRepeats, 1 ; 回数(0 は1回のみ, -1 は無限回) ; pSegment->SetRepeats( nRepeats ); pm = nRepeats icall pSegment, IDirectMusicSegment8_SetRepeats, pm, 1 if dllret < 0 : stt = 1 : return stt = 0 return ; ====================================================================== ; セグメントの解放 ; ====================================================================== #deffunc DA_FreeSegment int mref pSegment ; セグメントインターフェースポインタ ; pSegment->Unload(pPerformance); pm = pPerformance icall pSegment, IDirectMusicSegment8_Unload, pm, 1 ; pSegment->Release(); release pSegment return ; ====================================================================== ; 後始末(パフォーマンス・ローダーの解放/終了時に自動的に呼び出される) ; ====================================================================== #deffunc DA_Free onexit ; ローダーの解放 if pLoader { ; pLoader->Release(); release pLoader pLoader = 0 } ; パフォーマンスの解放 if pPerformance { ; pPerformance->CloseDown(); icall pPerformance, IDirectMusicPerformance8_CloseDown ; pPerformance->Release(); release pPerformance pPerformance = 0 } return #global
ファイルをロードして演奏するサンプルです。
#include "llmod.as" #include "unicode.as" #include "rrmod/com/lollipop.as" #include "daudio.as" sdim buf, 260, 4 sdim filename, 260, 4 screen 0, 500, 360 objsize 90 repeat 4 x = 20 : y = cnt*90 + 30 pos x, y-25 if cnt==0 { mes "プライマリセグメント" } else { mes "セカンダリセグメント"+cnt } pos x, y : button "open", *lb_open : btnid_o.cnt = stat pos x+100, y : button "play", *lb_play : btnid_p.cnt = stat pos x+200, y : button "stop", *lb_stop : btnid_s.cnt = stat pos x+300, y : chkbox "リピート", floop.cnt pos x, y+30 : mesbox buf.cnt, 450, 25, 2 : boxid.cnt = stat loop ; DirectX Audio の初期化 DA_Init if stat : dialog "DirectX Audio の初期化に失敗" : end stop *lb_open ; 押されたボタンを判定 repeat 4 if stat == btnid_o.cnt : idx = cnt : break loop ; ファイルを開く dialog "mid;*.wav", 16, "サウンドファイル" if stat == 0 : stop filename.idx = refstr if pSegment.idx { ; すでに読み込まれている場合は解放 DA_FreeSegment pSegment.idx } ; ファイルを読み込んでセグメントを作成 DA_LoadFile pSegment.idx, filename.idx if stat : dialog "ファイル読み込みに失敗" : stop ; ファイル名を表示 objprm boxid.idx, filename.idx stop *lb_play ; 押されたボタンを判定 repeat 4 if stat == btnid_p.cnt : idx = cnt : break loop if pSegment.idx { ; リピート回数の設定 if floop.idx { DA_Repeat pSegment.idx, -1 } else { DA_Repeat pSegment.idx, 0 } ; セグメントの演奏 if idx == 0 { DA_Play pSegment.0 ; プライマリセグメントとして演奏 } else { DA_Play pSegment.idx, 1 ; セカンダリセグメントとして演奏 } } stop *lb_stop ; 押されたボタンを判定 repeat 4 if stat == btnid_s.cnt : idx = cnt : break loop ; セグメントの演奏を停止 if pSegment.idx : DA_Stop pSegment.idx stop