X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=snd_win.c;h=89b885bacf90720bf122f9b350515547f4cfc62a;hb=dc5006685dfe9ad5a6b39b0dda5088d8144d396b;hp=2fed37be8279b8dda4ac6dcdf30e56f7e9a7f2ae;hpb=b37129d36872d2d42d861024433c34239b24f6a3;p=xonotic%2Fdarkplaces.git diff --git a/snd_win.c b/snd_win.c index 2fed37be..89b885ba 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,7 +18,11 @@ 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) @@ -42,10 +46,10 @@ static int sample16; static int snd_sent, snd_completed; -/* - * 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,7 +57,7 @@ HPSTR lpData, lpData2; HGLOBAL hWaveHdr; LPWAVEHDR lpWaveHdr; -HWAVEOUT hWaveOut; +HWAVEOUT hWaveOut; WAVEOUTCAPS wavecaps; @@ -147,7 +151,7 @@ void FreeSound (void) if (hWaveHdr) { - GlobalUnlock(hWaveHdr); + GlobalUnlock(hWaveHdr); GlobalFree(hWaveHdr); } @@ -185,39 +189,37 @@ sndinitstat SNDDMA_InitDirect (void) DSBCAPS dsbcaps; DWORD dwSize, dwWrite; 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_SafePrint("Couldn't load dsound.dll\n"); return SIS_FAILURE; } @@ -225,7 +227,7 @@ sndinitstat SNDDMA_InitDirect (void) if (!pDirectSoundCreate) { - Con_SafePrintf ("Couldn't get DS proc addr\n"); + Con_SafePrint("Couldn't get DS proc addr\n"); return SIS_FAILURE; } } @@ -234,7 +236,7 @@ sndinitstat SNDDMA_InitDirect (void) { if (hresult != DSERR_ALLOCATED) { - Con_SafePrintf ("DirectSound create failed\n"); + Con_SafePrint("DirectSound create failed\n"); return SIS_FAILURE; } @@ -244,8 +246,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_SafePrint("DirectSoundCreate failure\n hardware already in use\n"); return SIS_NOTAVAIL; } } @@ -254,19 +255,19 @@ sndinitstat SNDDMA_InitDirect (void) if (DS_OK != pDS->lpVtbl->GetCaps (pDS, &dscaps)) { - Con_SafePrintf ("Couldn't get DS caps\n"); + Con_SafePrint("Couldn't get DS caps\n"); } if (dscaps.dwFlags & DSCAPS_EMULDRIVER) { - Con_SafePrintf ("No DirectSound driver installed\n"); + Con_SafePrint("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_SafePrint("Set coop level failed\n"); FreeSound (); return SIS_FAILURE; } @@ -283,6 +284,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)) @@ -292,18 +294,19 @@ 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_SafePrint("Set primary sound buffer format: no\n"); } else { if (snd_firsttime) - Con_SafePrintf ("Set primary sound buffer format: yes\n"); + Con_SafePrint("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 @@ -318,42 +321,42 @@ sndinitstat SNDDMA_InitDirect (void) if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { - Con_SafePrintf ("DS:CreateSoundBuffer Failed"); + Con_SafePrint("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_SafePrint("DS:GetCaps failed\n"); FreeSound (); return SIS_FAILURE; } if (snd_firsttime) - Con_SafePrintf ("Using secondary sound buffer\n"); + Con_SafePrint("Using secondary sound buffer\n"); } else { if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, mainwindow, DSSCL_WRITEPRIMARY)) { - Con_SafePrintf ("Set coop level failed\n"); + Con_SafePrint("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_SafePrint("Using primary sound buffer\n"); } // Make sure mixer is active @@ -363,25 +366,25 @@ sndinitstat SNDDMA_InitDirect (void) Con_SafePrintf(" %d channel(s)\n" " %d bits/sample\n" " %d samples/sec\n", - shm->channels, shm->samplebits, shm->speed); - + 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_SafePrint("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_SafePrint("SNDDMA_InitDirect: DS: couldn't restore buffer\n"); FreeSound (); return SIS_FAILURE; } @@ -393,19 +396,16 @@ sndinitstat SNDDMA_InitDirect (void) 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; + lpData = NULL; pDSBuf->lpVtbl->Stop(pDSBuf); pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite); 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; + sample16 = shm->format.width - 1; dsound_init = true; @@ -422,42 +422,42 @@ 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.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.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_SafePrint("waveOutOpen failed\n"); return false; } @@ -467,83 +467,79 @@ 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_SafePrint("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_SafePrint("Sound: Out of memory.\n"); FreeSound (); - return false; + return false; } lpData = GlobalLock(hData); if (!lpData) - { - Con_SafePrintf ("Sound: Failed to lock.\n"); + { + Con_SafePrint("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_SafePrint("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_SafePrint("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; + sample16 = shm->format.width - 1; wav_init = true; @@ -563,6 +559,7 @@ qboolean SNDDMA_Init(void) { sndinitstat stat; +// COMMANDLINEOPTION: Windows Sound: -wavonly uses wave sound instead of DirectSound if (COM_CheckParm ("-wavonly")) wavonly = true; @@ -575,19 +572,19 @@ qboolean SNDDMA_Init(void) { 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"); + Con_SafePrint("DirectSound initialized\n"); } else { snd_isdirect = false; - Con_SafePrintf ("DirectSound failed to init\n"); + Con_SafePrint("DirectSound failed to init\n"); } } } @@ -606,11 +603,11 @@ qboolean SNDDMA_Init(void) if (snd_iswave) { if (snd_firsttime) - Con_SafePrintf ("Wave sound initialized\n"); + Con_SafePrint("Wave sound initialized\n"); } else { - Con_SafePrintf ("Wave sound failed to init\n"); + Con_SafePrint("Wave sound failed to init\n"); } } } @@ -638,7 +635,7 @@ int SNDDMA_GetDMAPos(void) int s; DWORD dwWrite; - if (dsound_init) + if (dsound_init) { mmtime.wType = TIME_SAMPLES; pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite); @@ -681,7 +678,7 @@ void SNDDMA_Submit(void) { if ( snd_completed == snd_sent ) { - Con_DPrintf ("Sound overrun\n"); + Con_DPrint("Sound overrun\n"); break; } @@ -710,7 +707,7 @@ void SNDDMA_Submit(void) if (wResult != MMSYSERR_NOERROR) { - Con_SafePrintf ("Failed to write block to device\n"); + Con_SafePrint("Failed to write block to device\n"); FreeSound (); return; } @@ -737,16 +734,27 @@ 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, &dsound_pbuf, &dsound_dwSize, &dsound_pbuf2, &dsound_dwSize2, 0)) != DS_OK) + 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_Printf ("S_LockBuffer: DS::Lock Sound Buffer Failed\n"); + Con_Print("S_LockBuffer: DS: Lock Sound Buffer Failed\n"); S_Shutdown (); S_Startup (); return NULL; @@ -754,7 +762,7 @@ void *S_LockBuffer(void) if (++reps > 10000) { - Con_Printf ("S_LockBuffer: DS: couldn't restore buffer\n"); + Con_Print("S_LockBuffer: DS: couldn't restore buffer\n"); S_Shutdown (); S_Startup (); return NULL; @@ -766,7 +774,7 @@ void *S_LockBuffer(void) return shm->buffer; } -void S_UnlockBuffer() +void S_UnlockBuffer(void) { if (pDSBuf) pDSBuf->lpVtbl->Unlock(pDSBuf, dsound_pbuf, dsound_dwSize, dsound_pbuf2, dsound_dwSize2);