DirectX Audio でサウンド再生してみる

DirectX Audio

今回は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によって自動的に行なわれるので、アプリケーション側の作業が楽になっています。

また、オーディオパスの導入など、以前のバージョンにはなかったさまざまな新機能が提供されています。

新しいDirectMusicで使用されるインターフェース

DirectX Audioとなってからの新しいDirectMusicでも、以前のDirectMusicで使用されていたオブジェクト(ローダー、セグメントなど)が使われますが、インターフェースは以前のものの拡張版のインターフェースを使用します。ここで使用されるインターフェースは、以前のインターフェース名に『8』がつけられています。たとえば、以前のDirectMusicで使用されていたインターフェースの拡張として IDirectMusicPerformance8IDirectMusicSegment8IDirectMusicLoader8 などが使われます。(DirectX 8.0で使用されるインターフェースの多くは、新しく追加されたインターフェースも含め、基本となるインターフェース名に『8』がつけられた名前になっています。)

オーディオパスについて

新しく追加されたオブジェクトクラスとして、オーディオパスというものがあります。オーディオパスとは、パフォーマンスにおける再生から、実際に出力されるまでの、サウンドデータの流れを管理するオブジェクトのことです。

アプリケーションは複数のオーディオパスを作成することができ、例えば、リバーブが設定されたバッファで再生するオーディパスや、3Dサウンドコントロールが設定されたバッファで再生するオーディオパスをアプリケーションで作成し、それぞれのオーディオパスを指定することによって、それぞれの効果(リバーブや3Dサウンド)が得られます。また、オーディオパスごとにボリュームの設定を行なうことができるので、例えば、効果音のボリュームはそのままでBGMをフェードアウト・フェードインさせるなどということもできます。

サウンド再生の手順

では、実際にサウンドファイルを再生させてみることにします。再生できるサウンドはウェーブファイルおよびMIDIファイル(SMF)で、今回は、同時に再生できるサウンドは1つのみです。手順は以下のようになります。

  1. パフォーマンスオブジェクトを作成して IDirectMusicPerformance8 インターフェースを取得し、 IDirectMusicPerformance8::InitAudio メソッドで初期化する。

  2. ローダーオブジェクトを作成して IDirectMusicLoader8 インターフェースを取得する。

  3. IDirectMusicLoader8::LoadObjectFromFile メソッドでファイルからセグメントオブジェクトを作成し、 IDirectMusicSegment8 インターフェースを取得する。

  4. IDirectMusicSegment8::Download メソッドで、音色などの、セグメントのバンドデータをパフォーマンスにダウンロードする。

  5. IDirectMusicPerformance8::PlaySegmentEx メソッドでセグメントを再生する。

  6. 演奏を停止させる場合には IDirectMusicPerformance8::StopEx メソッドを呼び出す。

  7. IDirectMusicSegment8::Unload メソッドで音色データをアンロードする。

  8. IDirectMusicPerformance8::CloseDown メソッドでパフォーマンスオブジェクトをクローズする。

  9. IDirectMusicSegment8IDirectMusicLoader8IDirectMusicPerformance8 インターフェースの 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
);

ppDirectMusicppDirectSoundhwnd については、 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) を指定しておきます。dwFlagsi64StartTimeppSegmentState については、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

サンプルスクリプト

定義用スクリプトファイル def.as

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