Annotation of quake2/win32/snd_win.c, revision 1.1.1.2

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.