Platform SDK: DirectX

カスタム ミキサー

[Visual Basic]

ここでは、C++ でのアプリケーション開発について説明する。

[C++]

ほとんどのアプリケーションは DirectSound ミキサーを使用する。このミキサーはほぼすべてのミキシングの要求を満たし、利用可能なすべてのハードウェア アクセラレーションを自動的に活用する。しかし、DirectSound が提供しない機能をアプリケーションが必要とする場合は、プライマリ サウンド バッファへの書き込みアクセスを取得し、そこでストリームを直接ミキシングできる。

カスタム ミキサーを実装するには、アプリケーションは最初に DSSCL_WRITEPRIMARY 協調レベルを設定し、プライマリ サウンド バッファを作成しなければならない。(「プライマリ バッファへのアクセス」を参照。)次にバッファをロックし、データを書き込み、バッファをアンロックし、他のバッファと同じように再生する。ただし、DSBPLAY_LOOPING フラグを指定しなければならない。さもないと IDirectSoundBuffer::Play の呼び出しが失敗する点に注意すること。

次の例は、アプリケーションがカスタム ミキサーを実装する方法を示す。サウンド デバイスがデータ ブロックの再生を繰り返さないよう、AppMixIntoPrimaryBuffer 関数を一定の間隔で呼び出さなければならない。CustomMixer 関数はアプリケーションが定義した関数であり、アプリケーションが定義した AppStreamInfo 構造体の指定に従って複数のストリームをミキシングし、結果を指定のポインタに書き込む。

BOOL AppMixIntoPrimaryBuffer( 
        LPAPPSTREAMINFO lpAppStreamInfo, 
        LPDIRECTSOUNDBUFFER lpDsbPrimary, 
        DWORD dwDataBytes, 
        DWORD dwOldPos, 
        LPDWORD lpdwNewPos) 
{ 
    LPVOID lpvPtr1; 
    DWORD dwBytes1; 
    LPVOID lpvPtr2; 
    DWORD dwBytes2; 
    HRESULT hr; 
    // 書き込みポインタを取得する。
    hr = lpDsbPrimary->lpVtbl->Lock(lpDsbPrimary, 
                                    dwOldPos, dwDataBytes, 
                                    &lpvPtr1, &dwBytes1, 
                                    &lpvPtr2, &dwBytes2, 0); 
    // DSERR_BUFFERLOST が返された場合、復元とロックの再試行を行う。
    if (DSERR_BUFFERLOST == hr) 
    { 
        lpDsbPrimary->lpVtbl->Restore(lpDsbPrimary); 
        hr = lpDsbPrimary->lpVtbl->Lock(lpDsbPrimary, 
                                        dwOldPos, dwDataBytes,
                                        &lpvPtr1, &dwBytes1, 
                                        &lpvPtr2, &dwBytes2, 0); 
    } 
    if SUCCEEDED(hr) 
    { 
        // データをミキシングして、返されたポインタに書き込む。
        CustomMixer(lpAppStreamInfo, lpvPtr1, dwBytes1); 
        *lpdwNewPos = dwOldPos + dwBytes1; 
        if (NULL != lpvPtr2) 
        { 
            CustomMixer(lpAppStreamInfo, lpvPtr2, dwBytes2); 
            *lpdwNewPos = dwBytes2; // ラップ アラウンドした (先頭へ戻った) ため。
        } 
        // データを解放して DirectSound へ返す。
        hr = lpDsbPrimary->lpVtbl->Unlock(lpDsbPrimary, 
                                          lpvPtr1, dwBytes1, 
                                          lpvPtr2, dwBytes2); 
        if SUCCEEDED(hr) 
        { 
            return TRUE; 
        } 
    } 
    // ロックまたはアンロックが失敗した。
    return FALSE; 
}