]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - snd_win.c
a bit of loading screen bar customization: new cvars scr_loadingscreen_barcolor,...
[xonotic/darkplaces.git] / snd_win.c
index 6b0225055b9a8fc3a098911cf861b3a723f0aebf..a7a2adff12571818a8f74629f8e821498585c7bf 100644 (file)
--- a/snd_win.c
+++ b/snd_win.c
@@ -20,12 +20,16 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 #include "quakedef.h"
 #include "snd_main.h"
 
+#ifdef SUPPORTDIRECTX
 #ifndef DIRECTSOUND_VERSION
 #      define DIRECTSOUND_VERSION 0x0500  /* Version 5.0 */
 #endif
+#endif
 #include <windows.h>
 #include <mmsystem.h>
+#ifdef SUPPORTDIRECTX
 #include <dsound.h>
+#endif
 
 // ==============================================================================
 
@@ -78,12 +82,15 @@ static const GUID MY_KSDATAFORMAT_SUBTYPE_PCM =
 // ==============================================================================
 
 extern HWND mainwindow;
+static cvar_t snd_wav_partitionsize = {CVAR_SAVE, "snd_wav_partitionsize", "1024", "controls sound delay in samples, values too low will cause crackling, too high will cause delayed sounds"};
+static qboolean sndsys_registeredcvars = false;
 
+#ifdef SUPPORTDIRECTX
 HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
+#endif
 
-// 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
+// Wave output: queue of this many sound buffers to play, reused cyclically
+#define        WAV_BUFFERS             16
 #define        WAV_MASK                (WAV_BUFFERS - 1)
 static unsigned int wav_buffer_size;
 
@@ -94,16 +101,19 @@ static unsigned int wav_buffer_size;
 
 typedef enum sndinitstat_e {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
 
+#ifdef SUPPORTDIRECTX
 static qboolean        dsound_init;
-static qboolean        wav_init;
+static unsigned int dsound_time;
 static qboolean        primary_format_set;
+#endif
+
+static qboolean        wav_init;
 
 static int     snd_sent, snd_completed;
 
 static int prev_painted;
 static unsigned int paintpot;
 
-static unsigned int dsound_time;
 
 
 /*
@@ -125,13 +135,17 @@ DWORD     gSndBufSize;
 
 DWORD  dwStartTime;
 
+#ifdef SUPPORTDIRECTX
 LPDIRECTSOUND pDS;
 LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
 
 HINSTANCE hInstDS;
+#endif
 
 qboolean SNDDMA_InitWav (void);
+#ifdef SUPPORTDIRECTX
 sndinitstat SNDDMA_InitDirect (void);
+#endif
 
 
 /*
@@ -152,10 +166,14 @@ static qboolean SndSys_BuildWaveFormat (const snd_format_t* requested, WAVEFORMA
        pfmtex->nBlockAlign = pfmtex->nChannels * pfmtex->wBitsPerSample / 8;
        pfmtex->nAvgBytesPerSec = pfmtex->nSamplesPerSec * pfmtex->nBlockAlign;
 
+       // LordHavoc: disabled this WAVE_FORMAT_EXTENSIBLE support because it does not seem to be working
+#if 0
        if (requested->channels <= 2)
        {
+#endif
                pfmtex->wFormatTag = WAVE_FORMAT_PCM;
                pfmtex->cbSize = 0;
+#if 0
        }
        else
        {
@@ -183,11 +201,13 @@ static qboolean SndSys_BuildWaveFormat (const snd_format_t* requested, WAVEFORMA
                                return false;
                }
        }
+#endif
 
        return true;
 }
 
 
+#ifdef SUPPORTDIRECTX
 /*
 ==================
 SndSys_InitDirectSound
@@ -218,7 +238,7 @@ static sndinitstat SndSys_InitDirectSound (const snd_format_t* requested)
                        return SIS_FAILURE;
                }
 
-               pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
+               pDirectSoundCreate = (HRESULT (__stdcall *)(GUID *, LPDIRECTSOUND *,IUnknown *))GetProcAddress(hInstDS,"DirectSoundCreate");
 
                if (!pDirectSoundCreate)
                {
@@ -321,7 +341,7 @@ static sndinitstat SndSys_InitDirectSound (const snd_format_t* requested)
                        requested->speed != format.Format.nSamplesPerSec)
                {
                        Con_Printf("DS:CreateSoundBuffer Failed (%d): channels=%u, width=%u, speed=%u\n",
-                                          result, format.Format.nChannels, format.Format.wBitsPerSample / 8, format.Format.nSamplesPerSec);
+                                          (int)result, (unsigned)format.Format.nChannels, (unsigned)format.Format.wBitsPerSample / 8, (unsigned)format.Format.nSamplesPerSec);
                        SndSys_Shutdown ();
                        return SIS_FAILURE;
                }
@@ -357,7 +377,7 @@ static sndinitstat SndSys_InitDirectSound (const snd_format_t* requested)
        // Make sure mixer is active
        IDirectSoundBuffer_Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
 
-       Con_DPrintf("   %d channel(s)\n"
+       Con_Printf("   %d channel(s)\n"
                                "   %d bits/sample\n"
                                "   %d samples/sec\n",
                                requested->channels, requested->width * 8, requested->speed);
@@ -399,6 +419,7 @@ static sndinitstat SndSys_InitDirectSound (const snd_format_t* requested)
 
        return SIS_SUCCESS;
 }
+#endif
 
 
 /*
@@ -438,7 +459,7 @@ static qboolean SndSys_InitMmsystem (const snd_format_t* requested)
                }
        }
 
-       wav_buffer_size = (requested->speed / 2 / WAV_BUFFERS) * requested->channels * requested->width;
+       wav_buffer_size = bound(128, snd_wav_partitionsize.integer, 8192) * requested->channels * requested->width;
 
        /*
         * Allocate and lock memory for the waveform data. The memory
@@ -453,7 +474,7 @@ static qboolean SndSys_InitMmsystem (const snd_format_t* requested)
                SndSys_Shutdown ();
                return false;
        }
-       lpData = GlobalLock(hData);
+       lpData = (HPSTR)GlobalLock(hData);
        if (!lpData)
        {
                Con_Print("Sound: Failed to lock.\n");
@@ -525,18 +546,29 @@ May return a suggested format if the requested format isn't available
 */
 qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
 {
+#ifdef SUPPORTDIRECTX
        qboolean wavonly;
+#endif
        sndinitstat     stat;
 
+       if (!sndsys_registeredcvars)
+       {
+               sndsys_registeredcvars = true;
+               Cvar_RegisterVariable(&snd_wav_partitionsize);
+       }
+
        Con_Print ("SndSys_Init: using the Win32 module\n");
 
+#ifdef SUPPORTDIRECTX
 // COMMANDLINEOPTION: Windows Sound: -wavonly uses wave sound instead of DirectSound
        wavonly = (COM_CheckParm ("-wavonly") != 0);
        dsound_init = false;
+#endif
        wav_init = false;
 
        stat = SIS_FAILURE;     // assume DirectSound won't initialize
 
+#ifdef SUPPORTDIRECTX
        // Init DirectSound
        if (!wavonly)
        {
@@ -547,12 +579,15 @@ qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
                else
                        Con_Print("DirectSound failed to init\n");
        }
+#endif
 
        // 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)
+#ifdef SUPPORTDIRECTX
        if (!dsound_init && (stat != SIS_NOTAVAIL))
+#endif
        {
                if (SndSys_InitMmsystem (requested))
                        Con_Print("Wave sound (MMSYSTEM) initialized\n");
@@ -560,7 +595,11 @@ qboolean SndSys_Init (const snd_format_t* requested, snd_format_t* suggested)
                        Con_Print("Wave sound failed to init\n");
        }
 
+#ifdef SUPPORTDIRECTX
        return (dsound_init || wav_init);
+#else
+       return wav_init;
+#endif
 }
 
 
@@ -573,6 +612,7 @@ Stop the sound card, delete "snd_renderbuffer" and free its other resources
 */
 void SndSys_Shutdown (void)
 {
+#ifdef SUPPORTDIRECTX
        if (pDSBuf)
        {
                IDirectSoundBuffer_Stop(pDSBuf);
@@ -590,6 +630,7 @@ void SndSys_Shutdown (void)
                IDirectSound_SetCooperativeLevel (pDS, mainwindow, DSSCL_NORMAL);
                IDirectSound_Release(pDS);
        }
+#endif
 
        if (hWaveOut)
        {
@@ -624,15 +665,17 @@ void SndSys_Shutdown (void)
                snd_renderbuffer = NULL;
        }
 
+#ifdef SUPPORTDIRECTX
        pDS = NULL;
        pDSBuf = NULL;
        pDSPBuf = NULL;
+       dsound_init = false;
+#endif
        hWaveOut = 0;
        hData = 0;
        hWaveHdr = 0;
        lpData = NULL;
        lpWaveHdr = NULL;
-       dsound_init = false;
        wav_init = false;
 }
 
@@ -663,17 +706,24 @@ void SndSys_Submit (void)
        {
                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));
