今回はDirectX Audioについてやります。
DirectX Audioは、DirectX 8.0より追加されたコンポーネントです。以前のDirectSoundとDirextMusicを統合したコンポーネントという位置付けがされています。
以前のDirectXでは、ウェーブベースのサウンド(WAVファイルなど)の再生はDirectSoundによって行ない、メッセージベースのサウンド(MIDIなど)の再生はDirectMusicによって行なっていました。しかし、DirectX 8.0以降ではこれらを統合し、ウェーブベース、メッセージベースサウンドをともに同じような手順によって再生させることができるようになっています。
DirectSoundとDirectMusicが統合されたとはいっても、これらを合わせてまったく新しいひとつのコンポーネントになったというのではありません。以前と同じようにDirectSoundとDirectMusicのそれぞれのコンポーネントが存在しています。実際には、DirectMusic の方で、これまでのメッセージベースのサウンドだけでなく、ウェーブベースのサウンドも取り扱うことができるようにしたのです。
具体的には、ウェーブベースのサウンドをDirectMusicセグメントとして扱えるようにしたことで、DirectMusicのインターフェースによって操作することができるようになっています。以前のDirectSoundはウェーブサウンドはファイルの読み込みやバッファ操作はアプリケーション側で行なっていましたが、ここではファイルの読み込み・バッファ操作などの面倒な作業はDirectMusicによって自動的に行なわれるので、アプリケーション側の作業が楽になっています。
また、オーディオパスの導入など、以前のバージョンにはなかったさまざまな新機能が提供されています。
DirectX Audioとなってからの新しいDirectMusicでも、以前のDirectMusicで使用されていたオブジェクト(ローダー、セグメントなど)が使われますが、インターフェースは以前のものの拡張版のインターフェースを使用します。ここで使用されるインターフェースは、以前のインターフェース名に『8』がつけられています。たとえば、以前のDirectMusicで使用されていたインターフェースの拡張として IDirectMusicPerformance8、 IDirectMusicSegment8、 IDirectMusicLoader8 などが使われます。(DirectX 8.0で使用されるインターフェースの多くは、新しく追加されたインターフェースも含め、基本となるインターフェース名に『8』がつけられた名前になっています。)
新しく追加されたオブジェクトクラスとして、オーディオパスというものがあります。オーディオパスとは、パフォーマンスにおける再生から、実際に出力されるまでの、サウンドデータの流れを管理するオブジェクトのことです。
アプリケーションは複数のオーディオパスを作成することができ、例えば、リバーブが設定されたバッファで再生するオーディパスや、3Dサウンドコントロールが設定されたバッファで再生するオーディオパスをアプリケーションで作成し、それぞれのオーディオパスを指定することによって、それぞれの効果(リバーブや3Dサウンド)が得られます。また、オーディオパスごとにボリュームの設定を行なうことができるので、例えば、効果音のボリュームはそのままでBGMをフェードアウト・フェードインさせるなどということもできます。
では、実際にサウンドファイルを再生させてみることにします。再生できるサウンドはウェーブファイルおよびMIDIファイル(SMF)で、今回は、同時に再生できるサウンドは1つのみです。手順は以下のようになります。
パフォーマンスオブジェクトを作成して IDirectMusicPerformance8 インターフェースを取得し、 IDirectMusicPerformance8::InitAudio メソッドで初期化する。
ローダーオブジェクトを作成して IDirectMusicLoader8 インターフェースを取得する。
IDirectMusicLoader8::LoadObjectFromFile メソッドでファイルからセグメントオブジェクトを作成し、 IDirectMusicSegment8 インターフェースを取得する。
IDirectMusicSegment8::Download メソッドで、音色などの、セグメントのバンドデータをパフォーマンスにダウンロードする。
IDirectMusicPerformance8::PlaySegmentEx メソッドでセグメントを再生する。
演奏を停止させる場合には IDirectMusicPerformance8::StopEx メソッドを呼び出す。
IDirectMusicSegment8::Unload メソッドで音色データをアンロードする。
IDirectMusicPerformance8::CloseDown メソッドでパフォーマンスオブジェクトをクローズする。
IDirectMusicSegment8、 IDirectMusicLoader8、 IDirectMusicPerformance8 インターフェースの Release メソッドを呼び出して、オブジェクトを解放する。
新しいDirectMusicでも、演奏全体の管理・処理を行なうのはDiectMusicパフォーマンスオブジェクトです。まずはパフォーマンスを作成して、 IDirectMusicPerformance8 インターフェースを取得します。
パフォーマンスのクラスIDは以前と同じく
{d2ac2881-b39b-11d1-8704-00600893b1bd}
です。また、 IDirectMusicPerformance8 インターフェースのインターフェースIDは
{679c4137-c62e-4147-b2b4-9d569acb254c}
になります。これらを createobj 命令に渡すことで、インターフェースポインタを取得できます。
#include "llmod.as" #include "rrmod/com/lollipop.as" ; CLSID, IID やメソッドインデックスの定義を def.as で行なう #include "def.as" ; パフォーマンスオブジェクトの作成 createobj pPerformance, CLSID_DirectMusicPerformance, IID_IDirectMusicPerformance8
パフォーマンスオブジェクトを作成できたら、オブジェクトの初期化を行ないます。前回は Init メソッドを使用しましたが、今回はオーディオパスを使用するので、 InitAudio メソッドを呼び出します。
HRESULT InitAudio( IDirectMusic** ppDirectMusic, IDirectSound** ppDirectSound, HWND hwnd, DWORD dwDefaultPathType, DWORD dwPChannelCount, DWORD dwFlags, DMUS_AUDIOPARAMS* pParams );
ppDirectMusic、 ppDirectSound、 hwnd については、 ppDirectSound がインターフェースを格納した(あるいは、格納するための)変数のアドレスであるということ以外は Init メソッドのときと同じなので、説明は省略します。DirectMusicオブジェクトとDirectSoundオブジェクトはHSPプログラム側では直接取り扱わずに内部管理させるので、はじめの2つのパラメータには 0 (NULL) を指定します。また、 hwnd にはメインウィンドウのハンドルを指定します。
dwDefaultPathType には、デフォルトで作成される標準オーディオパスのタイプを指定します。例えば、ステレオ出力とリバーブエフェクトを持つオーディオパスを作成する場合には、 1 (DMUS_APATH_SHARED_STEREOPLUSREVERB) を指定します。 dwPChannelCount には、オーディオパスに割り当てるパフォーマンスチャンネル数を指定します。通常、ウェーブファイルの再生に必要なチャンネル数は 1 、MIDIファイルの演奏に必要なチャンネル数は 16 になるので、必要なチャンネル数を指定します。多少余分にチャンネル数を要求しても問題はありません。
dwFlags には、要求される機能を指定するフラグ値を指定します。ここでは、シンセサイザのすべての機能が使えるように 0x3F (DMUS_AUDIOF_ALL) を指定します。
pParams には、より詳細なパラメータを指定するのに DMUS_AUDIOPARAMS 構造体のアドレスを指定しますが、同時発声数やサンプリングレートを設定したり、デフォルトのシンセサイザの情報を取得したりする必要がない場合には、 0 (NULL) を指定します。
; IDirectMusicPerformance8::InitAudio メソッド pm = 0, 0 mref bmscr, 67 : pm.2 = bmscr.13 ; ウィンドウハンドル pm.3 = 1 ; DMUS_APATH_SHARED_STEREOPLUSREVERB pm.4 = 16 ; パフォーマンスチャンネル数 pm.5 = 0x3F ; DMUS_AUDIOF_ALL pm.6 = 0 icall pPerformance, IDirectMusicPerformance8_InitAudio, pm, 7
次にローダーを作成して、 IDirectMusicLoader8 インターフェースを取得します。ローダーのクラスIDは
{d2ac2892-b39b-11d1-8704-00600893b1bd}
です。また、 IDirectMusicLoader8 インターフェースのインターフェースIDは
{19e7c08c-0a44-4e6a-a116-595a7cd5de8c}
になります。これらを createobj 命令に渡すことで、インターフェースポインタを取得できます。
; ローダーオブジェクトの作成
createobj pLoader, CLSID_DirectMusicLoader, IID_IDirectMusicLoader8
ローダーを作成できたら、サウンドファイルからセグメントをロードし、 IDirectMusicSegment8 インターフェースを取得します。これには、 IDirectMusicLoader8::LoadObjectFromFile メソッドを呼び出します。
HRESULT LoadObjectFromFile( REFGUID rclsid, REFIID riid, WCHAR pwzFilePath, LPVOID *ppv );
rclsid には、作成するセグメントオブジェクトのクラスIDである CLSID_DirectMusicSegment を指定します。このクラスIDは
{d2ac2882-b39b-11d1-8704-00600893b1bd}
で表されます。これを clsidconv 命令を使用して構造体の形式にし、アドレスを指定します。
riid には、取得する IDirectMusicSegment8 インターフェースのインターフェースIDである IID_IDirectMusicSegment8 を指定します。このインターフェースIDは
{c6784488-41a3-418f-aa15-b35093ba42d4}
で表されます。これを iidconv 命令を使用して構造体形式にし、アドレスを指定します。
pwzFilePath には、フルパスのファイル名を格納した変数のアドレスを指定しますが、このファイル名はワイド文字列(Unicode 文字列)でなければならないので、 to_uni 命令で Unicode に変換しておく必要があります。
ppv には、インターフェースポインタを格納する変数のアドレスを指定します。ファイルロードに成功した場合には、この変数に IDirectMusicSegment8 インターフェースポインタが格納されます。
; ロードするファイル sdim filename, 260 dialog "mid", 16 : filename = refstr ; Unicode に変換 sdim w_filename, 520 to_uni w_filename, filename, -1 ; IDirectMusicSegment8::LoadObjectFromFile メソッド clsidconv clsid, CLSID_DirectMusicSegment pm.0 = clsid iidconv iid, IID_IDirectMusicSegment8 pm.1 = iid getptr pm.2, w_filename getptr pm.3, pSegment icall pLoader, IDirectMusicLoader8_LoadObjectFromFile, pm, 4
セグメントをロードできたら、音色などを含むセグメントのバンドデータをダウンロードします。これには、 IDirectMusicSegment8::Download メソッドを呼び出します。
HRESULT Download( IUnknown* pAudioPath );
pAudioPath には、ダウンロード先となるパフォーマンスオブジェクトもしくはオーディオパスオブジェクトの所有するインターフェースポインタを指定します。今回はパフォーマンスのインターフェースを指定します。 IUnknown インターフェースを渡すとなっていますが、 IDirectMusicSegment8 インターフェースを渡してしまって問題ありません。
; IDirectMusicSegment8::Download メソッド
pm = pPerformance
icall pSegment, IDirectMusicSegment8_Download, pm, 1
この作業は、MIDIファイルのデータに対してだけではなく、WAVファイルをロードした場合にも行う必要があります。
セグメントを再生させるには、 IDirectMusicPerformance8::PlaySegment メソッドまたは、 IDirectMusicPerformance8::PlaySegmentEx メソッドを呼び出します。今回は PlaySegmentEx メソッドの方を使ってみます。
HRESULT PlaySegmentEx( IUnknown* pSource, WCHAR* pwzSegmentName, IUnknown* pTransition, DWORD dwFlags, __int64 i64StartTime, IDirectMusicSegmentState** ppSegmentState, IUnknown* pFrom, IUnknown* pAudioPath );
pSource パラメータには、再生させるセグメントオブジェクトのインターフェースポインタを指定します。 pwzSegmentName は予約されたパラメータで、DirectX 8.0では使用されません。0 (NULL) を指定しておきます。 pTransition には、ここでは 0 (NULL) を指定しておきます。dwFlags 、 i64StartTime 、 ppSegmentState については、PlaySegment メソッドと同じです。 pFrom には新しいセグメントの演奏を開始するときに停止するセグメント状態またはオーディオパスのインターフェイスポインタを指定しますが、ここでは 0 (NULL) を指定しておきます。 pAudioPath には演奏に使用するオーディオパスのインターフェースポインタを指定しますが、デフォルトのオーディオパスを使用する場合は 0 (NULL) を指定します。
PlaySegment メソッドの時と同じく、 i64StartTime パラメータが64ビット値であるので、呼び出し時には注意が必要です。
; IDirectMusicPerformance8::PlaySegmentEx メソッド pm.0 = pSegment pm.1 = 0 pm.2 = 0 pm.3 = 0 pm.4 = 0, 0 ; 64ビット値は2つのパラメータとして扱う pm.6 = 0 pm.7 = 0 pm.8 = 0 ; パラメータ数は 9 icall pPerformance, IDirectMusicPerformance8_PlaySegmentEx, pm, 9
演奏を停止させるには、 IDirectMusicPerformance8::Stop メソッドまたは IDirectMusicPerformance8::StopEx メソッドを呼び出します。今回は StopEx メソッドの方を使います。
HRESULT StopEx( IUnknown* pObject, __int64 i64StopTime, DWORD dwFlags );
pObject には、演奏を停止するオブジェクト(ここではセグメント)のインターフェースポインタを指定します。 i64StopTime には、停止するタイムを示す64ビット値を指定します。 0 を指定すると、直ちに演奏を停止します。 dwFlags には、停止するタイミング(拍・小節などの境界)を指定できますが、今回はすぐに停止するように 0 を指定します。
このメソッドも i64StopTime が64ビット値なので注意が必要です。
; IDirectMusicPerformance8::StopEx メソッド pm.0 = pSegment pm.1 = 0, 0 pm.3 = 0 ; パラメータ数は 4 icall pPerformance, IDirectMusicPerformance8_StopEx, pm, 4
パフォーマンスにダウンロードしてあった音色データをアンロードします。これには、 IDirectMusicSegment8::Unload メソッドを呼び出します。
HRESULT Unload( IUnknown* pAudioPath );
pAudioPath には、パフォーマンスオブジェクトのインターフェースポインタを指定します。
音色をアンロードできたら、 release 命令でセグメントを解放します。
; IDirectMusicSegment8::Unload メソッド pm = pPerformance icall pSegment, IDirectMusicSegment8_Unload, pm, 1 ; セグメントの解放 release pSegment
実際には、あとでパフォーマンスをクローズするときにアンロードされていない音色はすべて自動的に解放されるため、明示的にアンロードする必要はありませんが。
パフォーマンスオブジェクトを閉じるには、IDirectMusicPerformance8::CloseDown メソッドを呼び出します。これは以前までのDirectMusicと同じです。
パフォーマンスのクローズができたら、 release 命令でパフォーマンスをを解放します。
; IDirectMusicPerformance::CloseDown メソッド icall pPerformance, IDirectMusicPerformance8_CloseDown ; パフォーマンスの解放 release pPerformance
最後に、ローダーオブジェクトがまだ残っているので、これを解放します。
; ローダーの解放
release pLoader
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
ファイルをロードして演奏するサンプルです。
#include "llmod.as" #include "unicode.as" #include "rrmod/com/lollipop.as" #include "def.as" ; ファイルのロード dialog "mid;*.wav", 16 if stat == 0 : end sdim filename, 260 ; ファイル名を格納する変数 filename = refstr ; パフォーマンスオブジェクト作成 createobj pPerformance, CLSID_DirectMusicPerformance, IID_IDirectMusicPerformance8 if pPerformance == 0 { dialog "パフォーマンス作成に失敗", 1 goto *lb_free } ; パフォーマンス初期化 ; pPerformance->InitAudio( NULL, NULL, hwnd, DMUS_APATH_SHARED_STEREOPLUSREVERB, ; 16, DMUS_AUDIOF_ALL, NULL); pm = 0, 0 mref bmscr, 67 : pm.2 = bmscr.13 ; ウィンドウハンドル pm.3 = 1 ; DMUS_APATH_SHARED_STEREOPLUSREVERB pm.4 = 16 ; パフォーマンスチャンネル数 pm.5 = 0x3F ; DMUS_AUDIOF_ALL pm.6 = 0 icall pPerformance, IDirectMusicPerformance8_InitAudio, pm, 7 if dllret < 0 { dialog "パフォーマンスの初期化に失敗", 1 goto *lb_free } ; パフォーマンス初期化済みを示すフラグ f_init = 1 ; ローダー作成 createobj pLoader, CLSID_DirectMusicLoader, IID_IDirectMusicLoader8 ; ファイル名の Unicode 変換 sdim w_filename, 520 ; Unicode を格納する変数 to_uni w_filename, filename, -1 ; Unicode に変換 ; pSegment8->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, pSegment icall pLoader, IDirectMusicLoader8_LoadObjectFromFile, pm, 4 if (dllret < 0)|(pSegment == 0) { dialog "ファイルロードに失敗", 1 goto *lb_free } ; pSegment->Download(pPerformance); pm = pPerformance icall pSegment, IDirectMusicSegment8_Download, pm, 1 if dllret < 0 { dialog "音色ダウンロード失敗", 1 goto *lb_free } ; セグメントの再生 ; pPerformance->PlaySegmentEx( pSegment, NULL, NULL, 0, (__int64) 0, ; NULL, NULL, NULL ); pm = pSegment,0,0,0,0,0,0,0,0 ; 64ビット値は2つのパラメータとして扱う icall pPerformance, IDirectMusicPerformance8_PlaySegmentEx, pm, 9 if dllret < 0 { dialog "セグメントの再生に失敗", 1 goto *lb_free } ; 停止ボタン表示 button "停止", *lb_stop onexit *lb_stop stop *lb_stop ; 演奏の停止 ; pPerformance->StopEx( pSegment, (__int64)0, 0); pm = pSegment, 0, 0, 0 ; 64ビット値は2つのパラメータとして扱う icall pPerformance, IDirectMusicPerformance8_StopEx, pm, 4 *lb_free ; 終了処理(オブジェクトの解放) if pSegment { ; pSegment->Unload( pPerformance ); pm = pPerformance icall pSegment, IDirectMusicSegment8_Unload, pm, 1 ; セグメントの解放 release pSegment pSegment = 0 } if pPerformance { if f_init { ; pPerformance->CloseDown(); icall pPerformance, IDirectMusicPerformance8_CloseDown } ; パフォーマンスの解放 release pPerformance pPerformance = 0 } if pLoader { ; ローダーの解放 release pLoader pLoader = 0 } end