icculus quake2 doxygen  1.0 dev
snd_win.c
Go to the documentation of this file.
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 
37 
39 
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 
67 
68 MMTIME mmstarttime;
69 
70 LPDIRECTSOUND pDS;
71 LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf;
72 
73 HINSTANCE hInstDS;
74 
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 */
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 
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",
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 
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 )
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 */
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 */
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: ");
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 
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  {
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 
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 */
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  {
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 */
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  {
851  }
852  }
853  else
854  {
855  if ( pDS && cl_hwnd && snd_isdirect )
856  {
858  }
859  }
860 }
861 
lplpDS
LPDIRECTSOUND FAR * lplpDS
Definition: snd_win.c:28
hInstDS
HINSTANCE hInstDS
Definition: snd_win.c:73
snd_firsttime
static qboolean snd_firsttime
Definition: snd_win.c:42
WAV_BUFFERS
#define WAV_BUFFERS
Definition: snd_win.c:31
SNDDMA_InitDirect
qboolean SNDDMA_InitDirect(void)
Definition: snd_win.c:352
lpData
HPSTR lpData
Definition: snd_win.c:57
SIS_SUCCESS
@ SIS_SUCCESS
Definition: snd_win.c:36
lpWaveHdr
LPWAVEHDR lpWaveHdr
Definition: snd_win.c:60
WAV_MASK
#define WAV_MASK
Definition: snd_win.c:32
pDS
LPDIRECTSOUND pDS
Definition: snd_win.c:70
sample16
static int sample16
Definition: snd_win.c:47
qboolean
qboolean
Definition: q_shared.h:56
i
int i
Definition: q_shared.c:305
snd_iswave
static qboolean snd_iswave
Definition: snd_win.c:42
dma_t::submission_chunk
int submission_chunk
Definition: snd_loc.h:67
winquake.h
primary_format_set
static qboolean primary_format_set
Definition: snd_win.c:43
SNDDMA_Init
int SNDDMA_Init(void)
Definition: snd_win.c:593
dma_t::samples
int samples
Definition: snd_loc.h:66
wavecaps
WAVEOUTCAPS wavecaps
Definition: snd_win.c:64
DS_CreateBuffers
static qboolean DS_CreateBuffers(void)
Definition: snd_win.c:100
Cvar_Get
cvar_t * Cvar_Get(char *var_name, char *var_value, int flags)
Definition: cvar.c:127
cvar_s
Definition: q_shared.h:317
s_primary
cvar_t * s_primary
Definition: snd_dma.c:80
snd_buffer_count
static int snd_buffer_count
Definition: snd_win.c:46
DSoundError
static const char * DSoundError(int error)
Definition: snd_win.c:80
SNDDMA_Submit
void SNDDMA_Submit(void)
Definition: snd_win.c:761
dma_t::buffer
byte * buffer
Definition: snd_loc.h:71
dma_t::channels
int channels
Definition: snd_loc.h:65
hData
HANDLE hData
Definition: snd_win.c:56
paintedtime
int paintedtime
Definition: snd_dma.c:57
SNDDMA_InitWav
qboolean SNDDMA_InitWav(void)
Definition: snd_win.c:444
locksize
DWORD locksize
Definition: snd_win.c:706
lpData2
HPSTR lpData2
Definition: snd_win.c:57
pDSBuf
LPDIRECTSOUNDBUFFER pDSBuf
Definition: snd_win.c:71
snd_sent
static int snd_sent
Definition: snd_win.c:48
snd_isdirect
static qboolean snd_isdirect
Definition: snd_win.c:42
cl_hwnd
HWND cl_hwnd
Definition: vid_dll.c:53
S_Shutdown
void S_Shutdown(void)
Definition: snd_dma.c:164
cvar_s::value
float value
Definition: q_shared.h:324
dma_t::speed
int speed
Definition: snd_loc.h:70
hWaveOut
HWAVEOUT hWaveOut
Definition: snd_win.c:62
wav_init
static qboolean wav_init
Definition: snd_win.c:41
SECONDARY_BUFFER_SIZE
#define SECONDARY_BUFFER_SIZE
Definition: snd_win.c:34
NULL
#define NULL
Definition: q_shared.h:60
dsound_init
static qboolean dsound_init
Definition: snd_win.c:40
dma
dma_t dma
Definition: snd_dma.c:47
snd_completed
static int snd_completed
Definition: snd_win.c:48
SNDDMA_GetDMAPos
int SNDDMA_GetDMAPos(void)
Definition: snd_win.c:674
s_wavonly
cvar_t * s_wavonly
Definition: snd_win.c:38
SIS_FAILURE
@ SIS_FAILURE
Definition: snd_win.c:36
pDSPBuf
LPDIRECTSOUNDBUFFER pDSPBuf
Definition: snd_win.c:71
SNDDMA_BeginPainting
void SNDDMA_BeginPainting(void)
Definition: snd_win.c:707
dma_t::samplepos
int samplepos
Definition: snd_loc.h:68
SIS_NOTAVAIL
@ SIS_NOTAVAIL
Definition: snd_win.c:36
format
GLsizei GLenum format
Definition: qgl_win.c:131
Com_DPrintf
void Com_DPrintf(char *fmt,...)
Definition: common.c:155
S_Activate
void S_Activate(qboolean active)
Definition: snd_win.c:844
DWORD
DWORD
Definition: qgl_win.c:49
mmstarttime
MMTIME mmstarttime
Definition: snd_win.c:68
Com_Printf
void Com_Printf(char *fmt,...)
Definition: common.c:102
dma_t::samplebits
int samplebits
Definition: snd_loc.h:69
sndinitstat
sndinitstat
Definition: snd_win.c:36
FreeSound
void FreeSound(void)
Definition: snd_win.c:280
hWaveHdr
HGLOBAL hWaveHdr
Definition: snd_win.c:59
SNDDMA_Shutdown
void SNDDMA_Shutdown(void)
Definition: snd_win.c:829
iDirectSoundCreate
#define iDirectSoundCreate(a, b, c)
Definition: snd_win.c:26
WAV_BUFFER_SIZE
#define WAV_BUFFER_SIZE
Definition: snd_win.c:33
DS_DestroyBuffers
static void DS_DestroyBuffers(void)
Definition: snd_win.c:247
HRESULT
HRESULT(WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID
pUnkOuter
LPDIRECTSOUND FAR IUnknown FAR * pUnkOuter
Definition: snd_win.c:28
gSndBufSize
DWORD gSndBufSize
Definition: snd_win.c:66
s_khz
cvar_t * s_khz
Definition: snd_dma.c:77