-
-               if (wResult != MMSYSERR_NOERROR)
+               if (wResult == MMSYSERR_NOERROR)
+                       snd_sent++;
+               else if (wResult == WAVERR_STILLPLAYING)
+               {
+                       if(developer_insane.integer)
+                               Con_DPrint("waveOutWrite failed (too much sound data)\n");
+                       //h->dwFlags |= WHDR_DONE;
+                       //snd_sent++;
+               }
+               else
                {
-                       Con_Print("Failed to write block to device\n");
+                       Con_Printf("waveOutWrite failed, error code %d\n", (int) wResult);
                        SndSys_Shutdown ();
                        return;
                }
@@ -697,6 +747,7 @@ unsigned int SndSys_GetSoundTime (void)
 
        factor = snd_renderbuffer->format.width * snd_renderbuffer->format.channels;
 
+#ifdef SUPPORTDIRECTX
        if (dsound_init)
        {
                DWORD dwTime;
@@ -709,6 +760,7 @@ unsigned int SndSys_GetSoundTime (void)
                dsound_time += diff / factor;
                return dsound_time;
        }
+#endif
 
        if (wav_init)
        {
@@ -717,7 +769,7 @@ unsigned int SndSys_GetSoundTime (void)
                {
                        if (snd_completed == snd_sent)
                        {
-                               Con_DPrint("Sound overrun\n");
+                       //      Con_DPrint("Sound overrun\n");
                                break;
                        }
 
@@ -728,16 +780,32 @@ unsigned int SndSys_GetSoundTime (void)
                }
 
                return (snd_completed * wav_buffer_size) / factor;
+
+               /*
+                * S_PaintAndSubmit: WARNING: newsoundtime (soundtime (275 < 134217707)
+                * apparently this sound time wraps quite early?
+               {
+               MMRESULT res;
+               MMTIME mmtime;
+
+               mmtime.wType = TIME_SAMPLES;
+               res = waveOutGetPosition(hWaveOut, &mmtime, sizeof(mmtime));
+               if(res == MMSYSERR_NOERROR)
+                       return mmtime.u.sample;
+               }
+               */
        }
 
        return 0;
 }
 
 
+#ifdef SUPPORTDIRECTX
 static DWORD dsound_dwSize;
 static DWORD dsound_dwSize2;
 static DWORD *dsound_pbuf;
 static DWORD *dsound_pbuf2;
+#endif
 
 /*
 ====================
@@ -748,6 +816,7 @@ Get the exclusive lock on "snd_renderbuffer"
 */
 qboolean SndSys_LockRenderBuffer (void)
 {
+#ifdef SUPPORTDIRECTX
        int reps;
        HRESULT hresult;
        DWORD   dwStatus;
@@ -792,6 +861,7 @@ qboolean SndSys_LockRenderBuffer (void)
                        Sys_Error("SndSys_LockRenderBuffer: the ring address has changed!!!\n");
                return true;
        }
+#endif
 
        return wav_init;
 }
@@ -806,6 +876,20 @@ Release the exclusive lock on "snd_renderbuffer"
 */
 void SndSys_UnlockRenderBuffer (void)
 {
+#ifdef SUPPORTDIRECTX
        if (pDSBuf)
                IDirectSoundBuffer_Unlock(pDSBuf, dsound_pbuf, dsound_dwSize, dsound_pbuf2, dsound_dwSize2);
+#endif
+}
+
+/*
+====================
+SndSys_SendKeyEvents
+
+Send keyboard events originating from the sound system (e.g. MIDI)
+====================
+*/
+void SndSys_SendKeyEvents(void)
+{
+       // not supported
 }