📄 snd_dev_direct.cpp
字号:
if (!(dwStatus & DSBSTATUS_PLAYING))
pDSBufRR->Play(0, 0, DSBPLAY_LOOPING);
}
else if (pDSBuf)
{
if (pDSBuf->GetStatus (&dwStatus) != DS_OK)
Msg ("Couldn't get sound buffer status\n");
if (dwStatus & DSBSTATUS_BUFFERLOST)
pDSBuf->Restore ();
if (!(dwStatus & DSBSTATUS_PLAYING))
pDSBuf->Play(0, 0, DSBPLAY_LOOPING);
}
return endtime;
}
void CAudioDirectSound::PaintEnd( void )
{
}
void CAudioDirectSound::ClearBuffer( void )
{
int clear;
////////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD dwSizeFL, dwSizeFR, dwSizeRL, dwSizeRR;
char *pDataFL, *pDataFR, *pDataRL, *pDataRR;
if ( SURROUND_ON )
{
int SURROUNDreps;
HRESULT SURROUNDhresult;
SURROUNDreps = 0;
if ( !pDSBufFL && !pDSBufFR && !pDSBufRL && !pDSBufRR )
return;
while ((SURROUNDhresult = pDSBufFL->Lock(0, m_bufferSize/2, (void**)&pDataFL, &dwSizeFL, NULL, NULL, 0)) != DS_OK)
{
if (SURROUNDhresult != DSERR_BUFFERLOST)
{
Msg ("S_ClearBuffer: DS::Lock FL Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++SURROUNDreps > 10000)
{
Msg ("S_ClearBuffer: DS: couldn't restore FL buffer\n");
S_Shutdown ();
return;
}
}
SURROUNDreps = 0;
while ((SURROUNDhresult = pDSBufFR->Lock(0, m_bufferSize/2, (void**)&pDataFR, &dwSizeFR, NULL, NULL, 0)) != DS_OK)
{
if (SURROUNDhresult != DSERR_BUFFERLOST)
{
Msg ("S_ClearBuffer: DS::Lock FR Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++SURROUNDreps > 10000)
{
Msg ("S_ClearBuffer: DS: couldn't restore FR buffer\n");
S_Shutdown ();
return;
}
}
SURROUNDreps = 0;
while ((SURROUNDhresult = pDSBufRL->Lock(0, m_bufferSize/2, (void**)&pDataRL, &dwSizeRL, NULL, NULL, 0)) != DS_OK)
{
if (SURROUNDhresult != DSERR_BUFFERLOST)
{
Msg ("S_ClearBuffer: DS::Lock RL Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++SURROUNDreps > 10000)
{
Msg ("S_ClearBuffer: DS: couldn't restore RL buffer\n");
S_Shutdown ();
return;
}
}
SURROUNDreps = 0;
while ((SURROUNDhresult = pDSBufRR->Lock(0, m_bufferSize/2, (void**)&pDataRR, &dwSizeRR, NULL, NULL, 0)) != DS_OK)
{
if (SURROUNDhresult != DSERR_BUFFERLOST)
{
Msg ("S_ClearBuffer: DS::Lock RR Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++SURROUNDreps > 10000)
{
Msg ("S_ClearBuffer: DS: couldn't restore RR buffer\n");
S_Shutdown ();
return;
}
}
Q_memset(pDataFL, 0, m_bufferSize/2);
Q_memset(pDataFR, 0, m_bufferSize/2);
Q_memset(pDataRL, 0, m_bufferSize/2);
Q_memset(pDataRR, 0, m_bufferSize/2);
pDSBufFL->Unlock(pDataFL, dwSizeFL, NULL, 0);
pDSBufFR->Unlock(pDataFR, dwSizeFR, NULL, 0);
pDSBufRL->Unlock(pDataRL, dwSizeRL, NULL, 0);
pDSBufRR->Unlock(pDataRR, dwSizeRR, NULL, 0);
return;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if ( !pDSBuf )
return;
if ( DeviceSampleBits() == 8)
clear = 0x80;
else
clear = 0;
if (pDSBuf)
{
DWORD dwSize;
DWORD *pData;
int reps;
HRESULT hresult;
reps = 0;
while ((hresult = pDSBuf->Lock(0, m_bufferSize, (void**)&pData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
Msg ("S_ClearBuffer: DS::Lock Sound Buffer Failed\n");
S_Shutdown ();
return;
}
if (++reps > 10000)
{
Msg ("S_ClearBuffer: DS: couldn't restore buffer\n");
S_Shutdown ();
return;
}
}
Q_memset(pData, clear, DeviceSampleCount() * DeviceSampleBytes());
pDSBuf->Unlock(pData, dwSize, NULL, 0);
}
}
void CAudioDirectSound::StopAllSounds( void )
{
}
/*
==================
SNDDMA_InitDirect
Direct-Sound support
==================
*/
sndinitstat CAudioDirectSound::SNDDMA_InitDirect( void )
{
DSBUFFERDESC dsbuf;
DSBCAPS dsbcaps;
DWORD dwSize, dwWrite;
DSCAPS dscaps;
WAVEFORMATEX format, pformat;
HRESULT hresult;
int reps;
void *lpData = NULL;
qboolean primary_format_set;
// BUGBUG: Making 8 bit mono/stereo output has weird latency problems.
// UNDONE: Revisit and test this to make sure 8-bit devices will work.
m_deviceChannels = 2;
m_deviceSampleBits = 16;
m_deviceDmaSpeed = SOUND_DMA_SPEED; // 44k: hardware playback rate
memset (&format, 0, sizeof(format));
format.wFormatTag = WAVE_FORMAT_PCM;
format.nChannels = m_deviceChannels;
format.wBitsPerSample = m_deviceSampleBits;
format.nSamplesPerSec = m_deviceDmaSpeed;
format.nBlockAlign = format.nChannels
*format.wBitsPerSample / 8;
format.cbSize = 0;
format.nAvgBytesPerSec = format.nSamplesPerSec
*format.nBlockAlign;
if (!m_hInstDS)
{
m_hInstDS = LoadLibrary("dsound.dll");
if (m_hInstDS == NULL)
{
g_pSoundServices->ConSafePrint ("Couldn't load dsound.dll\n");
return SIS_FAILURE;
}
pDirectSoundCreate = (long (__stdcall *)(struct _GUID *,struct IDirectSound ** ,struct IUnknown *))GetProcAddress(m_hInstDS,"DirectSoundCreate");
if (!pDirectSoundCreate)
{
g_pSoundServices->ConSafePrint ("Couldn't get DS proc addr\n");
return SIS_FAILURE;
}
}
while ((hresult = iDirectSoundCreate(NULL, &pDS, NULL)) != DS_OK)
{
if (hresult != DSERR_ALLOCATED)
{
DevMsg ("DirectSound create failed\n");
return SIS_FAILURE;
}
#if 0
if (MessageBox (NULL,
"The sound hardware is in use by another app.\n\n"
"Select Retry to try to start sound again or Cancel to run Half-Life with no sound.",
"Sound not available",
MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
{
g_pSoundServices->ConSafePrint ("DirectSoundCreate failure\n"
" hardware already in use\n");
return SIS_NOTAVAIL;
}
#else
return SIS_NOTAVAIL;
#endif
}
dscaps.dwSize = sizeof(dscaps);
if (DS_OK != pDS->GetCaps (&dscaps))
{
g_pSoundServices->ConSafePrint ("Couldn't get DS caps\n");
}
if (dscaps.dwFlags & DSCAPS_EMULDRIVER)
{
g_pSoundServices->ConSafePrint ("No DirectSound driver installed\n");
Shutdown();
return SIS_FAILURE;
}
if (DS_OK != pDS->SetCooperativeLevel (*pmainwindow, DSSCL_EXCLUSIVE))
{
g_pSoundServices->ConSafePrint ("Set coop level failed\n");
Shutdown();
return SIS_FAILURE;
}
// get access to the primary buffer, if possible, so we can set the
// sound hardware format
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
dsbuf.dwBufferBytes = 0;
dsbuf.lpwfxFormat = NULL;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
primary_format_set = false;
if (!g_pSoundServices->CheckParm ("-snoforceformat"))
{
if (DS_OK == pDS->CreateSoundBuffer(&dsbuf, &pDSPBuf, NULL))
{
pformat = format;
if (DS_OK != pDSPBuf->SetFormat (&pformat))
{
if (snd_firsttime)
DevMsg ("Set primary sound buffer format: no\n");
}
else
{
if (snd_firsttime)
DevMsg ("Set primary sound buffer format: yes\n");
primary_format_set = true;
}
}
}
SURROUND_ON = FALSE;
if (s_surround.GetInt())
SURROUND_ON = SNDDMA_InitSurround(pDS, &format, &dsbcaps);
if ( !SURROUND_ON )
{
s_surround.SetValue( 0 );
if (!primary_format_set || !g_pSoundServices->CheckParm ("-primarysound"))
{
// create the secondary buffer we'll actually work with
memset (&dsbuf, 0, sizeof(dsbuf));
dsbuf.dwSize = sizeof(DSBUFFERDESC);
dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
dsbuf.lpwfxFormat = &format;
memset(&dsbcaps, 0, sizeof(dsbcaps));
dsbcaps.dwSize = sizeof(dsbcaps);
if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL))
{
g_pSoundServices->ConSafePrint ("DS:CreateSoundBuffer Failed");
Shutdown();
return SIS_FAILURE;
}
m_deviceChannels = format.nChannels;
m_deviceSampleBits = format.wBitsPerSample;
m_deviceDmaSpeed = format.nSamplesPerSec;
if (DS_OK != pDSBuf->GetCaps (&dsbcaps))
{
g_pSoundServices->ConSafePrint ("DS:GetCaps failed\n");
Shutdown();
return SIS_FAILURE;
}
if (snd_firsttime)
DevMsg ("Using secondary sound buffer\n");
}
else
{
if (DS_OK != pDS->SetCooperativeLevel (*pmainwindow, DSSCL_WRITEPRIMARY))
{
g_pSoundServices->ConSafePrint ("Set coop level failed\n");
Shutdown();
return SIS_FAILURE;
}
if (DS_OK != pDSPBuf->GetCaps (&dsbcaps))
{
Msg ("DS:GetCaps failed\n");
return SIS_FAILURE;
}
pDSBuf = pDSPBuf;
DevMsg ("Using primary sound buffer\n");
}
// Make sure mixer is active
pDSBuf->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 = dsbcaps.dwBufferBytes;
// initialize the buffer
reps = 0;
while ((hresult = pDSBuf->Lock(0, m_bufferSize, (void**)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK)
{
if (hresult != DSERR_BUFFERLOST)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n");
Shutdown();
return SIS_FAILURE;
}
if (++reps > 10000)
{
g_pSoundServices->ConSafePrint ("SNDDMA_InitDirect: DS: couldn't restore buffer\n");
Shutdown();
return SIS_FAILURE;
}
}
memset(lpData, 0, dwSize);
// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging
pDSBuf->Unlock(lpData, dwSize, NULL, 0);
/* we don't want anyone to access the buffer directly w/o locking it first. */
lpData = NULL;
pDSBuf->Stop();
pDSBuf->GetCurrentPosition(&m_mmstarttime.u.sample, &dwWrite);
pDSBuf->Play(0, 0, DSBPLAY_LOOPING);
}
m_deviceSampleCount = m_bufferSize/(DeviceSampleBytes());
// UNDONE: Do I need this?
//shm->buffer = (unsigned char *) lpData;
return SIS_SUCCESS;
}
/*
This routine is used to intercept SNDDMA_GetDMAPos. We need to return the total
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -