|
|
1.1.1.2 ! root 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: */ 1.1 root 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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.