Platform SDK: DirectX |
ここでは、C++ でのアプリケーション開発について説明する。Visual Basic については、「DirectMusic Visual Basic チュートリアル」を参照すること。
Donuts.cpp ファイル内の InitializeGame 関数で DirectMusic パフォーマンスを設定する。
アプリケーションは最初に GetSearchPath 関数を呼び出すことにより、レジストリへのクエリを行って、DirectX のサンプル ミュージック ファイルの検索パスを取得する。その後、次のようにコンポーザ用とパフォーマンス用の COM オブジェクトを作成する。
CoInitialize(NULL); if ( !SUCCEEDED(::CoCreateInstance( CLSID_DirectMusicComposer, NULL, CLSCTX_INPROC, IID_IDirectMusicComposer, (void**)&gpComposer ))) { return CleanupAndExit("Couldn't create a composer object"); } if ( !SUCCEEDED( CoCreateInstance( CLSID_DirectMusicPerformance, NULL, CLSCTX_INPROC, IID_IDirectMusicPerformance, (void**)&gpPerformance ))) { return CleanupAndExit("Couldn't create a performance object"); }
続いて、このアプリケーションは IDirectMusicPerformance::Init を呼び出してパフォーマンスを初期化する。このメソッドは、ポートの作成とアクティブ化を行う DirectMusic オブジェクトを作成する。DirectSound がほかのサウンド エフェクトに使用されているかどうかに応じて、lpDS に渡してパフォーマンスに既存の DirectSound オブジェクトをアタッチするか、NULL を渡してオブジェクトを作成する。
#ifdef USE_DSOUND if( !SUCCEEDED(gpPerformance->Init(&gpDirectMusic, lpDS, hWndMain))) { return CleanupAndExit("Couldn't initialize the performance"); } #else if( !SUCCEEDED(gpPerformance->Init(&gpDirectMusic, NULL, hWndMain))) { return CleanupAndExit("Couldn't initialize the performance"); } #endif
アプリケーションはここでデフォルト ポートを取得し、1 つのチャンネル グループでポートのインスタンスを作成し、その能力を取得する。
IDirectMusicPort* pPort = NULL; DMUS_PORTPARAMS dmos; DMUS_PORTCAPS dmpc; GUID guidSynthGUID; HRESULT hr = S_OK; if ( !SUCCEEDED(gpDirectMusic->GetDefaultPort(&guidSynthGUID))) { return CleanupAndExit("Could't GetDefaultPort on IDirectMusic"); } ZeroMemory(&dmos, sizeof(dmos)); dmos.dwSize = sizeof(DMUS_PORTPARAMS); dmos.dwChannelGroups = 1; dmos.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS; if( !SUCCEEDED(gpDirectMusic->CreatePort(guidSynthGUID, &dmos, &pPort, NULL))) { return CleanupAndExit("Couldn't CreatePort on IDirectMusic"); } ZeroMemory(&dmpc, sizeof(dmpc)); dmpc.dwSize = sizeof(DMUS_PORTCAPS); if( !SUCCEEDED(pPort->GetCaps(&dmpc))) { if (pPort) pPort->Release(); return CleanupAndExit("Couldn't GetCaps on IDirectMusicPort"); }
ここで、_SOFTWARE_SYNTH_ が定義されているかどうかに応じて、アプリケーションの動作が変わる。_SOFTWARE_SYNTH_ が定義されている場合、DLS 機能を持つシンセサイザが要求され、アプリケーションはデフォルト ポートで DMUS_PC_DLS 能力フラグを確認する。フラグが見つからない場合は、デフォルト ポートを解放し、DMUS_PC_DLS 機能を持つ出力ポートが見つかるまで、利用可能なポートを列挙し続ける。最終的に、見つかったポートのインスタンスが作成される。
if ((dmpc.dwClass != DMUS_PC_OUTPUTCLASS) || !(dmpc.dwFlags & DMUS_PC_DLS)) { pPort->Release(); pPort = NULL; } if (!pPort) { for (DWORD index = 0; hr == S_OK; index++) { ZeroMemory(&dmpc, sizeof(dmpc)); dmpc.dwSize = sizeof(DMUS_PORTCAPS); hr = gpDirectMusic->EnumPort(index, &dmpc); if(hr == S_OK) { if ( (dmpc.dwClass == DMUS_PC_OUTPUTCLASS) && (dmpc.dwFlags & DMUS_PC_DLS) ) { CopyMemory(&guidSynthGUID, &dmpc.guidPort, sizeof(GUID)); ZeroMemory(&dmos, sizeof(dmos)); dmos.dwSize = sizeof(DMUS_PORTPARAMS); dmos.dwChannelGroups = 1; dmos.dwValidParams = DMUS_PORTPARAMS_CHANNELGROUPS; hr = gpDirectMusic->CreatePort(guidSynthGUID, &dmos, &pPort, NULL); break; } } } if (hr != S_OK) { if (pPort) pPort->Release(); return CleanupAndExit("Couldn't initialize the Synth port"); } }
一方、_SOFTWARE_SYNTH_ が定義されていない場合は、従来のハードウェア ポートが要求され、アプリケーションは MIDI マッパーが見つかるまで、ポートを列挙し続ける(ここでは、コードを示していない)。
次に、このポートをアクティブ化して、パフォーマンスに付加する。
pPort->Activate(TRUE); gpPerformance->AddPort(pPort);
次の呼び出しで、P チャンネル 0-15 がこのポート上の最初の MIDI チャンネル グループへマップされる。このステップは、アプリケーションが AddPort に NULL を渡していないために必要である点に注意すること。
gpPerformance->AssignPChannelBlock(0, pPort, 1);
この時点で、ポートへのオリジナル参照を解放できる。この呼び出しは、パフォーマンスからポートを削除することはない。
if (pPort) pPort->Release();