X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=snd_win.c;h=8d4f00d272c5b91d004c7ce14169fc0af5209110;hb=71101f6373b765b5680dd3009431e65291ed2c49;hp=1fb72b99808199d83b3657f02cc0b20befc99df4;hpb=4d162c39ec059b7f3191fbb4fb18304bc9b1db59;p=xonotic%2Fdarkplaces.git diff --git a/snd_win.c b/snd_win.c index 1fb72b99..8d4f00d2 100644 --- a/snd_win.c +++ b/snd_win.c @@ -8,7 +8,7 @@ of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. @@ -18,34 +18,42 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "quakedef.h" -#include "winquake.h" +#include "snd_main.h" +#include +#include + +extern HWND mainwindow; #define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c) HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter); -// 64K is > 1 second at 16-bit, 22050 Hz +// Wave output: 64KB in 64 buffers of 1KB +// (64KB is > 1 sec at 16-bit 22050 Hz mono, and is 1/3 sec at 16-bit 44100 Hz stereo) #define WAV_BUFFERS 64 -#define WAV_MASK 0x3F -#define WAV_BUFFER_SIZE 0x0400 -#define SECONDARY_BUFFER_SIZE 0x10000 +#define WAV_MASK (WAV_BUFFERS - 1) +#define WAV_BUFFER_SIZE 1024 + +// DirectSound output: 64KB in 1 buffer +#define SECONDARY_BUFFER_SIZE (64 * 1024) typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat; static qboolean wavonly; static qboolean dsound_init; static qboolean wav_init; -static qboolean snd_firsttime = true, snd_isdirect, snd_iswave; static qboolean primary_format_set; -static int sample16; static int snd_sent, snd_completed; +static int prev_painted; +static unsigned int paintpot; -/* - * Global variables. Must be visible to window-procedure function - * so it can unlock and free the data block after it has been played. - */ + +/* + * Global variables. Must be visible to window-procedure function + * so it can unlock and free the data block after it has been played. + */ HANDLE hData; HPSTR lpData, lpData2; @@ -53,13 +61,13 @@ HPSTR lpData, lpData2; HGLOBAL hWaveHdr; LPWAVEHDR lpWaveHdr; -HWAVEOUT hWaveOut; +HWAVEOUT hWaveOut; WAVEOUTCAPS wavecaps; DWORD gSndBufSize; -MMTIME mmstarttime; +DWORD dwStartTime; LPDIRECTSOUND pDS; LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; @@ -76,16 +84,13 @@ S_BlockSound */ void S_BlockSound (void) { - -// DirectSound takes care of blocking itself - if (snd_iswave) + // DirectSound takes care of blocking itself + if (wav_init) { snd_blocked++; if (snd_blocked == 1) - { waveOutReset (hWaveOut); - } } } @@ -97,12 +102,9 @@ S_UnblockSound */ void S_UnblockSound (void) { - -// DirectSound takes care of blocking itself - if (snd_iswave) - { + // DirectSound takes care of blocking itself + if (wav_init) snd_blocked--; - } } @@ -121,7 +123,7 @@ void FreeSound (void) pDSBuf->lpVtbl->Release(pDSBuf); } -// only release primary buffer if it's not also the mixing buffer we just released + // only release primary buffer if it's not also the mixing buffer we just released if (pDSPBuf && (pDSBuf != pDSPBuf)) { pDSPBuf->lpVtbl->Release(pDSPBuf); @@ -147,7 +149,7 @@ void FreeSound (void) if (hWaveHdr) { - GlobalUnlock(hWaveHdr); + GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } @@ -183,41 +185,39 @@ sndinitstat SNDDMA_InitDirect (void) { DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; - DWORD dwSize, dwWrite; + DWORD dwSize; DSCAPS dscaps; - WAVEFORMATEX format, pformat; + WAVEFORMATEX format, pformat; HRESULT hresult; int reps; int i; - memset ((void *)&sn, 0, sizeof (sn)); - - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - i = COM_CheckParm ("-sndspeed"); // LordHavoc: -sndspeed option + memset((void *)shm, 0, sizeof(*shm)); + shm->format.channels = 2; + shm->format.width = 2; +// COMMANDLINEOPTION: Windows Sound: -sndspeed chooses 44100 hz, 22100 hz, or 11025 hz sound output rate + i = COM_CheckParm ("-sndspeed"); if (i && i != (com_argc - 1)) - shm->speed = atoi(com_argv[i+1]); + shm->format.speed = atoi(com_argv[i+1]); else - shm->speed = 11025; + shm->format.speed = 44100; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->speed; + format.nChannels = shm->format.channels; + format.wBitsPerSample = shm->format.width * 8; + format.nSamplesPerSec = shm->format.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; if (!hInstDS) { hInstDS = LoadLibrary("dsound.dll"); - + if (hInstDS == NULL) { - Con_SafePrintf ("Couldn't load dsound.dll\n"); + Con_Print("Couldn't load dsound.dll\n"); return SIS_FAILURE; } @@ -225,7 +225,7 @@ sndinitstat SNDDMA_InitDirect (void) if (!pDirectSoundCreate) { - Con_SafePrintf ("Couldn't get DS proc addr\n"); + Con_Print("Couldn't get DS proc addr\n"); return SIS_FAILURE; } } @@ -234,7 +234,7 @@ sndinitstat SNDDMA_InitDirect (void) { if (hresult != DSERR_ALLOCATED) { - Con_SafePrintf ("DirectSound create failed\n"); + Con_Print("DirectSound create failed\n"); return SIS_FAILURE; } @@ -244,8 +244,7 @@ sndinitstat SNDDMA_InitDirect (void) "Sound not available", MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) { - Con_SafePrintf ("DirectSoundCreate failure\n" - " hardware already in use\n"); + Con_Print("DirectSoundCreate failure\n hardware already in use\n"); return SIS_NOTAVAIL; } } @@ -254,25 +253,25 @@ sndinitstat SNDDMA_InitDirect (void) if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) { - Con_SafePrintf ("Couldn't get DS caps\n"); + Con_Print("Couldn't get DS caps\n"); } if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { - Con_SafePrintf ("No DirectSound driver installed\n"); + Con_Print("No DirectSound driver installed\n"); FreeSound (); return SIS_FAILURE; } if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_EXCLUSIVE)) { - Con_SafePrintf ("Set coop level failed\n"); + Con_Print("Set coop level failed\n"); FreeSound (); return SIS_FAILURE; } -// get access to the primary buffer, if possible, so we can set the -// sound hardware format + // 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; @@ -283,6 +282,7 @@ sndinitstat SNDDMA_InitDirect (void) dsbcaps.dwSize = sizeof(dsbcaps); primary_format_set = false; +// COMMANDLINEOPTION: Windows DirectSound: -snoforceformat uses the format that DirectSound returns, rather than forcing it if (!COM_CheckParm ("-snoforceformat")) { if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL)) @@ -291,22 +291,21 @@ sndinitstat SNDDMA_InitDirect (void) if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat)) { - if (snd_firsttime) - Con_SafePrintf ("Set primary sound buffer format: no\n"); + Con_Print("Set primary sound buffer format: no\n"); } else { - if (snd_firsttime) - Con_SafePrintf ("Set primary sound buffer format: yes\n"); + Con_Print("Set primary sound buffer format: yes\n"); primary_format_set = true; } } } +// COMMANDLINEOPTION: Windows DirectSound: -primarysound locks the sound hardware for exclusive use if (!primary_format_set || !COM_CheckParm ("-primarysound")) { - // create the secondary buffer we'll actually work with + // create the secondary buffer we'll actually work with memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE; @@ -318,70 +317,68 @@ sndinitstat SNDDMA_InitDirect (void) if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { - Con_SafePrintf ("DS:CreateSoundBuffer Failed"); + Con_Print("DS:CreateSoundBuffer Failed\n"); FreeSound (); return SIS_FAILURE; } - shm->channels = format.nChannels; - shm->samplebits = format.wBitsPerSample; - shm->speed = format.nSamplesPerSec; + shm->format.channels = format.nChannels; + shm->format.width = format.wBitsPerSample / 8; + shm->format.speed = format.nSamplesPerSec; if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps)) { - Con_SafePrintf ("DS:GetCaps failed\n"); + Con_Print("DS:GetCaps failed\n"); FreeSound (); return SIS_FAILURE; } - if (snd_firsttime) - Con_SafePrintf ("Using secondary sound buffer\n"); + Con_Print("Using secondary sound buffer\n"); } else { if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) { - Con_SafePrintf ("Set coop level failed\n"); + Con_Print("Set coop level failed\n"); FreeSound (); return SIS_FAILURE; } if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps)) { - Con_Printf ("DS:GetCaps failed\n"); + Con_Print("DS:GetCaps failed\n"); return SIS_FAILURE; } pDSBuf = pDSPBuf; - Con_SafePrintf ("Using primary sound buffer\n"); + Con_Print("Using primary sound buffer\n"); } // Make sure mixer is active pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - if (snd_firsttime) - Con_SafePrintf(" %d channel(s)\n" - " %d bits/sample\n" - " %d samples/sec\n", - shm->channels, shm->samplebits, shm->speed); - + Con_Printf(" %d channel(s)\n" + " %d bits/sample\n" + " %d samples/sec\n", + shm->format.channels, shm->format.width * 8, shm->format.speed); + gSndBufSize = dsbcaps.dwBufferBytes; -// initialize the buffer + // initialize the buffer reps = 0; - while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &lpData, &dwSize, NULL, NULL, 0)) != DS_OK) + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&lpData, &dwSize, NULL, NULL, 0)) != DS_OK) { if (hresult != DSERR_BUFFERLOST) { - Con_SafePrintf ("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); + Con_Print("SNDDMA_InitDirect: DS::Lock Sound Buffer Failed\n"); FreeSound (); return SIS_FAILURE; } if (++reps > 10000) { - Con_SafePrintf ("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); + Con_Print("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); FreeSound (); return SIS_FAILURE; } @@ -389,24 +386,19 @@ sndinitstat SNDDMA_InitDirect (void) } memset(lpData, 0, dwSize); -// lpData[4] = lpData[5] = 0x7f; // force a pop for debugging pDSBuf->lpVtbl->Unlock(pDSBuf, lpData, dwSize, NULL, 0); - /* we don't want anyone to access the buffer directly w/o locking it first. */ - lpData = NULL; + // we don't want anyone to access the buffer directly w/o locking it first. + lpData = NULL; pDSBuf->lpVtbl->Stop(pDSBuf); - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwStartTime, NULL); pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); - shm->soundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samples = gSndBufSize / shm->format.width; shm->samplepos = 0; - shm->submission_chunk = 1; shm->buffer = (unsigned char *) lpData; - sample16 = (shm->samplebits/8) - 1; dsound_init = true; @@ -423,42 +415,40 @@ Crappy windows multimedia base */ qboolean SNDDMA_InitWav (void) { - WAVEFORMATEX format; + WAVEFORMATEX format; int i; HRESULT hr; - + snd_sent = 0; snd_completed = 0; - shm = &sn; - - shm->channels = 2; - shm->samplebits = 16; - i = COM_CheckParm ("-sndspeed"); // LordHavoc: -sndspeed option + memset((void *)shm, 0, sizeof(*shm)); + shm->format.channels = 2; + shm->format.width = 2; +// COMMANDLINEOPTION: Windows Sound: -sndspeed chooses 44100 hz, 22100 hz, or 11025 hz sound output rate + i = COM_CheckParm ("-sndspeed"); if (i && i != (com_argc - 1)) - shm->speed = atoi(com_argv[i+1]); + shm->format.speed = atoi(com_argv[i+1]); else - shm->speed = 11025; + shm->format.speed = 44100; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; - format.nChannels = shm->channels; - format.wBitsPerSample = shm->samplebits; - format.nSamplesPerSec = shm->speed; - format.nBlockAlign = format.nChannels - *format.wBitsPerSample / 8; + format.nChannels = shm->format.channels; + format.wBitsPerSample = shm->format.width * 8; + format.nSamplesPerSec = shm->format.speed; + format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; - format.nAvgBytesPerSec = format.nSamplesPerSec - *format.nBlockAlign; - - /* Open a waveform device for output using window callback. */ - while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, - &format, + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; + + // Open a waveform device for output using window callback + while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER, + &format, 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR) { if (hr != MMSYSERR_ALLOCATED) { - Con_SafePrintf ("waveOutOpen failed\n"); + Con_Print("waveOutOpen failed\n"); return false; } @@ -468,83 +458,80 @@ qboolean SNDDMA_InitWav (void) "Sound not available", MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY) { - Con_SafePrintf ("waveOutOpen failure;\n" - " hardware already in use\n"); + Con_Print("waveOutOpen failure;\n hardware already in use\n"); return false; } - } - - /* - * Allocate and lock memory for the waveform data. The memory - * for waveform data must be globally allocated with - * GMEM_MOVEABLE and GMEM_SHARE flags. + } - */ + /* + * Allocate and lock memory for the waveform data. The memory + * for waveform data must be globally allocated with + * GMEM_MOVEABLE and GMEM_SHARE flags. + */ gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE; - hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); - if (!hData) - { - Con_SafePrintf ("Sound: Out of memory.\n"); + hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize); + if (!hData) + { + Con_Print("Sound: Out of memory.\n"); FreeSound (); - return false; + return false; } lpData = GlobalLock(hData); if (!lpData) - { - Con_SafePrintf ("Sound: Failed to lock.\n"); + { + Con_Print("Sound: Failed to lock.\n"); FreeSound (); - return false; - } + return false; + } memset (lpData, 0, gSndBufSize); - /* - * Allocate and lock memory for the header. This memory must - * also be globally allocated with GMEM_MOVEABLE and - * GMEM_SHARE flags. - */ - hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, - (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); + /* + * Allocate and lock memory for the header. This memory must + * also be globally allocated with GMEM_MOVEABLE and + * GMEM_SHARE flags. + */ + hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, + (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS); if (hWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to Alloc header.\n"); + { + Con_Print("Sound: Failed to Alloc header.\n"); FreeSound (); - return false; - } + return false; + } - lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); + lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr); if (lpWaveHdr == NULL) - { - Con_SafePrintf ("Sound: Failed to lock header.\n"); + { + Con_Print("Sound: Failed to lock header.\n"); FreeSound (); - return false; + return false; } memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS); - /* After allocation, set up and prepare headers. */ + // After allocation, set up and prepare headers for (i=0 ; isoundalive = true; - shm->splitbuffer = false; - shm->samples = gSndBufSize/(shm->samplebits/8); + shm->samples = gSndBufSize / shm->format.width; shm->samplepos = 0; - shm->submission_chunk = 1; shm->buffer = (unsigned char *) lpData; - sample16 = (shm->samplebits/8) - 1; + + prev_painted = 0; + paintpot = 0; wav_init = true; @@ -559,74 +546,46 @@ Try to find a sound device to mix for. Returns false if nothing is found. ================== */ - qboolean SNDDMA_Init(void) { sndinitstat stat; +// COMMANDLINEOPTION: Windows Sound: -wavonly uses wave sound instead of DirectSound if (COM_CheckParm ("-wavonly")) wavonly = true; - dsound_init = wav_init = 0; + dsound_init = false; + wav_init = false; stat = SIS_FAILURE; // assume DirectSound won't initialize - /* Init DirectSound */ + // Init DirectSound if (!wavonly) { - if (snd_firsttime || snd_isdirect) - { - stat = SNDDMA_InitDirect ();; + stat = SNDDMA_InitDirect (); - if (stat == SIS_SUCCESS) - { - snd_isdirect = true; - - if (snd_firsttime) - Con_SafePrintf ("DirectSound initialized\n"); - } - else - { - snd_isdirect = false; - Con_SafePrintf ("DirectSound failed to init\n"); - } - } + if (stat == SIS_SUCCESS) + Con_Print("DirectSound initialized\n"); + else + Con_Print("DirectSound failed to init\n"); } -// if DirectSound didn't succeed in initializing, try to initialize -// waveOut sound, unless DirectSound failed because the hardware is -// already allocated (in which case the user has already chosen not -// to have sound) + // if DirectSound didn't succeed in initializing, try to initialize + // waveOut sound, unless DirectSound failed because the hardware is + // already allocated (in which case the user has already chosen not + // to have sound) if (!dsound_init && (stat != SIS_NOTAVAIL)) { - if (snd_firsttime || snd_iswave) - { - - snd_iswave = SNDDMA_InitWav (); - - if (snd_iswave) - { - if (snd_firsttime) - Con_SafePrintf ("Wave sound initialized\n"); - } - else - { - Con_SafePrintf ("Wave sound failed to init\n"); - } - } + if (SNDDMA_InitWav ()) + Con_Print("Wave sound initialized\n"); + else + Con_Print("Wave sound failed to init\n"); } - snd_firsttime = false; - if (!dsound_init && !wav_init) - { -// if (snd_firsttime) -// Con_SafePrintf ("No sound device initialized\n"); + return false; - return 0; - } - - return 1; + return true; } /* @@ -640,27 +599,36 @@ how many sample are required to fill it up. */ int SNDDMA_GetDMAPos(void) { - MMTIME mmtime; - int s; - DWORD dwWrite; + DWORD dwTime, s; - if (dsound_init) + if (dsound_init) { - mmtime.wType = TIME_SAMPLES; - pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); - s = mmtime.u.sample - mmstarttime.u.sample; + pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &dwTime, NULL); + s = dwTime - dwStartTime; } else if (wav_init) { - s = snd_sent * WAV_BUFFER_SIZE; - } + // Find which sound blocks have completed + for (;;) + { + if (snd_completed == snd_sent) + { + Con_DPrint("Sound overrun\n"); + break; + } + if (!(lpWaveHdr[snd_completed & WAV_MASK].dwFlags & WHDR_DONE)) + break; - s >>= sample16; + snd_completed++; // this buffer has been played + } - s &= (shm->samples-1); + s = snd_completed * WAV_BUFFER_SIZE; + } + else + return 0; - return s; + return (s >> (shm->format.width - 1)) & (shm->samples - 1); } /* @@ -675,49 +643,36 @@ void SNDDMA_Submit(void) LPWAVEHDR h; int wResult; + // DirectSound doesn't need this if (!wav_init) return; - // - // find which sound blocks have completed - // - while (1) - { - if ( snd_completed == snd_sent ) - { - Con_DPrintf ("Sound overrun\n"); - break; - } - - if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) ) - { - break; - } - - snd_completed++; // this buffer has been played - } + paintpot += (paintedtime - prev_painted) * shm->format.channels * shm->format.width; + if (paintpot > WAV_BUFFERS * WAV_BUFFER_SIZE) + paintpot = WAV_BUFFERS * WAV_BUFFER_SIZE; + prev_painted = paintedtime; - // - // submit two new sound blocks - // - while (((snd_sent - snd_completed) >> sample16) < 4) + // submit new sound blocks + while (paintpot > WAV_BUFFER_SIZE) { - h = lpWaveHdr + ( snd_sent&WAV_MASK ); + h = lpWaveHdr + (snd_sent & WAV_MASK); snd_sent++; - /* - * Now the data block can be sent to the output device. The - * waveOutWrite function returns immediately and waveform - * data is sent to the output device in the background. - */ - wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); + /* + * Now the data block can be sent to the output device. The + * waveOutWrite function returns immediately and waveform + * data is sent to the output device in the background. + */ + wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR)); if (wResult != MMSYSERR_NOERROR) - { - Con_SafePrintf ("Failed to write block to device\n"); + { + Con_Print("Failed to write block to device\n"); FreeSound (); - return; - } + return; + } + + paintpot -= WAV_BUFFER_SIZE; } } @@ -733,3 +688,61 @@ void SNDDMA_Shutdown(void) FreeSound (); } + +static DWORD dsound_dwSize; +static DWORD dsound_dwSize2; +static DWORD *dsound_pbuf; +static DWORD *dsound_pbuf2; + +void *S_LockBuffer(void) +{ + int reps; + HRESULT hresult; + DWORD dwStatus; + + if (pDSBuf) + { + // if the buffer was lost or stopped, restore it and/or restart it + if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK) + Con_Print("Couldn't get sound buffer status\n"); + + if (dwStatus & DSBSTATUS_BUFFERLOST) + pDSBuf->lpVtbl->Restore (pDSBuf); + + if (!(dwStatus & DSBSTATUS_PLAYING)) + pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING); + + reps = 0; + + while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, (LPVOID*)&dsound_pbuf, &dsound_dwSize, (LPVOID*)&dsound_pbuf2, &dsound_dwSize2, 0)) != DS_OK) + { + if (hresult != DSERR_BUFFERLOST) + { + Con_Print("S_LockBuffer: DS: Lock Sound Buffer Failed\n"); + S_Shutdown (); + S_Startup (); + return NULL; + } + + if (++reps > 10000) + { + Con_Print("S_LockBuffer: DS: couldn't restore buffer\n"); + S_Shutdown (); + S_Startup (); + return NULL; + } + } + return dsound_pbuf; + } + else if (wav_init) + return shm->buffer; + else + return NULL; +} + +void S_UnlockBuffer(void) +{ + if (pDSBuf) + pDSBuf->lpVtbl->Unlock(pDSBuf, dsound_pbuf, dsound_dwSize, dsound_pbuf2, dsound_dwSize2); +} +