|
|
1.1 root 1: #include <float.h>
2:
3: #include "../client/client.h"
4: #include "../client/snd_loc.h"
5: #include "winquake.h"
6:
7: #define iDirectSoundCreate(a,b,c) pDirectSoundCreate(a,b,c)
8:
9: HRESULT (WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID, LPDIRECTSOUND FAR *lplpDS, IUnknown FAR *pUnkOuter);
10:
11: // 64K is > 1 second at 16-bit, 22050 Hz
12: #define WAV_BUFFERS 64
13: #define WAV_MASK 0x3F
14: #define WAV_BUFFER_SIZE 0x0400
15: #define SECONDARY_BUFFER_SIZE 0x10000
16:
17: typedef enum {SIS_SUCCESS, SIS_FAILURE, SIS_NOTAVAIL} sndinitstat;
18:
19: cvar_t *s_wavonly;
20:
21: static qboolean dsound_init;
22: static qboolean wav_init;
23: static qboolean snd_firsttime = true, snd_isdirect, snd_iswave;
24: static qboolean primary_format_set;
25:
26: // starts at 0 for disabled
27: static int snd_buffer_count = 0;
28: static int sample16;
29: static int snd_sent, snd_completed;
30:
31: /*
32: * Global variables. Must be visible to window-procedure function
33: * so it can unlock and free the data block after it has been played.
34: */
35:
36:
37: HANDLE hData;
38: HPSTR lpData, lpData2;
39:
40: HGLOBAL hWaveHdr;
41: LPWAVEHDR lpWaveHdr;
42:
43: HWAVEOUT hWaveOut;
44:
45: WAVEOUTCAPS wavecaps;
46:
47: DWORD gSndBufSize;
48:
49: MMTIME mmstarttime;
50:
51: LPDIRECTSOUND pDS;
52: LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
53:
54: HINSTANCE hInstDS;
55:
56: qboolean SNDDMA_InitDirect (void);
57: qboolean SNDDMA_InitWav (void);
58:
59: void FreeSound( void );
60:
61: static const char *DSoundError( int error )
62: {
63: switch ( error )
64: {
65: case DSERR_BUFFERLOST:
66: return "DSERR_BUFFERLOST";
67: case DSERR_INVALIDCALL:
68: return "DSERR_INVALIDCALLS";
69: case DSERR_INVALIDPARAM:
70: return "DSERR_INVALIDPARAM";
71: case DSERR_PRIOLEVELNEEDED:
72: return "DSERR_PRIOLEVELNEEDED";
73: }
74:
75: return "unknown";
76: }
77:
78: /*
79: ** DS_CreateBuffers
80: */
81: static qboolean DS_CreateBuffers( void )
82: {
83: DSBUFFERDESC dsbuf;
84: DSBCAPS dsbcaps;
85: WAVEFORMATEX pformat, format;
86: DWORD dwWrite;
87:
88: memset (&format, 0, sizeof(format));
89: format.wFormatTag = WAVE_FORMAT_PCM;
90: format.nChannels = dma.channels;
91: format.wBitsPerSample = dma.samplebits;
92: format.nSamplesPerSec = dma.speed;
93: format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8;
94: format.cbSize = 0;
95: format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign;
96:
97: Com_Printf( "Creating DS buffers\n" );
98:
99: Com_DPrintf("...setting EXCLUSIVE coop level: " );
100: if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_EXCLUSIVE ) )
101: {
102: Com_Printf ("failed\n");
103: FreeSound ();
104: return false;
105: }
106: Com_DPrintf("ok\n" );
107:
108: // get access to the primary buffer, if possible, so we can set the
109: // sound hardware format
110: memset (&dsbuf, 0, sizeof(dsbuf));
111: dsbuf.dwSize = sizeof(DSBUFFERDESC);
112: dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER;
113: dsbuf.dwBufferBytes = 0;
114: dsbuf.lpwfxFormat = NULL;
115:
116: memset(&dsbcaps, 0, sizeof(dsbcaps));
117: dsbcaps.dwSize = sizeof(dsbcaps);
118: primary_format_set = false;
119:
120: Com_DPrintf( "...creating primary buffer: " );
121: if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSPBuf, NULL))
122: {
123: pformat = format;
124:
125: Com_DPrintf( "ok\n" );
126: if (DS_OK != pDSPBuf->lpVtbl->SetFormat (pDSPBuf, &pformat))
127: {
128: if (snd_firsttime)
129: Com_DPrintf ("...setting primary sound format: failed\n");
130: }
131: else
132: {
133: if (snd_firsttime)
134: Com_DPrintf ("...setting primary sound format: ok\n");
135:
136: primary_format_set = true;
137: }
138: }
139: else
140: Com_Printf( "failed\n" );
141:
142: if ( !primary_format_set || !s_primary->value)
143: {
144: // create the secondary buffer we'll actually work with
145: memset (&dsbuf, 0, sizeof(dsbuf));
146: dsbuf.dwSize = sizeof(DSBUFFERDESC);
147: dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE;
148: dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE;
149: dsbuf.lpwfxFormat = &format;
150:
151: memset(&dsbcaps, 0, sizeof(dsbcaps));
152: dsbcaps.dwSize = sizeof(dsbcaps);
153:
154: Com_DPrintf( "...creating secondary buffer: " );
155: if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL))
156: {
157: Com_Printf( "failed\n" );
158: FreeSound ();
159: return false;
160: }
161: Com_DPrintf( "ok\n" );
162:
163: dma.channels = format.nChannels;
164: dma.samplebits = format.wBitsPerSample;
165: dma.speed = format.nSamplesPerSec;
166:
167: if (DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps))
168: {
169: Com_Printf ("*** GetCaps failed ***\n");
170: FreeSound ();
171: return false;
172: }
173:
174: Com_Printf ("...using secondary sound buffer\n");
175: }
176: else
177: {
178: Com_Printf( "...using primary buffer\n" );
179:
180: Com_DPrintf( "...setting WRITEPRIMARY coop level: " );
181: if (DS_OK != pDS->lpVtbl->SetCooperativeLevel (pDS, cl_hwnd, DSSCL_WRITEPRIMARY))
182: {
183: Com_Printf( "failed\n" );
184: FreeSound ();
185: return false;
186: }
187: Com_DPrintf( "ok\n" );
188:
189: if (DS_OK != pDSPBuf->lpVtbl->GetCaps (pDSPBuf, &dsbcaps))
190: {
191: Com_Printf ("*** GetCaps failed ***\n");
192: return false;
193: }
194:
195: pDSBuf = pDSPBuf;
196: }
197:
198: // Make sure mixer is active
199: pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
200:
201: if (snd_firsttime)
202: Com_Printf(" %d channel(s)\n"
203: " %d bits/sample\n"
204: " %d bytes/sec\n",
205: dma.channels, dma.samplebits, dma.speed);
206:
207: gSndBufSize = dsbcaps.dwBufferBytes;
208:
209: /* we don't want anyone to access the buffer directly w/o locking it first. */
210: lpData = NULL;
211:
212: pDSBuf->lpVtbl->Stop(pDSBuf);
213: pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmstarttime.u.sample, &dwWrite);
214: pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
215:
216: dma.samples = gSndBufSize/(dma.samplebits/8);
217: dma.samplepos = 0;
218: dma.submission_chunk = 1;
219: dma.buffer = (unsigned char *) lpData;
220: sample16 = (dma.samplebits/8) - 1;
221:
222: return true;
223: }
224:
225: /*
226: ** DS_DestroyBuffers
227: */
228: static void DS_DestroyBuffers( void )
229: {
230: Com_DPrintf( "Destroying DS buffers\n" );
231: if ( pDS )
232: {
233: Com_DPrintf( "...setting NORMAL coop level\n" );
234: pDS->lpVtbl->SetCooperativeLevel( pDS, cl_hwnd, DSSCL_NORMAL );
235: }
236:
237: if ( pDSBuf )
238: {
239: Com_DPrintf( "...stopping and releasing sound buffer\n" );
240: pDSBuf->lpVtbl->Stop( pDSBuf );
241: pDSBuf->lpVtbl->Release( pDSBuf );
242: }
243:
244: // only release primary buffer if it's not also the mixing buffer we just released
245: if ( pDSPBuf && ( pDSBuf != pDSPBuf ) )
246: {
247: Com_DPrintf( "...releasing primary buffer\n" );
248: pDSPBuf->lpVtbl->Release( pDSPBuf );
249: }
250: pDSBuf = NULL;
251: pDSPBuf = NULL;
252:
253: dma.buffer = NULL;
254: }
255:
256: /*
257: ==================
258: FreeSound
259: ==================
260: */
261: void FreeSound (void)
262: {
263: int i;
264:
265: Com_DPrintf( "Shutting down sound system\n" );
266:
267: if ( pDS )
268: DS_DestroyBuffers();
269:
270: if ( hWaveOut )
271: {
272: Com_DPrintf( "...resetting waveOut\n" );
273: waveOutReset (hWaveOut);
274:
275: if (lpWaveHdr)
276: {
277: Com_DPrintf( "...unpreparing headers\n" );
278: for (i=0 ; i< WAV_BUFFERS ; i++)
279: waveOutUnprepareHeader (hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR));
280: }
281:
282: Com_DPrintf( "...closing waveOut\n" );
283: waveOutClose (hWaveOut);
284:
285: if (hWaveHdr)
286: {
287: Com_DPrintf( "...freeing WAV header\n" );
288: GlobalUnlock(hWaveHdr);
289: GlobalFree(hWaveHdr);
290: }
291:
292: if (hData)
293: {
294: Com_DPrintf( "...freeing WAV buffer\n" );
295: GlobalUnlock(hData);
296: GlobalFree(hData);
297: }
298:
299: }
300:
301: if ( pDS )
302: {
303: Com_DPrintf( "...releasing DS object\n" );
304: pDS->lpVtbl->Release( pDS );
305: }
306:
307: if ( hInstDS )
308: {
309: Com_DPrintf( "...freeing DSOUND.DLL\n" );
310: FreeLibrary( hInstDS );
311: hInstDS = NULL;
312: }
313:
314: pDS = NULL;
315: pDSBuf = NULL;
316: pDSPBuf = NULL;
317: hWaveOut = 0;
318: hData = 0;
319: hWaveHdr = 0;
320: lpData = NULL;
321: lpWaveHdr = NULL;
322: dsound_init = false;
323: wav_init = false;
324: }
325:
326: /*
327: ==================
328: SNDDMA_InitDirect
329:
330: Direct-Sound support
331: ==================
332: */
333: sndinitstat SNDDMA_InitDirect (void)
334: {
335: DSCAPS dscaps;
336: HRESULT hresult;
337:
338: dma.channels = 2;
339: dma.samplebits = 16;
340:
341: if (s_khz->value == 44)
342: dma.speed = 44100;
343: if (s_khz->value == 22)
344: dma.speed = 22050;
345: else
346: dma.speed = 11025;
347:
348: Com_Printf( "Initializing DirectSound\n");
349:
350: if ( !hInstDS )
351: {
352: Com_DPrintf( "...loading dsound.dll: " );
353:
354: hInstDS = LoadLibrary("dsound.dll");
355:
356: if (hInstDS == NULL)
357: {
358: Com_Printf ("failed\n");
359: return SIS_FAILURE;
360: }
361:
362: Com_DPrintf ("ok\n");
363: pDirectSoundCreate = (void *)GetProcAddress(hInstDS,"DirectSoundCreate");
364:
365: if (!pDirectSoundCreate)
366: {
367: Com_Printf ("*** couldn't get DS proc addr ***\n");
368: return SIS_FAILURE;
369: }
370: }
371:
372: Com_DPrintf( "...creating DS object: " );
373: while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK )
374: {
375: if (hresult != DSERR_ALLOCATED)
376: {
377: Com_Printf( "failed\n" );
378: return SIS_FAILURE;
379: }
380:
381: if (MessageBox (NULL,
382: "The sound hardware is in use by another app.\n\n"
383: "Select Retry to try to start sound again or Cancel to run Quake with no sound.",
384: "Sound not available",
385: MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
386: {
387: Com_Printf ("failed, hardware already in use\n" );
388: return SIS_NOTAVAIL;
389: }
390: }
391: Com_DPrintf( "ok\n" );
392:
393: dscaps.dwSize = sizeof(dscaps);
394:
395: if ( DS_OK != pDS->lpVtbl->GetCaps( pDS, &dscaps ) )
396: {
397: Com_Printf ("*** couldn't get DS caps ***\n");
398: }
399:
400: if ( dscaps.dwFlags & DSCAPS_EMULDRIVER )
401: {
402: Com_DPrintf ("...no DSound driver found\n" );
403: FreeSound();
404: return SIS_FAILURE;
405: }
406:
407: if ( !DS_CreateBuffers() )
408: return SIS_FAILURE;
409:
410: dsound_init = true;
411:
412: Com_DPrintf("...completed successfully\n" );
413:
414: return SIS_SUCCESS;
415: }
416:
417:
418: /*
419: ==================
420: SNDDM_InitWav
421:
422: Crappy windows multimedia base
423: ==================
424: */
425: qboolean SNDDMA_InitWav (void)
426: {
427: WAVEFORMATEX format;
428: int i;
429: HRESULT hr;
430:
431: Com_Printf( "Initializing wave sound\n" );
432:
433: snd_sent = 0;
434: snd_completed = 0;
435:
436: dma.channels = 2;
437: dma.samplebits = 16;
438:
439: if (s_khz->value == 44)
440: dma.speed = 44100;
441: if (s_khz->value == 22)
442: dma.speed = 22050;
443: else
444: dma.speed = 11025;
445:
446: memset (&format, 0, sizeof(format));
447: format.wFormatTag = WAVE_FORMAT_PCM;
448: format.nChannels = dma.channels;
449: format.wBitsPerSample = dma.samplebits;
450: format.nSamplesPerSec = dma.speed;
451: format.nBlockAlign = format.nChannels
452: *format.wBitsPerSample / 8;
453: format.cbSize = 0;
454: format.nAvgBytesPerSec = format.nSamplesPerSec
455: *format.nBlockAlign;
456:
457: /* Open a waveform device for output using window callback. */
458: Com_DPrintf ("...opening waveform device: ");
459: while ((hr = waveOutOpen((LPHWAVEOUT)&hWaveOut, WAVE_MAPPER,
460: &format,
461: 0, 0L, CALLBACK_NULL)) != MMSYSERR_NOERROR)
462: {
463: if (hr != MMSYSERR_ALLOCATED)
464: {
465: Com_Printf ("failed\n");
466: return false;
467: }
468:
469: if (MessageBox (NULL,
470: "The sound hardware is in use by another app.\n\n"
471: "Select Retry to try to start sound again or Cancel to run Quake 2 with no sound.",
472: "Sound not available",
473: MB_RETRYCANCEL | MB_SETFOREGROUND | MB_ICONEXCLAMATION) != IDRETRY)
474: {
475: Com_Printf ("hw in use\n" );
476: return false;
477: }
478: }
479: Com_DPrintf( "ok\n" );
480:
481: /*
482: * Allocate and lock memory for the waveform data. The memory
483: * for waveform data must be globally allocated with
484: * GMEM_MOVEABLE and GMEM_SHARE flags.
485:
486: */
487: Com_DPrintf ("...allocating waveform buffer: ");
488: gSndBufSize = WAV_BUFFERS*WAV_BUFFER_SIZE;
489: hData = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, gSndBufSize);
490: if (!hData)
491: {
492: Com_Printf( " failed\n" );
493: FreeSound ();
494: return false;
495: }
496: Com_DPrintf( "ok\n" );
497:
498: Com_DPrintf ("...locking waveform buffer: ");
499: lpData = GlobalLock(hData);
500: if (!lpData)
501: {
502: Com_Printf( " failed\n" );
503: FreeSound ();
504: return false;
505: }
506: memset (lpData, 0, gSndBufSize);
507: Com_DPrintf( "ok\n" );
508:
509: /*
510: * Allocate and lock memory for the header. This memory must
511: * also be globally allocated with GMEM_MOVEABLE and
512: * GMEM_SHARE flags.
513: */
514: Com_DPrintf ("...allocating waveform header: ");
515: hWaveHdr = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE,
516: (DWORD) sizeof(WAVEHDR) * WAV_BUFFERS);
517:
518: if (hWaveHdr == NULL)
519: {
520: Com_Printf( "failed\n" );
521: FreeSound ();
522: return false;
523: }
524: Com_DPrintf( "ok\n" );
525:
526: Com_DPrintf ("...locking waveform header: ");
527: lpWaveHdr = (LPWAVEHDR) GlobalLock(hWaveHdr);
528:
529: if (lpWaveHdr == NULL)
530: {
531: Com_Printf( "failed\n" );
532: FreeSound ();
533: return false;
534: }
535: memset (lpWaveHdr, 0, sizeof(WAVEHDR) * WAV_BUFFERS);
536: Com_DPrintf( "ok\n" );
537:
538: /* After allocation, set up and prepare headers. */
539: Com_DPrintf ("...preparing headers: ");
540: for (i=0 ; i<WAV_BUFFERS ; i++)
541: {
542: lpWaveHdr[i].dwBufferLength = WAV_BUFFER_SIZE;
543: lpWaveHdr[i].lpData = lpData + i*WAV_BUFFER_SIZE;
544:
545: if (waveOutPrepareHeader(hWaveOut, lpWaveHdr+i, sizeof(WAVEHDR)) !=
546: MMSYSERR_NOERROR)
547: {
548: Com_Printf ("failed\n");
549: FreeSound ();
550: return false;
551: }
552: }
553: Com_DPrintf ("ok\n");
554:
555: dma.samples = gSndBufSize/(dma.samplebits/8);
556: dma.samplepos = 0;
557: dma.submission_chunk = 512;
558: dma.buffer = (unsigned char *) lpData;
559: sample16 = (dma.samplebits/8) - 1;
560:
561: wav_init = true;
562:
563: return true;
564: }
565:
566: /*
567: ==================
568: SNDDMA_Init
569:
570: Try to find a sound device to mix for.
571: Returns false if nothing is found.
572: ==================
573: */
574: int SNDDMA_Init(void)
575: {
576: sndinitstat stat;
577:
578: memset ((void *)&dma, 0, sizeof (dma));
579:
580: s_wavonly = Cvar_Get ("s_wavonly", "0", 0);
581:
582: dsound_init = wav_init = 0;
583:
584: stat = SIS_FAILURE; // assume DirectSound won't initialize
585:
586: /* Init DirectSound */
587: if (!s_wavonly->value)
588: {
589: if (snd_firsttime || snd_isdirect)
590: {
591: stat = SNDDMA_InitDirect ();
592:
593: if (stat == SIS_SUCCESS)
594: {
595: snd_isdirect = true;
596:
597: if (snd_firsttime)
598: Com_Printf ("dsound init succeeded\n" );
599: }
600: else
601: {
602: snd_isdirect = false;
603: Com_Printf ("*** dsound init failed ***\n");
604: }
605: }
606: }
607:
608: // if DirectSound didn't succeed in initializing, try to initialize
609: // waveOut sound, unless DirectSound failed because the hardware is
610: // already allocated (in which case the user has already chosen not
611: // to have sound)
612: if (!dsound_init && (stat != SIS_NOTAVAIL))
613: {
614: if (snd_firsttime || snd_iswave)
615: {
616:
617: snd_iswave = SNDDMA_InitWav ();
618:
619: if (snd_iswave)
620: {
621: if (snd_firsttime)
622: Com_Printf ("Wave sound init succeeded\n");
623: }
624: else
625: {
626: Com_Printf ("Wave sound init failed\n");
627: }
628: }
629: }
630:
631: snd_firsttime = false;
632:
633: snd_buffer_count = 1;
634:
635: if (!dsound_init && !wav_init)
636: {
637: if (snd_firsttime)
638: Com_Printf ("*** No sound device initialized ***\n");
639:
640: return 0;
641: }
642:
643: return 1;
644: }
645:
646: /*
647: ==============
648: SNDDMA_GetDMAPos
649:
650: return the current sample position (in mono samples read)
651: inside the recirculating dma buffer, so the mixing code will know
652: how many sample are required to fill it up.
653: ===============
654: */
655: int SNDDMA_GetDMAPos(void)
656: {
657: MMTIME mmtime;
658: int s;
659: DWORD dwWrite;
660:
661: if (dsound_init)
662: {
663: mmtime.wType = TIME_SAMPLES;
664: pDSBuf->lpVtbl->GetCurrentPosition(pDSBuf, &mmtime.u.sample, &dwWrite);
665: s = mmtime.u.sample - mmstarttime.u.sample;
666: }
667: else if (wav_init)
668: {
669: s = snd_sent * WAV_BUFFER_SIZE;
670: }
671:
672:
673: s >>= sample16;
674:
675: s &= (dma.samples-1);
676:
677: return s;
678: }
679:
680: /*
681: ==============
682: SNDDMA_BeginPainting
683:
684: Makes sure dma.buffer is valid
685: ===============
686: */
687: DWORD locksize;
688: void SNDDMA_BeginPainting (void)
689: {
690: int reps;
691: DWORD dwSize2;
692: DWORD *pbuf, *pbuf2;
693: HRESULT hresult;
694: DWORD dwStatus;
695:
696: if (!pDSBuf)
697: return;
698:
699: // if the buffer was lost or stopped, restore it and/or restart it
700: if (pDSBuf->lpVtbl->GetStatus (pDSBuf, &dwStatus) != DS_OK)
701: Com_Printf ("Couldn't get sound buffer status\n");
702:
703: if (dwStatus & DSBSTATUS_BUFFERLOST)
704: pDSBuf->lpVtbl->Restore (pDSBuf);
705:
706: if (!(dwStatus & DSBSTATUS_PLAYING))
707: pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING);
708:
709: // lock the dsound buffer
710:
711: reps = 0;
712: dma.buffer = NULL;
713:
714: while ((hresult = pDSBuf->lpVtbl->Lock(pDSBuf, 0, gSndBufSize, &pbuf, &locksize,
715: &pbuf2, &dwSize2, 0)) != DS_OK)
716: {
717: if (hresult != DSERR_BUFFERLOST)
718: {
719: Com_Printf( "S_TransferStereo16: Lock failed with error '%s'\n", DSoundError( hresult ) );
720: S_Shutdown ();
721: return;
722: }
723: else
724: {
725: pDSBuf->lpVtbl->Restore( pDSBuf );
726: }
727:
728: if (++reps > 2)
729: return;
730: }
731: dma.buffer = (unsigned char *)pbuf;
732: }
733:
734: /*
735: ==============
736: SNDDMA_Submit
737:
738: Send sound to device if buffer isn't really the dma buffer
739: Also unlocks the dsound buffer
740: ===============
741: */
742: void SNDDMA_Submit(void)
743: {
744: LPWAVEHDR h;
745: int wResult;
746:
747: if (!dma.buffer)
748: return;
749:
750: // unlock the dsound buffer
751: if (pDSBuf)
752: pDSBuf->lpVtbl->Unlock(pDSBuf, dma.buffer, locksize, NULL, 0);
753:
754: if (!wav_init)
755: return;
756:
757: //
758: // find which sound blocks have completed
759: //
760: while (1)
761: {
762: if ( snd_completed == snd_sent )
763: {
764: Com_DPrintf ("Sound overrun\n");
765: break;
766: }
767:
768: if ( ! (lpWaveHdr[ snd_completed & WAV_MASK].dwFlags & WHDR_DONE) )
769: {
770: break;
771: }
772:
773: snd_completed++; // this buffer has been played
774: }
775:
776: //Com_Printf ("completed %i\n", snd_completed);
777: //
778: // submit a few new sound blocks
779: //
780: while (((snd_sent - snd_completed) >> sample16) < 8)
781: {
782: h = lpWaveHdr + ( snd_sent&WAV_MASK );
783: if (paintedtime/256 <= snd_sent)
784: break; // Com_Printf ("submit overrun\n");
785: //Com_Printf ("send %i\n", snd_sent);
786: snd_sent++;
787: /*
788: * Now the data block can be sent to the output device. The
789: * waveOutWrite function returns immediately and waveform
790: * data is sent to the output device in the background.
791: */
792: wResult = waveOutWrite(hWaveOut, h, sizeof(WAVEHDR));
793:
794: if (wResult != MMSYSERR_NOERROR)
795: {
796: Com_Printf ("Failed to write block to device\n");
797: FreeSound ();
798: return;
799: }
800: }
801: }
802:
803: /*
804: ==============
805: SNDDMA_Shutdown
806:
807: Reset the sound device for exiting
808: ===============
809: */
810: void SNDDMA_Shutdown(void)
811: {
812: FreeSound ();
813: }
814:
815:
816: /*
817: ===========
818: S_Activate
819:
820: Called when the main window gains or loses focus.
821: The window have been destroyed and recreated
822: between a deactivate and an activate.
823: ===========
824: */
825: void S_Activate (qboolean active)
826: {
827: if ( active )
828: {
829: if ( pDS && cl_hwnd && snd_isdirect )
830: {
831: DS_CreateBuffers();
832: }
833: }
834: else
835: {
836: if ( pDS && cl_hwnd && snd_isdirect )
837: {
838: DS_DestroyBuffers();
839: }
840: }
841: }
842:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.