aboutsummaryrefslogtreecommitdiffstats
path: root/Alc/dsound.c
diff options
context:
space:
mode:
authorChris Robinson <[email protected]>2008-01-08 07:09:25 -0800
committerChris Robinson <[email protected]>2008-01-08 07:09:25 -0800
commit1e3ad2f9ce9dcb95c76ab1e16a317d50657bba09 (patch)
tree75f4a0ff24ddd1afb2a192dee2c2e3e0a0fda2a6 /Alc/dsound.c
parent9c97f07ec9e5e72a8bfebffe05b7de5ce439d7f6 (diff)
Use a more reliable thread loop for DSound, instead of a Win32 timer
Also use a simpler method for calculating the read/write location
Diffstat (limited to 'Alc/dsound.c')
-rw-r--r--Alc/dsound.c132
1 files changed, 64 insertions, 68 deletions
diff --git a/Alc/dsound.c b/Alc/dsound.c
index ddedaf21..d2708f0a 100644
--- a/Alc/dsound.c
+++ b/Alc/dsound.c
@@ -36,71 +36,74 @@ typedef struct {
LPDIRECTSOUND lpDS;
LPDIRECTSOUNDBUFFER DSpbuffer;
LPDIRECTSOUNDBUFFER DSsbuffer;
- MMRESULT ulDSTimerID;
- DWORD OldWriteCursor;
+
+ int killNow;
+ ALvoid *thread;
} DSoundData;
static ALCchar *DeviceList[16];
-static void CALLBACK DirectSoundProc(UINT uID,UINT uReserved,DWORD_PTR dwUser,DWORD_PTR dwReserved1,DWORD_PTR dwReserved2)
-{
- ALCdevice *pDevice = (ALCdevice *)dwUser;
- DSoundData *pData = pDevice->ExtraData;
- DWORD PlayCursor,WriteCursor;
- BYTE *WritePtr1,*WritePtr2;
- DWORD WriteCnt1,WriteCnt2;
- WAVEFORMATEX OutputType;
- DWORD BytesPlayed;
- DWORD BufSize;
- HRESULT DSRes;
- (void)uID;
- (void)uReserved;
- (void)dwReserved1;
- (void)dwReserved2;
+static ALuint DSoundProc(ALvoid *ptr)
+{
+ ALCdevice *pDevice = (ALCdevice*)ptr;
+ DSoundData *pData = (DSoundData*)pDevice->ExtraData;
+ DWORD LastCursor = 0;
+ DWORD PlayCursor;
+ VOID *WritePtr;
+ DWORD WriteCnt;
+ DWORD avail;
+ HRESULT err;
+
+ while(!pData->killNow)
+ {
+ // Get current play and write cursors
+ IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL);
+ avail = (PlayCursor-LastCursor) % (pDevice->UpdateFreq*pDevice->FrameSize);
- BufSize = pDevice->UpdateFreq * 2 * pDevice->FrameSize;
+ if(avail == 0)
+ {
+ Sleep(1);
+ continue;
+ }
- // Get current play and write cursors
- IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer,&PlayCursor,&WriteCursor);
- if (!pData->OldWriteCursor) pData->OldWriteCursor=WriteCursor-PlayCursor;
+ // Lock output buffer
+ WriteCnt = 0;
+ err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, &WritePtr, &WriteCnt, NULL, NULL, 0);
- // Get the output format and figure the number of bytes played (block aligned)
- IDirectSoundBuffer_GetFormat(pData->DSsbuffer,&OutputType,sizeof(WAVEFORMATEX),NULL);
- BytesPlayed=((((WriteCursor<pData->OldWriteCursor)?(BufSize+WriteCursor-pData->OldWriteCursor):(WriteCursor-pData->OldWriteCursor))/OutputType.nBlockAlign)*OutputType.nBlockAlign);
+ // If the buffer is lost, restore it, play and lock
+ if(err == DSERR_BUFFERLOST)
+ {
+ err = IDirectSoundBuffer_Restore(pData->DSsbuffer);
+ if(SUCCEEDED(err))
+ err = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
+ if(SUCCEEDED(err))
+ err = IDirectSoundBuffer_Lock(pData->DSsbuffer, LastCursor, avail, (LPVOID*)&WritePtr, &WriteCnt, NULL, NULL, 0);
+ }
- // Lock output buffer started at 40msec in front of the old write cursor (15msec in front of the actual write cursor)
- DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(pData->OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
+ // Successfully locked the output buffer
+ if(SUCCEEDED(err))
+ {
+ // If we have an active context, mix data directly into output buffer otherwise fill with silence
+ SuspendContext(NULL);
+ aluMixData(pDevice->Context, WritePtr, WriteCnt, pDevice->Format);
+ ProcessContext(NULL);
- // If the buffer is lost, restore it, play and lock
- if (DSRes==DSERR_BUFFERLOST)
- {
- IDirectSoundBuffer_Restore(pData->DSsbuffer);
- IDirectSoundBuffer_Play(pData->DSsbuffer,0,0,DSBPLAY_LOOPING);
- DSRes=IDirectSoundBuffer_Lock(pData->DSsbuffer,(pData->OldWriteCursor+(OutputType.nSamplesPerSec/25)*OutputType.nBlockAlign)%BufSize,BytesPlayed,(LPVOID*)&WritePtr1,&WriteCnt1,(LPVOID*)&WritePtr2,&WriteCnt2,0);
- }
+ // Unlock output buffer only when successfully locked
+ IDirectSoundBuffer_Unlock(pData->DSsbuffer, WritePtr, WriteCnt, NULL, 0);
+ }
+ else
+ AL_PRINT("Buffer lock error: %#lx\n", err);
- // Successfully locked the output buffer
- if (DSRes==DS_OK)
- {
- // If we have an active context, mix data directly into output buffer otherwise fill with silence
- SuspendContext(NULL);
- if (WritePtr1)
- aluMixData(pDevice->Context, WritePtr1, WriteCnt1, pDevice->Format);
- if (WritePtr2)
- aluMixData(pDevice->Context, WritePtr2, WriteCnt2, pDevice->Format);
- ProcessContext(NULL);
-
- // Unlock output buffer only when successfully locked
- IDirectSoundBuffer_Unlock(pData->DSsbuffer,WritePtr1,WriteCnt1,WritePtr2,WriteCnt2);
+ // Update old write cursor location
+ LastCursor += WriteCnt;
+ LastCursor %= pDevice->UpdateFreq*pDevice->FrameSize;
}
- // Update old write cursor location
- pData->OldWriteCursor=((pData->OldWriteCursor+BytesPlayed)%BufSize);
+ return 0;
}
-
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName)
{
DSBUFFERDESC DSBDescription;
@@ -169,7 +172,7 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
memset(&DSBDescription,0,sizeof(DSBUFFERDESC));
DSBDescription.dwSize=sizeof(DSBUFFERDESC);
DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2;
- DSBDescription.dwBufferBytes=device->UpdateFreq * 2 * device->FrameSize;
+ DSBDescription.dwBufferBytes=device->UpdateFreq * device->FrameSize;
DSBDescription.lpwfxFormat=&OutputType;
hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL);
}
@@ -177,6 +180,13 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
if(SUCCEEDED(hr))
hr = IDirectSoundBuffer_Play(pData->DSsbuffer, 0, 0, DSBPLAY_LOOPING);
+ device->MaxNoOfSources = 256;
+ device->ExtraData = pData;
+
+ pData->thread = StartThread(DSoundProc, device);
+ if(!pData->thread)
+ hr = E_FAIL;
+
if(FAILED(hr))
{
if (pData->DSsbuffer)
@@ -190,10 +200,6 @@ static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceNam
return ALC_FALSE;
}
- pData->ulDSTimerID = timeSetEvent(25, 0, (LPTIMECALLBACK)DirectSoundProc, (DWORD)device, (UINT)TIME_CALLBACK_FUNCTION|TIME_PERIODIC);
- device->MaxNoOfSources = 256;
-
- device->ExtraData = pData;
return ALC_TRUE;
}
@@ -201,26 +207,16 @@ static void DSoundClosePlayback(ALCdevice *device)
{
DSoundData *pData = device->ExtraData;
- // Stop and release the DS timer
- if (pData->ulDSTimerID)
- timeKillEvent(pData->ulDSTimerID);
+ pData->killNow = 1;
+ StopThread(pData->thread);
- // Wait ... just in case any timer events happen
- Sleep(100);
-
- SuspendContext(NULL);
-
- if (pData->DSsbuffer)
- IDirectSoundBuffer_Release(pData->DSsbuffer);
- if (pData->DSpbuffer)
- IDirectSoundBuffer_Release(pData->DSpbuffer);
+ IDirectSoundBuffer_Release(pData->DSsbuffer);
+ IDirectSoundBuffer_Release(pData->DSpbuffer);
IDirectSound_Release(pData->lpDS);
//Deinit COM
CoUninitialize();
- ProcessContext(NULL);
-
free(pData);
device->ExtraData = NULL;
}