📄 snd_dev_direct.cpp
字号:
number based on both buffers so the rest of the framework behaves the same.
*/
int CAudioDirectSound::GetOutputPositionSurround()
{
DWORD dwPos;
DWORD dwRtn;
pDSBufFL->GetCurrentPosition(&dwPos, NULL);
// Causing problems on some EAX cards
#if 0
pDSBufFR->SetCurrentPosition(dwPos);
pDSBufRL->SetCurrentPosition(dwPos);
pDSBufRR->SetCurrentPosition(dwPos);
#endif
dwPos -= dwSurroundStart;
dwRtn = dwPos << 1;
dwRtn >>= SAMPLE_16BIT_SHIFT;
dwRtn &= DeviceSampleCount() - 1;
return (int)dwRtn;
}
/*
Release all Surround buffer pointers
*/
void ReleaseSurround(void)
{
if ( pDSPropSetFL != NULL ) pDSPropSetFL->Release();
pDSPropSetFL = NULL;
if ( pDSPropSetFR != NULL ) pDSPropSetFR->Release();
pDSPropSetFR = NULL;
if ( pDSPropSetRL != NULL ) pDSPropSetRL->Release();
pDSPropSetRL = NULL;
if ( pDSPropSetRR != NULL ) pDSPropSetRR->Release();
pDSPropSetRR = NULL;
if ( pDSBuf3DFL != NULL ) pDSBuf3DFL->Release();
pDSBuf3DFL = NULL;
if ( pDSBuf3DFR != NULL ) pDSBuf3DFR->Release();
pDSBuf3DFR = NULL;
if ( pDSBuf3DRL != NULL ) pDSBuf3DRL->Release();
pDSBuf3DRL = NULL;
if ( pDSBuf3DRR != NULL ) pDSBuf3DRR->Release();
pDSBuf3DRR = NULL;
if ( pDSBufFL != NULL ) pDSBufFL->Release();
pDSBufFL = NULL;
if ( pDSBufFR != NULL ) pDSBufFR->Release();
pDSBufFR = NULL;
if ( pDSBufRL != NULL ) pDSBufRL->Release();
pDSBufRL = NULL;
if ( pDSBufRR != NULL ) pDSBufRR->Release();
pDSBufRR = NULL;
}
// Initialization for Surround sound support (4 channel).
// Creates 4 mono 3D buffers to be used as Front Left, Front Right, Rear Left, Rear Right
bool CAudioDirectSound::SNDDMA_InitSurround(LPDIRECTSOUND lpDS, WAVEFORMATEX* lpFormat, DSBCAPS* lpdsbc)
{
DSBUFFERDESC dsbuf;
WAVEFORMATEX wvex;
DWORD dwSize, dwWrite;
int reps;
HRESULT hresult;
void *lpData = NULL;
if ( lpDS == NULL ) return FALSE;
// Force format to mono channel
memcpy(&wvex, lpFormat, sizeof(WAVEFORMATEX));
wvex.nChannels = 1;
wvex.nBlockAlign = wvex.nChannels * wvex.wBitsPerSample / 8;
wvex.nAvgBytesPerSec = wvex.nSamplesPerSec * wvex.nBlockAlign;
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
// LOCHARDWARE causes SB AWE64 to crash in it's DSOUND driver
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY|DSBCAPS_CTRL3D;//|DSBCAPS_LOCHARDWARE;
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE/2;
dsbuf.lpwfxFormat = &wvex;
// create 4 mono buffers FL, FR, RL, RR
if (DS_OK != lpDS->CreateSoundBuffer(&dsbuf, &pDSBufFL, NULL))
{
g_pSoundServices->ConSafePrint ("DS:CreateSoundBuffer for 3d front left failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != lpDS->CreateSoundBuffer(&dsbuf, &pDSBufFR, NULL))
{
g_pSoundServices->ConSafePrint ("DS:CreateSoundBuffer for 3d front right failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != lpDS->CreateSoundBuffer(&dsbuf, &pDSBufRL, NULL))
{
g_pSoundServices->ConSafePrint ("DS:CreateSoundBuffer for 3d rear left failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != lpDS->CreateSoundBuffer(&dsbuf, &pDSBufRR, NULL))
{
g_pSoundServices->ConSafePrint ("DS:CreateSoundBuffer for 3d rear right failed");
ReleaseSurround();
return FALSE;
}
// Try to get 4 3D buffers from the mono DS buffers
if (DS_OK != pDSBufFL->QueryInterface(IID_IDirectSound3DBufferDef, (void**)&pDSBuf3DFL))
{
g_pSoundServices->ConSafePrint ("DS:Query 3DBuffer for 3d front left failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != pDSBufFR->QueryInterface(IID_IDirectSound3DBufferDef, (void**)&pDSBuf3DFR))
{
g_pSoundServices->ConSafePrint ("DS:Query 3DBuffer for 3d front right failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != pDSBufRL->QueryInterface(IID_IDirectSound3DBufferDef, (void**)&pDSBuf3DRL))
{
g_pSoundServices->ConSafePrint ("DS:Query 3DBuffer for 3d rear left failed");
ReleaseSurround();
return FALSE;
}
if (DS_OK != pDSBufRR->QueryInterface(IID_IDirectSound3DBufferDef, (void**)&pDSBuf3DRR))
{
g_pSoundServices->ConSafePrint ("DS:Query 3DBuffer for 3d rear right failed");
ReleaseSurround();
return FALSE;
}
// UNDONE: set speaker configuration to 2, 4 or headphone
//lpDS->lpVtbl->SetSpeakerConfig(lpDS, DSSPEAKER_QUAD);
// Position the 4 3D buffers to FL, FR, RL, RR
pDSBuf3DFL->SetPosition(-1.0f, 0.0f, 1.0f, DS3D_IMMEDIATE);
pDSBuf3DFR->SetPosition(1.0f, 0.0f, 1.0f, DS3D_IMMEDIATE);
pDSBuf3DRL->SetPosition(-1.0f, 0.0f, -1.0f, DS3D_IMMEDIATE);
pDSBuf3DRR->SetPosition(1.0f, 0.0f, -1.0f, DS3D_IMMEDIATE);
#if 0
// try to get EAX fx on the 4 buffers (unused)
ULONG ulAnswer;
ulAnswer = 0;
if ( (pDSBufFL->QueryInterface(IID_IKsPropertySetDef, (LPVOID *)&pDSPropSetFL)) == DS_OK )
{
if ( (pDSPropSetFL->QuerySupport(DSPROPSETID_EAX_ReverbPropertiesDef, DSPROPERTY_EAX_ALL, &ulAnswer)) == DS_OK )
{
if ( (ulAnswer & KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) != (KSPROPERTY_SUPPORT_SET|KSPROPERTY_SUPPORT_GET) )
{
g_pSoundServices->ConSafePrint ("The current device is not EAX capable.");
ReleaseSurround();
return FALSE;
}
}
else
{
g_pSoundServices->ConSafePrint ("EAX:QuerySupport for DSPROPSETID_EAX_ReverbProperties Failed\n");
ReleaseSurround();
return FALSE;
}
}
else
{
g_pSoundServices->ConSafePrint ("EAX:QueryInterface for IID_IKsPropertySet FL Failed");
ReleaseSurround();
return FALSE;
}
if ( (pDSBufFR->QueryInterface(IID_IKsPropertySetDef, (LPVOID *)&pDSPropSetFR)) != DS_OK )
{
g_pSoundServices->ConSafePrint ("EAX:QueryInterface for IID_IKsPropertySet FR Failed");
ReleaseSurround();
return FALSE;
}
if ( (pDSBufRL->QueryInterface(IID_IKsPropertySetDef, (LPVOID *)&pDSPropSetRL)) != DS_OK )
{
g_pSoundServices->ConSafePrint ("EAX:QueryInterface for IID_IKsPropertySet RL Failed");
ReleaseSurround();
return FALSE;
}
if ( (pDSBufRR->QueryInterface(IID_IKsPropertySetDef, (LPVOID *)&pDSPropSetRR)) != DS_OK )
{
g_pSoundServices->ConSafePrint ("EAX:QueryInterface for IID_IKsPropertySet RR Failed");
ReleaseSurround();
return FALSE;
}
#endif // 0
m_deviceChannels = lpFormat->nChannels;
m_deviceSampleBits = lpFormat->wBitsPerSample;
m_deviceDmaSpeed = lpFormat->nSamplesPerSec;
memset(lpdsbc, 0, sizeof(DSBCAPS));
lpdsbc->dwSize = sizeof(DSBCAPS);
if (DS_OK != pDSBufFL->GetCaps (lpdsbc))
{
g_pSoundServices->ConSafePrint ("DS:GetCaps failed for 3d sound buffer\n");
ReleaseSurround();
return FALSE;
}
pDSBufFL->Play(0, 0, DSBPLAY_LOOPING);
pDSBufFR->Play(0, 0, DSBPLAY_LOOPING);
if (snd_firsttime)
DevMsg(" %d channel(s)\n"
" %d bits/sample\n"
" %d samples/sec\n",
DeviceChannels(), DeviceSampleBits(), DeviceDmaSpeed());
m_bufferSize = lpdsbc->dwBufferBytes*2;
// Test everything just like in the normal initialization.
reps = 0;
while ((hresult = pDSBufFL->Lock(0, lpdsbc->dwBufferBytes, (void**)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitSurround: DS::Lock Sound Buffer Failed for 3d FL\n");
ReleaseSurround();
return FALSE;
}
if (++reps > 10000)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitSurround: DS: couldn't restore buffer for 3d FL\n");
ReleaseSurround();
return FALSE;
}
}
memset(lpData, 0, dwSize);
pDSBufFL->Unlock(lpData, dwSize, NULL, 0);
reps = 0;
while ((hresult = pDSBufFR->Lock(0, lpdsbc->dwBufferBytes, (void**)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitSurround: DS::Lock Sound Buffer Failed for 3d FR\n");
ReleaseSurround();
return FALSE;
}
if (++reps > 10000)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitSurround: DS: couldn't restore buffer for FR\n");
ReleaseSurround();
return FALSE;
}
}
memset(lpData, 0, dwSize);
pDSBufFR->Unlock(lpData, dwSize, NULL, 0);
reps = 0;
while ((hresult = pDSBufRL->Lock(0, lpdsbc->dwBufferBytes, (void**)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed for RL\n");
ReleaseSurround();
return FALSE;
}
if (++reps > 10000)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS: couldn't restore buffer for RL\n");
ReleaseSurround();
return FALSE;
}
}
memset(lpData, 0, dwSize);
pDSBufRL->Unlock(lpData, dwSize, NULL, 0);
reps = 0;
while ((hresult = pDSBufRR->Lock(0, lpdsbc->dwBufferBytes, (void**)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed for RR\n");
ReleaseSurround();
return FALSE;
}
if (++reps > 10000)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS: couldn't restore buffer for RR\n");
ReleaseSurround();
return FALSE;
}
}
memset(lpData, 0, dwSize);
pDSBufRR->Unlock(lpData, dwSize, NULL, 0);
lpData = NULL; // this is invalid now
// OK Stop and get our positions and were good to go.
pDSBufFL->Stop();
pDSBufFR->Stop();
pDSBufRL->Stop();
pDSBufRR->Stop();
pDSBufFL->GetCurrentPosition(&dwSurroundStart, &dwWrite);
pDSBufFR->SetCurrentPosition(dwSurroundStart);
pDSBufRL->SetCurrentPosition(dwSurroundStart);
pDSBufRR->SetCurrentPosition(dwSurroundStart);
pDSBufFL->Play(0, 0, DSBPLAY_LOOPING);
pDSBufFR->Play(0, 0, DSBPLAY_LOOPING);
pDSBufRL->Play(0, 0, DSBPLAY_LOOPING);
pDSBufRR->Play(0, 0, DSBPLAY_LOOPING);
if (snd_firsttime)
g_pSoundServices->ConSafePrint ("3d surround sound initialization successful\n");
return TRUE;
}
void CAudioDirectSound::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
{
VectorCopy( forward, m_listenerForward );
}
void CAudioDirectSound::MixBegin( int sampleCount )
{
MIX_ClearAllPaintBuffers( sampleCount, false );
}
void CAudioDirectSound::MixUpsample( int sampleCount, int filtertype )
{
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
int ifilter = ppaint->ifilter;
Assert (ifilter < CPAINTFILTERS);
S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
S_MixBufferUpsample2x( sampleCount, ppaint->pbufrear, &(ppaint->fltmemrear[ifilter][0]), CPAINTFILTERMEM, filtertype );
}
// make sure on next upsample pass for this paintbuffer, new filter memory is used
ppaint->ifilter++;
}
// UNDONE: Implement fast 3D mixing routines instead of doing 2D mix times 2 ??
void CAudioDirectSound::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES]; // fl, fr, rl, rr
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1);
Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount);
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix8MonoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
}
}
void CAudioDirectSound::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 );
Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
if ( ppaint->fsurround )
{
Assert( ppaint->pbufrear );
Mix8StereoWavtype( pChannel, ppaint->pbufrear + outputOffset, &volume[IREAR_LEFT], (byte *)pData, inputOffset, rateScaleFix, outCount );
}
}
void CAudioDirectSound::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
{
int volume[CCHANVOLUMES];
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -