From 5744aa8d9efb3525c4bd7d46559adbd0b8cb571e Mon Sep 17 00:00:00 2001 From: Alibek Omarov Date: Tue, 17 Apr 2018 03:44:53 +0300 Subject: [PATCH] Add SDL sound backend --- engine/client/s_backend.c | 483 -------------------------------- engine/client/s_main.c | 6 +- engine/client/sound.h | 13 +- engine/platform/sdl/s_backend.c | 261 +++++++++++++++++ 4 files changed, 277 insertions(+), 486 deletions(-) delete mode 100644 engine/client/s_backend.c create mode 100644 engine/platform/sdl/s_backend.c diff --git a/engine/client/s_backend.c b/engine/client/s_backend.c deleted file mode 100644 index d234be55..00000000 --- a/engine/client/s_backend.c +++ /dev/null @@ -1,483 +0,0 @@ -/* -s_backend.c - sound hardware output -Copyright (C) 2009 Uncle Mike - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. -*/ - -#include "common.h" -#include "sound.h" -#include - -#define iDirectSoundCreate( a, b, c ) pDirectSoundCreate( a, b, c ) - -static HRESULT ( _stdcall *pDirectSoundCreate)(GUID* lpGUID, LPDIRECTSOUND* lpDS, IUnknown* pUnkOuter ); - -static dllfunc_t dsound_funcs[] = -{ -{ "DirectSoundCreate", (void **) &pDirectSoundCreate }, -{ NULL, NULL } -}; - -dll_info_t dsound_dll = { "dsound.dll", dsound_funcs, false }; - -#define SAMPLE_16BIT_SHIFT 1 -#define SECONDARY_BUFFER_SIZE 0x10000 - -typedef enum -{ - SIS_SUCCESS, - SIS_FAILURE, - SIS_NOTAVAIL -} si_state_t; - -static qboolean snd_firsttime = true; -static qboolean primary_format_set; -static HWND snd_hwnd; - -/* -======================================================================= -Global variables. Must be visible to window-procedure function -so it can unlock and free the data block after it has been played. -======================================================================= -*/ -static DWORD locksize; -static HPSTR lpData, lpData2; -static DWORD gSndBufSize; -static MMTIME mmstarttime; -static LPDIRECTSOUNDBUFFER pDSBuf, pDSPBuf; -static LPDIRECTSOUND pDS; - -qboolean SNDDMA_InitDirect( void *hInst ); -void SNDDMA_FreeSound( void ); - -static const char *DSoundError( int error ) -{ - switch( error ) - { - case DSERR_BUFFERLOST: - return "buffer is lost"; - case DSERR_INVALIDCALL: - return "invalid call"; - case DSERR_INVALIDPARAM: - return "invalid param"; - case DSERR_PRIOLEVELNEEDED: - return "invalid priority level"; - } - - return "unknown error"; -} - -/* -================== -DS_CreateBuffers -================== -*/ -static qboolean DS_CreateBuffers( void *hInst ) -{ - WAVEFORMATEX pformat, format; - DSBCAPS dsbcaps; - DSBUFFERDESC dsbuf; - - 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; - - if( pDS->lpVtbl->SetCooperativeLevel( pDS, hInst, DSSCL_EXCLUSIVE ) != DS_OK ) - { - Con_DPrintf( S_ERROR "DirectSound: failed to set EXCLUSIVE coop level\n" ); - SNDDMA_FreeSound(); - return false; - } - - // get access to the primary buffer, if possible, so we can set the sound hardware format - memset( &dsbuf, 0, sizeof( dsbuf )); - dsbuf.dwSize = sizeof( DSBUFFERDESC ); - dsbuf.dwFlags = DSBCAPS_PRIMARYBUFFER; - dsbuf.dwBufferBytes = 0; - dsbuf.lpwfxFormat = NULL; - - memset( &dsbcaps, 0, sizeof( dsbcaps )); - dsbcaps.dwSize = sizeof( dsbcaps ); - primary_format_set = false; - - if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSPBuf, NULL ) == DS_OK ) - { - pformat = format; - - if( pDSPBuf->lpVtbl->SetFormat( pDSPBuf, &pformat ) != DS_OK ) - { - if( snd_firsttime ) - Con_DPrintf( S_ERROR "DirectSound: failed to set primary sound format\n" ); - } - else - { - primary_format_set = true; - } - } - - // create the secondary buffer we'll actually work with - memset( &dsbuf, 0, sizeof( dsbuf )); - dsbuf.dwSize = sizeof( DSBUFFERDESC ); - dsbuf.dwFlags = (DSBCAPS_CTRLFREQUENCY|DSBCAPS_LOCSOFTWARE); - dsbuf.dwBufferBytes = SECONDARY_BUFFER_SIZE; - dsbuf.lpwfxFormat = &format; - - memset( &dsbcaps, 0, sizeof( dsbcaps )); - dsbcaps.dwSize = sizeof( dsbcaps ); - - if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) != DS_OK ) - { - // couldn't get hardware, fallback to software. - dsbuf.dwFlags = (DSBCAPS_LOCSOFTWARE|DSBCAPS_GETCURRENTPOSITION2); - - if( pDS->lpVtbl->CreateSoundBuffer( pDS, &dsbuf, &pDSBuf, NULL ) != DS_OK ) - { - Con_DPrintf( S_ERROR "DirectSound: failed to create secondary buffer\n" ); - SNDDMA_FreeSound (); - return false; - } - } - - if( pDSBuf->lpVtbl->GetCaps( pDSBuf, &dsbcaps ) != DS_OK ) - { - Con_DPrintf( S_ERROR "DirectSound: failed to get capabilities\n" ); - SNDDMA_FreeSound (); - return false; - } - - // make sure mixer is active - if( pDSBuf->lpVtbl->Play( pDSBuf, 0, 0, DSBPLAY_LOOPING ) != DS_OK ) - { - Con_DPrintf( S_ERROR "DirectSound: failed to create circular buffer\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 ) memset( dma.buffer, 0, dma.samples * 2 ); - SNDDMA_Submit(); - - return true; -} - -/* -================== -DS_DestroyBuffers -================== -*/ -static void DS_DestroyBuffers( void ) -{ - if( pDS ) pDS->lpVtbl->SetCooperativeLevel( pDS, snd_hwnd, DSSCL_NORMAL ); - - if( pDSBuf ) - { - pDSBuf->lpVtbl->Stop( pDSBuf ); - pDSBuf->lpVtbl->Release( pDSBuf ); - } - - // only release primary buffer if it's not also the mixing buffer we just released - if( pDSPBuf && ( pDSBuf != pDSPBuf )) - pDSPBuf->lpVtbl->Release( pDSPBuf ); - - dma.buffer = NULL; - pDSPBuf = NULL; - pDSBuf = NULL; -} - -/* -================== -SNDDMA_LockSound -================== -*/ -void SNDDMA_LockSound( void ) -{ - if( pDSBuf != NULL ) - pDSBuf->lpVtbl->Stop( pDSBuf ); -} - -/* -================== -SNDDMA_LockSound -================== -*/ -void SNDDMA_UnlockSound( void ) -{ - if( pDSBuf != NULL ) - pDSBuf->lpVtbl->Play( pDSBuf, 0, 0, DSBPLAY_LOOPING ); -} - -/* -================== -SNDDMA_FreeSound -================== -*/ -void SNDDMA_FreeSound( void ) -{ - if( pDS ) - { - DS_DestroyBuffers(); - pDS->lpVtbl->Release( pDS ); - Sys_FreeLibrary( &dsound_dll ); - } - - lpData = NULL; - pDSPBuf = NULL; - pDSBuf = NULL; - pDS = NULL; -} - -/* -================== -SNDDMA_InitDirect - -Direct-Sound support -================== -*/ -si_state_t SNDDMA_InitDirect( void *hInst ) -{ - DSCAPS dscaps; - HRESULT hresult; - - if( !dsound_dll.link ) - { - if( !Sys_LoadLibrary( &dsound_dll )) - return SIS_FAILURE; - } - - if(( hresult = iDirectSoundCreate( NULL, &pDS, NULL )) != DS_OK ) - { - if( hresult != DSERR_ALLOCATED ) - return SIS_FAILURE; - - Con_DPrintf( S_ERROR "DirectSound: hardware already in use\n" ); - return SIS_NOTAVAIL; - } - - dscaps.dwSize = sizeof( dscaps ); - - if( pDS->lpVtbl->GetCaps( pDS, &dscaps ) != DS_OK ) - Con_DPrintf( S_ERROR "DirectSound: failed to get capabilities\n" ); - - if( FBitSet( dscaps.dwFlags, DSCAPS_EMULDRIVER )) - { - Con_DPrintf( S_ERROR "DirectSound: driver not installed\n" ); - SNDDMA_FreeSound(); - return SIS_FAILURE; - } - - if( !DS_CreateBuffers( hInst )) - return SIS_FAILURE; - - return SIS_SUCCESS; -} - -/* -================== -SNDDMA_Init - -Try to find a sound device to mix for. -Returns false if nothing is found. -================== -*/ -int SNDDMA_Init( void *hInst ) -{ - // already initialized - if( dma.initialized ) return true; - - memset( &dma, 0, sizeof( dma )); - - // init DirectSound - if( SNDDMA_InitDirect( hInst ) != SIS_SUCCESS ) - return false; - - if( snd_firsttime ) - Con_Printf( "Audio: DirectSound\n" ); - dma.initialized = true; - snd_firsttime = false; - - return true; -} - -/* -============== -SNDDMA_GetDMAPos - -return the current sample position (in mono samples read) -inside the recirculating dma buffer, so the mixing code will know -how many sample are required to fill it up. -=============== -*/ -int SNDDMA_GetDMAPos( void ) -{ - int s; - MMTIME mmtime; - DWORD dwWrite; - - if( !dma.initialized ) - return 0; - - mmtime.wType = TIME_SAMPLES; - pDSBuf->lpVtbl->GetCurrentPosition( pDSBuf, &mmtime.u.sample, &dwWrite ); - s = mmtime.u.sample - mmstarttime.u.sample; - - s >>= SAMPLE_16BIT_SHIFT; - s &= (dma.samples - 1); - - return s; -} - -/* -============== -SNDDMA_GetSoundtime - -update global soundtime -=============== -*/ -int SNDDMA_GetSoundtime( void ) -{ - static int buffers, oldsamplepos; - int samplepos, fullsamples; - - fullsamples = dma.samples / 2; - - // it is possible to miscount buffers - // if it has wrapped twice between - // calls to S_Update. Oh well. - samplepos = SNDDMA_GetDMAPos(); - - if( samplepos < oldsamplepos ) - { - buffers++; // buffer wrapped - - if( paintedtime > 0x40000000 ) - { - // time to chop things off to avoid 32 bit limits - buffers = 0; - paintedtime = fullsamples; - S_StopAllSounds( true ); - } - } - - oldsamplepos = samplepos; - - return (buffers * fullsamples + samplepos / 2); -} - -/* -============== -SNDDMA_BeginPainting - -Makes sure dma.buffer is valid -=============== -*/ -void SNDDMA_BeginPainting( void ) -{ - int reps; - DWORD dwSize2; - DWORD *pbuf, *pbuf2; - HRESULT hr; - DWORD dwStatus; - - if( !pDSBuf ) return; - - // if the buffer was lost or stopped, restore it and/or restart it - if( pDSBuf->lpVtbl->GetStatus( pDSBuf, &dwStatus ) != DS_OK ) - Con_DPrintf( S_ERROR "BeginPainting: couldn't get sound buffer status\n" ); - - if( dwStatus & DSBSTATUS_BUFFERLOST ) - pDSBuf->lpVtbl->Restore( pDSBuf ); - - if( !FBitSet( dwStatus, DSBSTATUS_PLAYING )) - pDSBuf->lpVtbl->Play( pDSBuf, 0, 0, DSBPLAY_LOOPING ); - - // lock the dsound buffer - dma.buffer = NULL; - reps = 0; - - while(( hr = pDSBuf->lpVtbl->Lock( pDSBuf, 0, gSndBufSize, &pbuf, &locksize, &pbuf2, &dwSize2, 0 )) != DS_OK ) - { - if( hr != DSERR_BUFFERLOST ) - { - Con_DPrintf( S_ERROR "BeginPainting: %s\n", DSoundError( hr )); - S_Shutdown (); - return; - } - else pDSBuf->lpVtbl->Restore( pDSBuf ); - if( ++reps > 2 ) return; - } - - dma.buffer = (byte *)pbuf; -} - -/* -============== -SNDDMA_Submit - -Send sound to device if buffer isn't really the dma buffer -Also unlocks the dsound buffer -=============== -*/ -void SNDDMA_Submit( void ) -{ - if( !dma.buffer ) return; - // unlock the dsound buffer - if( pDSBuf ) pDSBuf->lpVtbl->Unlock( pDSBuf, dma.buffer, locksize, NULL, 0 ); -} - -/* -============== -SNDDMA_Shutdown - -Reset the sound device for exiting -=============== -*/ -void SNDDMA_Shutdown( void ) -{ - if( !dma.initialized ) return; - dma.initialized = false; - SNDDMA_FreeSound(); -} - -/* -=========== -S_Activate - -Called when the main window gains or loses focus. -The window have been destroyed and recreated -between a deactivate and an activate. -=========== -*/ -void S_Activate( qboolean active, void *hInst ) -{ - if( !dma.initialized ) return; - snd_hwnd = (HWND)hInst; - - if( !pDS || !snd_hwnd ) - return; - - if( active ) - DS_CreateBuffers( snd_hwnd ); - else DS_DestroyBuffers(); -} \ No newline at end of file diff --git a/engine/client/s_main.c b/engine/client/s_main.c index 6d3eb713..2942f5e2 100644 --- a/engine/client/s_main.c +++ b/engine/client/s_main.c @@ -50,11 +50,13 @@ convar_t *snd_foliage_db_loss; convar_t *snd_gain; convar_t *snd_gain_max; convar_t *snd_gain_min; +convar_t *snd_mute_losefocus; convar_t *s_refdist; convar_t *s_refdb; convar_t *s_cull; // cull sounds by geometry convar_t *s_test; // cvar for testing new effects convar_t *s_phs; +convar_t *s_samplecount; /* ============================================================================= @@ -2172,12 +2174,14 @@ qboolean S_Init( void ) snd_foliage_db_loss = Cvar_Get( "snd_foliage_db_loss", "4", 0, "foliage loss factor" ); snd_gain_max = Cvar_Get( "snd_gain_max", "1", 0, "gain maximal threshold" ); snd_gain_min = Cvar_Get( "snd_gain_min", "0.01", 0, "gain minimal threshold" ); + snd_mute_losefocus = Cvar_Get( "snd_mute_losefocus", "1", FCVAR_ARCHIVE, "silence the audio when game window loses focus" ); s_refdist = Cvar_Get( "s_refdist", "36", 0, "soundlevel reference distance" ); s_refdb = Cvar_Get( "s_refdb", "60", 0, "soundlevel refernce dB" ); snd_gain = Cvar_Get( "snd_gain", "1", 0, "sound default gain" ); s_cull = Cvar_Get( "s_cull", "0", FCVAR_ARCHIVE, "cull sounds by geometry" ); s_test = Cvar_Get( "s_test", "0", 0, "engine developer cvar for quick testing new features" ); s_phs = Cvar_Get( "s_phs", "0", FCVAR_ARCHIVE, "cull sounds by PHS" ); + s_samplecount = Cvar_Get( "s_samplecount", "0", FCVAR_ARCHIVE, "sample count (0 for default value)" ); Cmd_AddCommand( "play", S_Play_f, "playing a specified sound file" ); Cmd_AddCommand( "playvol", S_PlayVol_f, "playing a specified sound file with specified volume" ); @@ -2241,4 +2245,4 @@ void S_Shutdown( void ) SNDDMA_Shutdown (); MIX_FreeAllPaintbuffers (); Mem_FreePool( &sndpool ); -} \ No newline at end of file +} diff --git a/engine/client/sound.h b/engine/client/sound.h index 2d790a3b..a8d7ca70 100644 --- a/engine/client/sound.h +++ b/engine/client/sound.h @@ -127,8 +127,16 @@ typedef struct float percent; } musicfade_t; +typedef struct snd_format_s +{ + unsigned int speed; + unsigned int width; + unsigned int channels; +} snd_format_t; + typedef struct { + snd_format_t format; int samples; // mono samples in buffer int samplepos; // in mono samples byte *buffer; @@ -266,6 +274,7 @@ extern convar_t *s_mixahead; extern convar_t *s_lerping; extern convar_t *dsp_off; extern convar_t *s_test; // cvar to testify new effects +extern convar_t *s_samplecount; void S_InitScaletable( void ); wavdata_t *S_LoadSound( sfx_t *sfx ); @@ -303,7 +312,7 @@ void DSP_ClearState( void ); qboolean S_Init( void ); void S_Shutdown( void ); -void S_Activate( qboolean active, void *hInst ); +void S_Activate( qboolean active ); void S_SoundList_f( void ); void S_SoundInfo_f( void ); @@ -356,4 +365,4 @@ void VOX_LoadSound( channel_t *pchan, const char *psz ); float VOX_ModifyPitch( channel_t *ch, float pitch ); int VOX_MixDataToDevice( channel_t *pChannel, int sampleCount, int outputRate, int outputOffset ); -#endif//SOUND_H \ No newline at end of file +#endif//SOUND_H diff --git a/engine/platform/sdl/s_backend.c b/engine/platform/sdl/s_backend.c new file mode 100644 index 00000000..19fbdca5 --- /dev/null +++ b/engine/platform/sdl/s_backend.c @@ -0,0 +1,261 @@ +/* +s_backend.c - sound hardware output +Copyright (C) 2009 Uncle Mike + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. +*/ + +#include "common.h" +#if XASH_SOUND == SOUND_SDL + +#include "sound.h" + +#include + +#define SAMPLE_16BIT_SHIFT 1 +#define SECONDARY_BUFFER_SIZE 0x10000 + +/* +======================================================================= +Global variables. Must be visible to window-procedure function +so it can unlock and free the data block after it has been played. +======================================================================= +*/ +static int sdl_dev; + +//static qboolean snd_firsttime = true; +//static qboolean primary_format_set; + +void SDL_SoundCallback( void *userdata, Uint8 *stream, int len ) +{ + int size = dma.samples << 1; + int pos = dma.samplepos << 1; + int wrapped = pos + len - size; + + if( wrapped < 0 ) + { + memcpy( stream, dma.buffer + pos, len ); + dma.samplepos += len >> 1; + } + else + { + int remaining = size - pos; + memcpy( stream, dma.buffer + pos, remaining ); + memcpy( stream + remaining, dma.buffer, wrapped ); + dma.samplepos = wrapped >> 1; + } +} + +/* +================== +SNDDMA_Init + +Try to find a sound device to mix for. +Returns false if nothing is found. +================== +*/ +qboolean SNDDMA_Init( void *hInst ) +{ + SDL_AudioSpec desired, obtained; + int samplecount; + + if( SDL_Init( SDL_INIT_AUDIO ) ) + { + MsgDev( D_ERROR, "Audio: SDL: %s \n", SDL_GetError( ) ); + return false; + } + +#ifdef __linux__ + setenv( "PULSE_PROP_application.name", GI->title, 1 ); + setenv( "PULSE_PROP_media.role", "game", 1 ); +#endif + + memset( &desired, 0, sizeof( desired ) ); + desired.freq = SOUND_DMA_SPEED; + desired.format = AUDIO_S16LSB; + desired.samples = 1024; + desired.channels = 2; + desired.callback = SDL_SoundCallback; + + sdl_dev = SDL_OpenAudioDevice( NULL, 0, &desired, &obtained, 0 ); + + if( !sdl_dev ) + { + Con_Printf( "Couldn't open SDL audio: %s\n", SDL_GetError( ) ); + return false; + } + + if( obtained.format != AUDIO_S16LSB ) + { + Con_Printf( "SDL audio format %d unsupported.\n", obtained.format ); + goto fail; + } + + if( obtained.channels != 1 && obtained.channels != 2 ) + { + Con_Printf( "SDL audio channels %d unsupported.\n", obtained.channels ); + goto fail; + } + + dma.format.speed = obtained.freq; + dma.format.channels = obtained.channels; + dma.format.width = 2; + samplecount = s_samplecount->value; + if( !samplecount ) + samplecount = 0x8000; + dma.samples = samplecount * obtained.channels; + dma.buffer = Z_Malloc( dma.samples * 2 ); + dma.samplepos = 0; + + Con_Printf( "Using SDL audio driver: %s @ %d Hz\n", SDL_GetCurrentAudioDriver( ), obtained.freq ); + + SDL_PauseAudioDevice( sdl_dev, 0 ); + + dma.initialized = true; + return true; + +fail: + SNDDMA_Shutdown( ); + return false; +} + +/* +============== +SNDDMA_GetDMAPos + +return the current sample position (in mono samples read) +inside the recirculating dma buffer, so the mixing code will know +how many sample are required to fill it up. +=============== +*/ +int SNDDMA_GetDMAPos( void ) +{ + return dma.samplepos; +} + +/* +============== +SNDDMA_GetSoundtime + +update global soundtime +=============== +*/ +int SNDDMA_GetSoundtime( void ) +{ + static int buffers, oldsamplepos; + int samplepos, fullsamples; + + fullsamples = dma.samples / 2; + + // it is possible to miscount buffers + // if it has wrapped twice between + // calls to S_Update. Oh well. + samplepos = SNDDMA_GetDMAPos( ); + + if( samplepos < oldsamplepos ) + { + buffers++; // buffer wrapped + + if( paintedtime > 0x40000000 ) + { + // time to chop things off to avoid 32 bit limits + buffers = 0; + paintedtime = fullsamples; + S_StopAllSounds( true ); + } + } + + oldsamplepos = samplepos; + + return ( buffers * fullsamples + samplepos / 2 ); +} + +/* +============== +SNDDMA_BeginPainting + +Makes sure dma.buffer is valid +=============== +*/ +void SNDDMA_BeginPainting( void ) +{ + SDL_LockAudio( ); +} + +/* +============== +SNDDMA_Submit + +Send sound to device if buffer isn't really the dma buffer +Also unlocks the dsound buffer +=============== +*/ +void SNDDMA_Submit( void ) +{ + SDL_UnlockAudio( ); +} + +/* +============== +SNDDMA_Shutdown + +Reset the sound device for exiting +=============== +*/ +void SNDDMA_Shutdown( void ) +{ + Con_Printf( "Shutting down audio.\n" ); + dma.initialized = false; + + if( sdl_dev ) + { + SDL_PauseAudioDevice( sdl_dev, 1 ); +#ifndef __EMSCRIPTEN__ + SDL_CloseAudioDevice( sdl_dev ); + SDL_CloseAudio( ); +#endif + } + +#ifndef __EMSCRIPTEN__ + if( SDL_WasInit( SDL_INIT_AUDIO ) ) + SDL_QuitSubSystem( SDL_INIT_AUDIO ); +#endif + + if( dma.buffer ) + { + Mem_Free( dma.buffer ); + dma.buffer = NULL; + } +} + +/* +=========== +S_PrintDeviceName +=========== +*/ +void S_PrintDeviceName( void ) +{ + Msg( "Audio: SDL (driver: %s)\n", SDL_GetCurrentAudioDriver( ) ); +} + +/* +=========== +S_Activate +Called when the main window gains or loses focus. +The window have been destroyed and recreated +between a deactivate and an activate. +=========== +*/ +void S_Activate( qboolean active ) +{ + SDL_PauseAudioDevice( sdl_dev, !active ); +} +#endif // XASH_SOUND == SOUND_SDL