From 7cd6327969a6813cbd666ac1e69375082e3e4b47 Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Thu, 21 Jul 2011 02:48:09 -0700 Subject: Use DSound notifications to wake up the mixer thread --- Alc/ALc.c | 2 ++ Alc/dsound.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/Alc/ALc.c b/Alc/ALc.c index 905fee22..9423ebc3 100644 --- a/Alc/ALc.c +++ b/Alc/ALc.c @@ -32,6 +32,8 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); +DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16); + DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); DEFINE_GUID(IID_IMMDeviceEnumerator, 0xa95664d2, 0x9614, 0x4f35, 0xa7,0x46, 0xde,0x8d,0xb6,0x36,0x17,0xe6); DEFINE_GUID(IID_IAudioClient, 0x1cb9ad4c, 0xdbfa, 0x4c32, 0xb1,0x78, 0xc2,0xf5,0x68,0xa7,0x03,0xb2); diff --git a/Alc/dsound.c b/Alc/dsound.c index 5f3c8e3c..7373584c 100644 --- a/Alc/dsound.c +++ b/Alc/dsound.c @@ -61,6 +61,8 @@ typedef struct { LPDIRECTSOUND lpDS; LPDIRECTSOUNDBUFFER DSpbuffer; LPDIRECTSOUNDBUFFER DSsbuffer; + LPDIRECTSOUNDNOTIFY DSnotify; + HANDLE hNotifyEvent; volatile int killNow; ALvoid *thread; @@ -76,6 +78,7 @@ static const ALCchar dsDevice[] = "DirectSound Default"; static DevMap *DeviceList; static ALuint NumDevices; +#define MAX_UPDATES 128 static void *DSoundLoad(void) { @@ -196,7 +199,7 @@ static ALuint DSoundProc(ALvoid *ptr) IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &LastCursor, NULL); while(!pData->killNow) { - // Get current play and write cursors + // Get current play cursor IDirectSoundBuffer_GetCurrentPosition(pData->DSsbuffer, &PlayCursor, NULL); avail = (PlayCursor-LastCursor+DSBCaps.dwBufferBytes) % DSBCaps.dwBufferBytes; @@ -213,7 +216,10 @@ static ALuint DSoundProc(ALvoid *ptr) } Playing = TRUE; } - Sleep(1); + + avail = WaitForSingleObjectEx(pData->hNotifyEvent, 2000, FALSE); + if(avail != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); continue; } avail -= avail%FragSize; @@ -461,29 +467,67 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device) if(SUCCEEDED(hr)) { + if(device->NumUpdates > MAX_UPDATES) + { + device->UpdateSize = ((ALuint64)device->UpdateSize*MAX_UPDATES + + device->NumUpdates-1) / device->NumUpdates; + device->NumUpdates = MAX_UPDATES; + } + memset(&DSBDescription,0,sizeof(DSBUFFERDESC)); DSBDescription.dwSize=sizeof(DSBUFFERDESC); - DSBDescription.dwFlags=DSBCAPS_GLOBALFOCUS|DSBCAPS_GETCURRENTPOSITION2; + DSBDescription.dwFlags=DSBCAPS_CTRLPOSITIONNOTIFY|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_GLOBALFOCUS; DSBDescription.dwBufferBytes=device->UpdateSize * device->NumUpdates * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat=&OutputType.Format; hr = IDirectSound_CreateSoundBuffer(pData->lpDS, &DSBDescription, &pData->DSsbuffer, NULL); } + if(SUCCEEDED(hr)) + { + hr = IDirectSoundBuffer_QueryInterface(pData->DSsbuffer, &IID_IDirectSoundNotify, (LPVOID *)&pData->DSnotify); + if(SUCCEEDED(hr)) + { + pData->hNotifyEvent = CreateEvent(NULL, FALSE, TRUE, NULL); + if(pData->hNotifyEvent == NULL) + hr = E_FAIL; + else + { + DSBPOSITIONNOTIFY notifies[MAX_UPDATES]; + ALuint i; + + for(i = 0;i < device->NumUpdates;++i) + { + notifies[i].dwOffset = i * device->UpdateSize * + OutputType.Format.nBlockAlign; + notifies[i].hEventNotify = pData->hNotifyEvent; + } + if(IDirectSoundNotify_SetNotificationPositions(pData->DSnotify, device->NumUpdates, notifies) != DS_OK) + hr = E_FAIL; + } + } + } + if(SUCCEEDED(hr)) { SetDefaultWFXChannelOrder(device); pData->thread = StartThread(DSoundProc, device); - if(!pData->thread) + if(pData->thread == NULL) hr = E_FAIL; } if(FAILED(hr)) { - if (pData->DSsbuffer) + if(pData->hNotifyEvent != NULL) + CloseHandle(pData->hNotifyEvent); + pData->hNotifyEvent = NULL; + if(pData->DSnotify != NULL) + IDirectSoundNotify_Release(pData->DSnotify); + pData->DSnotify = NULL; + if(pData->DSsbuffer != NULL) IDirectSoundBuffer_Release(pData->DSsbuffer); pData->DSsbuffer = NULL; - if (pData->DSpbuffer) + if(pData->DSpbuffer != NULL) IDirectSoundBuffer_Release(pData->DSpbuffer); pData->DSpbuffer = NULL; return ALC_FALSE; @@ -505,9 +549,13 @@ static void DSoundStopPlayback(ALCdevice *device) pData->killNow = 0; + CloseHandle(pData->hNotifyEvent); + pData->hNotifyEvent = NULL; + IDirectSoundNotify_Release(pData->DSnotify); + pData->DSnotify = NULL; IDirectSoundBuffer_Release(pData->DSsbuffer); pData->DSsbuffer = NULL; - if (pData->DSpbuffer) + if(pData->DSpbuffer != NULL) IDirectSoundBuffer_Release(pData->DSpbuffer); pData->DSpbuffer = NULL; } -- cgit v1.2.3