void S_Update_(void) { unsigned endtime; int samps; static float lastTime = 0.0f; float ma, op; float thisTime, sane; static int ot = -1; if ( !s_soundStarted || s_soundMuted ) { return; } thisTime = Com_Milliseconds(); // Updates s_soundtime S_GetSoundtime(); if (s_soundtime == ot) { return; } ot = s_soundtime; // clear any sound effects that end before the current time, // and start any new sounds S_ScanChannelStarts(); sane = thisTime - lastTime; if (sane<11) { sane = 11; // 85hz } ma = s_mixahead->value * dma.speed; op = s_mixPreStep->value + sane*dma.speed*0.01; if (op < ma) { ma = op; } // mix ahead of current position endtime = s_soundtime + ma; // mix to an even submission block size endtime = (endtime + dma.submission_chunk-1) & ~(dma.submission_chunk-1); // never mix more than the complete buffer samps = dma.samples >> (dma.channels-1); if (endtime - s_soundtime > samps) endtime = s_soundtime + samps; SNDDMA_BeginPainting (); S_PaintChannels (endtime); SNDDMA_Submit (); lastTime = thisTime; }
/* ================== S_ClearSoundBuffer If we are about to perform file access, clear the buffer so sound doesn't stutter. ================== */ void S_Base_ClearSoundBuffer( void ) { int clear; if (!s_soundStarted) return; // stop looping sounds Com_Memset(loopSounds, 0, MAX_GENTITIES*sizeof(loopSound_t)); Com_Memset(loop_channels, 0, MAX_CHANNELS*sizeof(channel_t)); numLoopChannels = 0; S_ChannelSetup(); Com_Memset(s_rawend, '\0', sizeof (s_rawend)); if (dma.samplebits == 8) clear = 0x80; else clear = 0; SNDDMA_BeginPainting (); if (dma.buffer) Com_Memset(dma.buffer, clear, dma.samples * dma.samplebits/8); SNDDMA_Submit (); }
/* ================== SNDDMA_Init Initialize direct sound Returns false if failed ================== */ qboolean SNDDMA_Init(void) { memset ((void *)&dma, 0, sizeof (dma)); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; if (s_khz->integer == 44) dma.speed = 44100; else if (s_khz->integer == 22) dma.speed = 22050; else dma.speed = 11025; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); // Hack !! dma.samples = 32768; dma.submission_chunk = 1; dma.buffer = new byte[dma.samples * 2]; Com_DPrintf("Completed successfully\n" ); return qtrue; }
void S_Update_() { guard(S_Update_); if (!sound_started) return; SNDDMA_BeginPainting(); if (!dma.buffer) return; // Updates DMA time GetSoundtime(); // check to make sure that we haven't overshot if (paintedtime < soundtime) { Com_DPrintf("S_Update_ : overflow\n"); paintedtime = soundtime; } // mix ahead of current position unsigned endtime = soundtime + appRound(s_mixahead->value * dma.speed); // mix to an even submission block size endtime = Align(endtime, dma.submission_chunk); int samps = dma.samples >> (dma.channels-1); if (endtime - soundtime > samps) endtime = soundtime + samps; S_PaintChannels(endtime); SNDDMA_Submit(); unguard; }
/* ================== S_ClearSoundBuffer If we are about to perform file access, clear the buffer so sound doesn't stutter. ================== */ void S_ClearSoundBuffer( void ) { int clear; if (!s_soundStarted) return; // stop looping sounds Com_Memset(loopSounds, 0, MAX_GENTITIES*sizeof(loopSound_t)); Com_Memset(loop_channels, 0, MAX_CHANNELS*sizeof(channel_t)); numLoopChannels = 0; S_ChannelSetup(); s_rawend = 0; if (dma.samplebits == 8) clear = 0x80; else clear = 0; SNDDMA_BeginPainting (); if (dma.buffer) // TTimo: due to a particular bug workaround in linux sound code, // have to optionally use a custom C implementation of Com_Memset // not affecting win32, we have #define Snd_Memset Com_Memset // https://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=371 Snd_Memset(dma.buffer, clear, dma.samples * dma.samplebits/8); SNDDMA_Submit (); }
/* ================== S_ClearBuffer ================== */ static void S_ClearBuffer (void) { int clear; if (!sound_started) return; #ifdef USE_OPENAL if (alSound) return; #endif s_rawend = 0; if (dma.samplebits == 8) clear = 0x80; else clear = 0; SNDDMA_BeginPainting (); if (dma.buffer) Snd_Memset(dma.buffer, clear, dma.samples * dma.samplebits/8); SNDDMA_Submit (); }
void S_ClearBuffer() { if (!sound_started) return; s_rawend = 0; int clear; if (dma.samplebits == 8) clear = 0x80; else clear = 0; SNDDMA_BeginPainting(); if (dma.buffer) memset(dma.buffer, clear, dma.samples * dma.samplebits/8); SNDDMA_Submit(); }
/* * S_Clear */ static void S_Clear( void ) { int clear; num_loopsfx = 0; S_ClearRawSounds(); if( dma.samplebits == 8 ) clear = 0x80; else clear = 0; SNDDMA_BeginPainting(); if( dma.buffer ) memset( dma.buffer, clear, dma.samples * dma.samplebits/8 ); SNDDMA_Submit(); }
void S_DMAClearBuffer( void ) { int clear; if (!dmaInit) return; /* Clear the active channels and loops */ Com_Memset( dmaLoops, 0, sizeof( dmaLoops )); Com_Memset( dmaChannels, 0, sizeof( dmaChannels )); Com_Memset( &dmaEffect, 0, sizeof( &dmaEffect )); if (dma.samplebits == 8) clear = 0x80; else clear = 0; /* Fill the dma buffer */ SNDDMA_BeginPainting (); if (dma.buffer) Snd_Memset(dma.buffer, clear, dma.samples * dma.samplebits/8); SNDDMA_Submit (); }
void S_Update_(void) { unsigned endtime; int samps; if (!sound_started) return; SNDDMA_BeginPainting (); if (!dma.buffer) return; // Updates DMA time GetSoundtime(); // check to make sure that we haven't overshot if (paintedtime < soundtime) { Com_DPrintf ("S_Update_ : overflow\n"); paintedtime = soundtime; } // mix ahead of current position endtime = soundtime + s_mixahead->value * dma.speed; //endtime = (soundtime + 4096) & ~4095; // mix to an even submission block size endtime = (endtime + dma.submission_chunk-1) & ~(dma.submission_chunk-1); samps = dma.samples >> (dma.channels-1); if (endtime - soundtime > samps) endtime = soundtime + samps; S_PaintChannels (endtime); SNDDMA_Submit (); }
void S_Base_ClearSounds(qboolean clearStreaming, qboolean clearMusic) { if (!s_soundStarted) { return; } // stop looping sounds Com_Memset(loopSounds, 0, MAX_LOOP_SOUNDS * sizeof(loopSound_t)); Com_Memset(loop_channels, 0, MAX_CHANNELS * sizeof(channel_t)); numLoopChannels = 0; numLoopSounds = 0; // moved this up so streaming sounds dont get updated with the music, below, // and leave us with a snippet off streaming sounds after we reload if (clearStreaming) { int i; streamingSound_t *ss; channel_t *ch; for (i = 0, ss = streamingSounds; i < MAX_STREAMING_SOUNDS; i++, ss++) { if (i > 0 || clearMusic) { S_StopStreamingSound(i); } } // we should also kill all channels, since we are killing streaming sounds anyway // (fixes siren in forest playing after a map_restart/loadgame ch = s_channels; for (i = 0; i < MAX_CHANNELS; i++, ch++) { if (ch->thesfx) { S_ChannelFree(ch); } } } if (!clearMusic) { S_UpdateStreamingSounds(); } if (clearStreaming && clearMusic) { int clear; if (dma.samplebits == 8) { clear = 0x80; } else { clear = 0; } SNDDMA_BeginPainting(); if (dma.buffer) { Com_Memset(dma.buffer, clear, dma.samples * dma.samplebits / 8); } SNDDMA_Submit(); // clear out channels so they don't finish playing when audio restarts S_ChannelSetup(); } }
static int SNDDMA_InitDS () { HRESULT hresult; qboolean pauseTried; DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX format; Com_Printf( "Initializing DirectSound\n"); if ( !hInstDS ) { Com_DPrintf( "...loading dsound.dll: " ); hInstDS = LoadLibrary("dsound.dll"); if ( hInstDS == NULL ) { Com_Printf ("failed\n"); return 0; } Com_DPrintf ("ok\n"); pDirectSoundCreate = (long (__stdcall *)(struct _GUID *,struct IDirectSound ** ,struct IUnknown *)) GetProcAddress(hInstDS,"DirectSoundCreate"); if ( !pDirectSoundCreate ) { Com_Printf ("*** couldn't get DS proc addr ***\n"); return 0; } } Com_DPrintf( "...creating DS object: " ); pauseTried = qfalse; while ( ( hresult = iDirectSoundCreate( NULL, &pDS, NULL ) ) != DS_OK ) { if ( hresult != DSERR_ALLOCATED ) { Com_Printf( "failed\n" ); return 0; } if ( pauseTried ) { Com_Printf ("failed, hardware already in use\n" ); return 0; } // first try just waiting five seconds and trying again // this will handle the case of a sysyem beep playing when the // game starts Com_DPrintf ("retrying...\n"); Sleep( 3000 ); pauseTried = qtrue; } Com_DPrintf( "ok\n" ); Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf("ok\n" ); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; if (s_khz->integer == 44) dma.speed = 44100; else if (s_khz->integer == 22) dma.speed = 22050; else dma.speed = 11025; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); #define idDSBCAPS_GETCURRENTPOSITION2 0x00010000 dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCHARDWARE | idDSBCAPS_GETCURRENTPOSITION2; dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; Com_DPrintf( "...creating secondary buffer: " ); if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) { dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY; hresult = pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL); if (hresult != DS_OK) { Com_Printf( "failed to create secondary buffer - %s\n", DSoundError( hresult ) ); SNDDMA_Shutdown (); return qfalse; } } Com_Printf( "locked hardware. ok\n" ); // Make sure mixer is active if ( DS_OK != pDSBuf->Play(0, 0, DSBPLAY_LOOPING) ) { Com_Printf ("*** Looped sound play failed ***\n"); SNDDMA_Shutdown (); return qfalse; } memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); // get the returned buffer size if ( DS_OK != pDSBuf->GetCaps (&dsbcaps) ) { Com_Printf ("*** GetCaps failed ***\n"); SNDDMA_Shutdown (); return qfalse; } gSndBufSize = dsbcaps.dwBufferBytes; dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; dma.samples = gSndBufSize/(dma.samplebits/8); dma.submission_chunk = 1; dma.buffer = NULL; // must be locked first sample16 = (dma.samplebits/8) - 1; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); return 1; }
int SNDDMA_InitDS () { HRESULT hresult; DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX format; int use8; // Match/Choose output directsound device SNDDMAHD_DSEnumSoundDevices(qfalse); Com_Printf( "Initializing DirectSound\n"); use8 = 1; // Create IDirectSound using the primary sound device if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8, (void **)&pDS))) { use8 = 0; if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&pDS))) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } } hresult = pDS->lpVtbl->Initialize( pDS, g_dsguid); Com_DPrintf( "ok\n" ); Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf("ok\n" ); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; if (s_khz->integer >= 44) dma.speed = 44100; else if (s_khz->integer >= 32) dma.speed = 32000; else if (s_khz->integer >= 24) dma.speed = 24000; else if (s_khz->integer >= 22) dma.speed = 22050; else dma.speed = 11025; #ifndef NO_DMAHD if (dmaHD_Enabled()) { // p5yc0runn3r - Fix dmaHD sound to 44KHz, Stereo and 16 bits per sample. dma.speed = 44100; dma.channels = 2; dma.samplebits = 16; } #endif memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); // Micah: take advantage of 2D hardware.if available. dsbuf.dwFlags = DSBCAPS_LOCHARDWARE; if (s_alttabmute->integer == 0) { // Keep playing when out of focus. dsbuf.dwFlags |= DSBCAPS_STICKYFOCUS; } if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); Com_DPrintf( "...creating secondary buffer: " ); if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { Com_Printf( "locked hardware. ok\n" ); } else { // Couldn't get hardware, fallback to software. dsbuf.dwFlags = DSBCAPS_LOCSOFTWARE; if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { Com_Printf( "failed\n" ); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf( "forced to software. ok\n" ); } // Make sure mixer is active if ( DS_OK != pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING) ) { Com_Printf ("*** Looped sound play failed ***\n"); SNDDMA_Shutdown (); return qfalse; } // get the returned buffer size if ( DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps) ) { Com_Printf ("*** GetCaps failed ***\n"); SNDDMA_Shutdown (); return qfalse; } gSndBufSize = dsbcaps.dwBufferBytes; dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; dma.samples = gSndBufSize/(dma.samplebits/8); dma.submission_chunk = 1; dma.buffer = NULL; // must be locked first sample16 = (dma.samplebits/8) - 1; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); return 1; }
/* ================== DS_CreateBuffers ================== */ static qboolean DS_CreateBuffers( void *hInst ) { DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX pformat, format; Q_memset( &format, 0, sizeof( format )); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = 2; format.wBitsPerSample = 16; format.nSamplesPerSec = SOUND_DMA_SPEED; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; format.cbSize = 0; MsgDev( D_NOTE, "DS_CreateBuffers: initialize\n" ); MsgDev( D_NOTE, "DS_CreateBuffers: setting EXCLUSIVE coop level " ); if( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, hInst, DSSCL_EXCLUSIVE )) { MsgDev( D_NOTE, "- failed\n" ); SNDDMA_FreeSound(); return false; } MsgDev( D_NOTE, "- ok\n" ); // get access to the primary buffer, if possible, so we can set the sound hardware format Q_memset( &dsbuf, 0, sizeof( dsbuf )); dsbuf.dwSize = sizeof( DSBUFFERDESC ); dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; dsbuf.dwBufferBytes = 0; dsbuf.lpwfxFormat = NULL; Q_memset( &dsbcaps, 0, sizeof( dsbcaps )); dsbcaps.dwSize = sizeof( dsbcaps ); primary_format_set = false; MsgDev( D_NOTE, "DS_CreateBuffers: creating primary buffer " ); if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSPBuf, NULL ) == DS_OK ) { pformat = format; MsgDev( D_NOTE, "- ok\n" ); if( snd_firsttime ) MsgDev( D_NOTE, "DS_CreateBuffers: setting primary sound format " ); if( pDSPBuf->lpVtbl->SetFormat( pDSPBuf, &pformat ) != DS_OK ) { if( snd_firsttime ) MsgDev( D_NOTE, "- failed\n" ); } else { if( snd_firsttime ) MsgDev( D_NOTE, "- ok\n" ); primary_format_set = true; } } else MsgDev( D_NOTE, "- failed\n" ); if( !primary_format_set || !s_primary->integer ) { // create the secondary buffer we'll actually work with Q_memset( &dsbuf, 0, sizeof( dsbuf )); dsbuf.dwSize = sizeof( DSBUFFERDESC ); dsbuf.dwFlags = (DSBCAPS_CTRLFREQUENCY|DSBCAPS_LOCSOFTWARE); dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; Q_memset( &dsbcaps, 0, sizeof( dsbcaps )); dsbcaps.dwSize = sizeof( dsbcaps ); MsgDev( D_NOTE, "DS_CreateBuffers: creating secondary buffer " ); if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) == DS_OK ) { MsgDev( D_NOTE, "- ok\n" ); } else { // couldn't get hardware, fallback to software. dsbuf.dwFlags = (DSBCAPS_LOCSOFTWARE|DSBCAPS_GETCURRENTPOSITION2); if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) != DS_OK ) { MsgDev( D_NOTE, "- failed\n" ); SNDDMA_FreeSound (); return false; } MsgDev( D_INFO, "- failed. forced to software\n" ); } if( pDSBuf->lpVtbl->GetCaps( pDSBuf, &dsbcaps ) != DS_OK ) { MsgDev( D_ERROR, "DS_CreateBuffers: GetCaps failed\n"); SNDDMA_FreeSound (); return false; } MsgDev( D_NOTE, "DS_CreateBuffers: using secondary sound buffer\n" ); } else { MsgDev( D_NOTE, "DS_CreateBuffers: using primary sound buffer\n" ); MsgDev( D_NOTE, "DS_CreateBuffers: setting WRITEPRIMARY coop level " ); if( pDS->lpVtbl->SetCooperativeLevel( pDS, hInst, DSSCL_WRITEPRIMARY ) != DS_OK ) { MsgDev( D_NOTE, "- failed\n" ); SNDDMA_FreeSound (); return false; } MsgDev( D_NOTE, "- ok\n" ); if( pDSPBuf->lpVtbl->GetCaps( pDSPBuf, &dsbcaps ) != DS_OK ) { MsgDev( D_ERROR, "DS_CreateBuffers: GetCaps failed\n"); SNDDMA_FreeSound (); return false; } pDSBuf = pDSPBuf; } // make sure mixer is active if( pDSBuf->lpVtbl->Play( pDSBuf, 0, 0, DSBPLAY_LOOPING ) != DS_OK ) { MsgDev( D_ERROR, "DS_CreateBuffers: looped sound play failed\n" ); SNDDMA_FreeSound (); return false; } // we don't want anyone to access the buffer directly w/o locking it first lpData = NULL; dma.samplepos = 0; snd_hwnd = (HWND)hInst; gSndBufSize = dsbcaps.dwBufferBytes; dma.samples = gSndBufSize / 2; dma.buffer = (byte *)lpData; SNDDMA_BeginPainting(); if( dma.buffer ) Q_memset( dma.buffer, 0, dma.samples * 2 ); SNDDMA_Submit(); return true; }
int SNDDMA_InitDS () { HRESULT hresult; DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX format; int use8; HMODULE hdsounddll; pDirectSoundEnumerate DSEnumerate; if ((hdsounddll = LoadLibrary("dsound.dll")) != NULL && (DSEnumerate = (pDirectSoundEnumerate)GetProcAddress(hdsounddll, "DirectSoundEnumerateA")) != NULL && s_dev->string != NULL && s_dev->string[0] != '\0') { Com_Printf( "^4Looking for DirectSound Device '%s'\n", s_dev->string); if (FAILED(DSEnumerate(SNDDMAHD_DSEnumCallback, NULL))) Com_Printf("^1Error Enumerating DirectSound Devices\n"); if (g_dsguid == NULL) Com_Printf("^1Device '%s' not found. ^2Using default driver.\n", s_dev->string); } Com_Printf( "Initializing DirectSound\n"); use8 = 1; // Create IDirectSound using the primary sound device if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound8, (void **)&pDS))) { use8 = 0; if( FAILED( hresult = CoCreateInstance(&CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, &IID_IDirectSound, (void **)&pDS))) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } } hresult = pDS->lpVtbl->Initialize( pDS, g_dsguid); Com_DPrintf( "ok\n" ); Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); if ( DS_OK != pDS->lpVtbl->SetCooperativeLevel( pDS, g_wv.hWnd, DSSCL_PRIORITY ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf("ok\n" ); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; if (s_khz->integer >= 44) dma.speed = 44100; else if (s_khz->integer >= 32) dma.speed = 32000; else if (s_khz->integer >= 24) dma.speed = 24000; else if (s_khz->integer >= 22) dma.speed = 22050; else dma.speed = 11025; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); // Micah: take advantage of 2D hardware.if available. dsbuf.dwFlags = DSBCAPS_LOCHARDWARE; if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); Com_DPrintf( "...creating secondary buffer: " ); if (DS_OK == pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { Com_Printf( "locked hardware. ok\n" ); } else { // Couldn't get hardware, fallback to software. dsbuf.dwFlags = DSBCAPS_LOCSOFTWARE; if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } if (DS_OK != pDS->lpVtbl->CreateSoundBuffer(pDS, &dsbuf, &pDSBuf, NULL)) { Com_Printf( "failed\n" ); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf( "forced to software. ok\n" ); } // Make sure mixer is active if ( DS_OK != pDSBuf->lpVtbl->Play(pDSBuf, 0, 0, DSBPLAY_LOOPING) ) { Com_Printf ("*** Looped sound play failed ***\n"); SNDDMA_Shutdown (); return qfalse; } // get the returned buffer size if ( DS_OK != pDSBuf->lpVtbl->GetCaps (pDSBuf, &dsbcaps) ) { Com_Printf ("*** GetCaps failed ***\n"); SNDDMA_Shutdown (); return qfalse; } gSndBufSize = dsbcaps.dwBufferBytes; dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; dma.samples = gSndBufSize/(dma.samplebits/8); dma.submission_chunk = 1; dma.buffer = NULL; // must be locked first sample16 = (dma.samplebits/8) - 1; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); return 1; }
int SNDDMA_InitDS () { HRESULT hresult; DSBUFFERDESC dsbuf; DSBCAPS dsbcaps; WAVEFORMATEX format; int use8; Com_Printf( "Initializing DirectSound\n"); use8 = 1; // Create IDirectSound using the primary sound device if( FAILED( hresult = CoCreateInstance(CLSID_DirectSound8, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound8, (void **)&pDS))) { use8 = 0; if( FAILED( hresult = CoCreateInstance(CLSID_DirectSound, NULL, CLSCTX_INPROC_SERVER, IID_IDirectSound, (void **)&pDS))) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } } hresult = pDS->Initialize( NULL); Com_DPrintf( "ok\n" ); Com_DPrintf("...setting DSSCL_PRIORITY coop level: " ); if ( DS_OK != pDS->SetCooperativeLevel( g_wv.hWnd, DSSCL_PRIORITY ) ) { Com_Printf ("failed\n"); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf("ok\n" ); // create the secondary buffer we'll actually work with dma.channels = 2; dma.samplebits = 16; if (s_khz->integer == 44) dma.speed = 44100; else if (s_khz->integer == 22) dma.speed = 22050; else dma.speed = 11025; memset (&format, 0, sizeof(format)); format.wFormatTag = WAVE_FORMAT_PCM; format.nChannels = dma.channels; format.wBitsPerSample = dma.samplebits; format.nSamplesPerSec = dma.speed; format.nBlockAlign = format.nChannels * format.wBitsPerSample / 8; format.cbSize = 0; format.nAvgBytesPerSec = format.nSamplesPerSec*format.nBlockAlign; memset (&dsbuf, 0, sizeof(dsbuf)); dsbuf.dwSize = sizeof(DSBUFFERDESC); // Micah: take advantage of 2D hardware.if available. dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCHARDWARE; if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } //#define idDSBCAPS_GETCURRENTPOSITION2 0x00010000 dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; dsbuf.lpwfxFormat = &format; memset(&dsbcaps, 0, sizeof(dsbcaps)); dsbcaps.dwSize = sizeof(dsbcaps); Com_DPrintf( "...creating secondary buffer: " ); if (DS_OK == pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) { Com_Printf( "locked hardware. ok\n" ); } else { // Couldn't get hardware, fallback to software. dsbuf.dwFlags = DSBCAPS_CTRLFREQUENCY | DSBCAPS_LOCSOFTWARE; if (use8) { dsbuf.dwFlags |= DSBCAPS_GETCURRENTPOSITION2; } if (DS_OK != pDS->CreateSoundBuffer(&dsbuf, &pDSBuf, NULL)) { Com_Printf( "failed\n" ); SNDDMA_Shutdown (); return qfalse; } Com_DPrintf( "forced to software. ok\n" ); } // Make sure mixer is active if ( DS_OK != pDSBuf->Play(0, 0, DSBPLAY_LOOPING) ) { Com_Printf ("*** Looped sound play failed ***\n"); SNDDMA_Shutdown (); return qfalse; } // get the returned buffer size if ( DS_OK != pDSBuf->GetCaps (&dsbcaps) ) { Com_Printf ("*** GetCaps failed ***\n"); SNDDMA_Shutdown (); return qfalse; } gSndBufSize = dsbcaps.dwBufferBytes; dma.channels = format.nChannels; dma.samplebits = format.wBitsPerSample; dma.speed = format.nSamplesPerSec; dma.samples = gSndBufSize/(dma.samplebits/8); dma.submission_chunk = 1; dma.buffer = NULL; // must be locked first sample16 = (dma.samplebits/8) - 1; SNDDMA_BeginPainting (); if (dma.buffer) memset(dma.buffer, 0, dma.samples * dma.samplebits/8); SNDDMA_Submit (); return 1; }
void S_Update_(void) { unsigned endtime; int samps; static float lastTime = 0.0f; float ma, op; float thisTime, sane; static int ot = -1; if (!s_soundStarted || s_soundMuted) { return; } thisTime = Sys_Milliseconds(); // Updates s_soundtime S_GetSoundtime(); if (s_soundtime == ot) { return; } ot = s_soundtime; // clear any sound effects that end before the current time, // and start any new sounds S_ScanChannelStarts(); sane = thisTime - lastTime; if (sane < 11) { sane = 11; // 85hz } ma = s_mixahead->value * dma.speed; op = s_mixPreStep->value + sane * dma.speed * 0.01; if (op < ma) { ma = op; } // mix ahead of current position endtime = s_soundtime + ma; // mix to an even submission block size endtime = (endtime + dma.submission_chunk - 1) & ~(dma.submission_chunk - 1); // never mix more than the complete buffer samps = dma.samples >> (dma.channels - 1); if (endtime - s_soundtime > samps) { endtime = s_soundtime + samps; } // global volume fading // endtime or s_paintedtime or s_soundtime... if (s_soundtime < s_volTime2) // still has fading to do { if (s_soundtime > s_volTime1) // has started fading { s_volFadeFrac = ((float)(s_soundtime - s_volTime1) / (float)(s_volTime2 - s_volTime1)); s_volCurrent = ((1.0f - s_volFadeFrac) * s_volStart + s_volFadeFrac * s_volTarget); } else { s_volCurrent = s_volStart; } } else { s_volCurrent = s_volTarget; if (s_stopSounds) { // stop playing any sounds if they are all faded out S_StopAllSounds(); s_stopSounds = qfalse; } } SNDDMA_BeginPainting(); S_PaintChannels(endtime); SNDDMA_Submit(); lastTime = thisTime; }
void S_DMA_Update( float scale ) { int ma, count; static int lastPos; int thisPos; int lastWrite, lastRead; int bufSize, bufDone; int speed; int buf[2048]; if (!dmaInit) return; bufSize = dma.samples >> (dma.channels-1); // Check for possible buffer underruns thisPos = SNDDMA_GetDMAPos() >> (dma.channels - 1); lastWrite = (lastPos <= dmaWrite) ? (dmaWrite - lastPos) : (bufSize - lastPos + dmaWrite); lastRead = ( lastPos <= thisPos ) ? (thisPos - lastPos) : (bufSize - lastPos + thisPos); if (lastRead > lastWrite) { bufDone = 0; dmaWrite = thisPos; // Com_Printf("OMG Buffer underrun\n"); } else { bufDone = lastWrite - lastRead; } // Com_Printf( "lastRead %d lastWrite %d done %d\n", lastRead, lastWrite, bufDone ); lastPos = thisPos; ma = s_mixahead->value * dma.speed; count = lastRead; if (bufDone + count < ma) { count = ma - bufDone + 1; } else if (bufDone + count > bufSize) { count = bufSize - bufDone; } if (count > sizeof(buf) / (2 * sizeof(int))) { count = sizeof(buf) / (2 * sizeof(int)); } // mix to an even submission block size count = (count + dma.submission_chunk-1) & ~(dma.submission_chunk-1); // never mix more than the complete buffer speed = (scale * (MIX_SPEED << MIX_SHIFT)) / dma.speed; /* Make sure that the speed will always go forward for very small scales */ if ( speed == 0 && scale ) speed = 1; /* Mix sound or fill with silence depending on speed */ if ( speed > 0 ) { /* mix the background track or init the buffer with silence */ S_MixBackground(&dmaBackground, speed, count, buf); S_MixChannels(dmaChannels, DMA_SNDCHANNELS, speed, count, buf); S_MixLoops(dmaLoops, DMA_LOOPCHANNELS, speed, count, buf); S_MixEffects(&dmaEffect, speed, count, buf); } else { Com_Memset(buf, 0, sizeof( buf[0] ) * count * 2); } /* Lock dma buffer and copy/clip the final data */ SNDDMA_BeginPainting (); S_MixClipOutput(count, buf, (short *)dma.buffer, dmaWrite, bufSize-1); SNDDMA_Submit (); dmaWrite += count; if (dmaWrite >= bufSize) dmaWrite -= bufSize; }