Platform SDK: DirectX

プライマリ バッファへのアクセス

[Visual Basic]

バッファ記述で DSBCAPS_PRIMARYBUFFER フラグを指定し、この記述を DirectSound.CreateSoundBuffer に渡すことにより、プライマリ バッファ オブジェクトを作成できる。このような処理を行う最も一般的な状況として、プライマリ バッファの DirectSoundBuffer.Play メソッドを呼び出し、短時間のサウンド中断の頻発を防止することが挙げられる。詳細については、「プライマリ バッファの連続再生」を参照すること。

DirectX for Visual Basic アプリケーションでは、プライマリ バッファへの書き込みアクセスの取得を試みないこと。

[C++]

セカンダリ バッファがサポートしていない特別なミキシングや他のエフェクトを必要とするアプリケーションに対して、DirectSound はプライマリ バッファへの直接アクセスを許可する。

プライマリ サウンド バッファへの書き込みアクセスを取得すると、DirectSound の他の機能は利用できなくなる。セカンダリ バッファのミキシングも行われないので、ハードウェア アクセラレーション ミキシングも利用できなくなる。

ほとんどのアプリケーションは、プライマリ バッファへ直接アクセスせずにセカンダリ バッファを使う。セカンダリ バッファへの書き込みは簡単に行える。より大きなバッファにより、次のデータ ブロックの書き込みまでの時間が長くなり、オーディオの音が途切れる危険が最小限に抑えられる。アプリケーションが必要とするオーディオが、ミキシングを必要としない 1 つのオーディオ ストリームのような単純なものであっても、セカンダリ バッファを使ってオーディオ データを再生することにより、より高い性能が実現できる。

プライマリ バッファのサイズは指定できず、バッファを作成した後に返されるサイズを受け入れなければならない。通常、プライマリ バッファは極めて小さく、もしアプリケーションがこのようなバッファに直接書き込む場合は短い間隔でデータ ブロックを書き込み、以前のデータがもう一度再生されることを防がなければならない。

DSBUFFERDESC 構造体に DSBCAPS_PRIMARYBUFFER フラグを指定し、この構造体を IDirectSound::CreateSoundBuffer メソッドに渡して、アクセス可能なプライマリ バッファを作成する。バッファに書き込みをしたい場合は、協調レベルは DSSCL_WRITEPRIMARY でなければならない。

プライマリ バッファがハードウェア上に存在していない限り、そのバッファの書き込みアクセスは取得できない。これに該当するかどうかを確認するには、IDirectSoundBuffer::GetCaps メソッドを呼び出して DSBCAPS 構造体の dwFlags メンバ内の SBCAPS_LOCHARDWARE フラグの有無をチェックする。ソフトウェアでエミュレートしたプライマリ バッファをロックしようとすると、呼び出しは失敗する。

プライマリ サウンド バッファは、ループして再生しなければならない。その目的で、DSBPLAY_LOOPING フラグが設定されていることを確認する。

次の例は、プライマリ バッファへの書き込みアクセスを取得する方法を示す。

BOOL AppCreateWritePrimaryBuffer( 
    LPDIRECTSOUND lpDirectSound, 
    LPDIRECTSOUNDBUFFER *lplpDsb, 
    LPDWORD lpdwBufferSize, 
    HWND hwnd) 
{ 
    DSBUFFERDESC dsbdesc; 
    DSBCAPS dsbcaps; 
    HRESULT hr; 
    WAVEFORMATEX wf;
 
    // ウェーブ フォーマット構造体を設定する。
    memset(&wf, 0, sizeof(WAVEFORMATEX)); 
    wf.wFormatTag = WAVE_FORMAT_PCM; 
    wf.nChannels = 2; 
    wf.nSamplesPerSec = 22050; 
    wf.nBlockAlign = 4; 
    wf.nAvgBytesPerSec = 
        wf.nSamplesPerSec * wf.nBlockAlign; 
    wf.wBitsPerSample = 16; 
 
    // DSBUFFERDESC 構造体を設定する。
    memset(&dsbdesc, 0, sizeof(DSBUFFERDESC));
    dsbdesc.dwSize = sizeof(DSBUFFERDESC); 
    dsbdesc.dwFlags = DSBCAPS_PRIMARYBUFFER; 
    // バッファサイズは、サウンド ハードウェアによって決まる。
    dsbdesc.dwBufferBytes = 0; 
    dsbdesc.lpwfxFormat = NULL; // プライマリ バッファでは NULL でなければならない。
 
    // 書き込み優先協調レベルを取得する。
    hr = lpDirectSound->lpVtbl->SetCooperativeLevel(lpDirectSound, 
        hwnd, DSSCL_WRITEPRIMARY); 
    if SUCCEEDED(hr) 
    { 
        // バッファの作成を試みる。
        hr = lpDirectSound->lpVtbl->CreateSoundBuffer(lpDirectSound, 
            &dsbdesc, lplpDsb, NULL); 
        if SUCCEEDED(hr) 
        { 
            // プライマリ バッファを希望のフォーマットに設定する。
            hr = (*lplpDsb)->lpVtbl->SetFormat(*lplpDsb, &wf); 
            if SUCCEEDED(hr) 
            { 
                // バッファのサイズを知りたい場合は GetCaps を呼び出す。
                    dsbcaps.dwSize = sizeof(DSBCAPS); 
                (*lplpDsb)->lpVtbl->GetCaps(*lplpDsb, &dsbcaps); 
                *lpdwBufferSize = dsbcaps.dwBufferBytes; 
                return TRUE; 
            } 
        } 
    } 
    // 失敗。
    *lplpDsb = NULL; 
    *lpdwBufferSize = 0; 
    return FALSE; 
} 
 

DSSCL_WRITEPRIMARY 以外の協調レベルを指定すると、書き込みアクセスがなくてもプライマリ バッファ オブジェクトを作成できる。このような処理を行う状況の 1 つとして、プライマリ バッファに対して IDirectSoundBuffer::Play メソッドを呼び出し、短時間のサウンド中断の頻発を防止することが挙げられる。詳細については、「プライマリ バッファの連続再生」および「カスタム ミキサー」を参照すること。