Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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