mirror of
https://github.com/nillerusr/source-engine.git
synced 2024-12-23 06:36:54 +00:00
612 lines
16 KiB
C++
612 lines
16 KiB
C++
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
//
|
||
// Purpose:
|
||
//
|
||
//===========================================================================//
|
||
|
||
#include "audio_pch.h"
|
||
#include <OpenAL/al.h>
|
||
#include <OpenAL/alc.h>
|
||
#ifdef OSX
|
||
#include <OpenAL/MacOSX_OALExtensions.h>
|
||
#endif
|
||
|
||
|
||
// memdbgon must be the last include file in a .cpp file!!!
|
||
#include "tier0/memdbgon.h"
|
||
|
||
#ifndef DEDICATED // have to test this because VPC is forcing us to compile this file.
|
||
|
||
extern bool snd_firsttime;
|
||
extern bool MIX_ScaleChannelVolume( paintbuffer_t *ppaint, channel_t *pChannel, int volume[CCHANVOLUMES], int mixchans );
|
||
extern void S_SpatializeChannel( int volume[6], int master_vol, const Vector *psourceDir, float gain, float mono );
|
||
|
||
#define NUM_BUFFERS_SOURCES 128
|
||
#define BUFF_MASK (NUM_BUFFERS_SOURCES - 1 )
|
||
#define BUFFER_SIZE 0x0400
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
//
|
||
// NOTE: This only allows 16-bit, stereo wave out
|
||
//
|
||
//-----------------------------------------------------------------------------
|
||
class CAudioDeviceOpenAL : public CAudioDeviceBase
|
||
{
|
||
public:
|
||
bool IsActive( void );
|
||
bool Init( void );
|
||
void Shutdown( void );
|
||
void PaintEnd( void );
|
||
int GetOutputPosition( void );
|
||
void ChannelReset( int entnum, int channelIndex, float distanceMod );
|
||
void Pause( void );
|
||
void UnPause( void );
|
||
float MixDryVolume( void );
|
||
bool Should3DMix( void );
|
||
void StopAllSounds( void );
|
||
|
||
int PaintBegin( float mixAheadTime, int soundtime, int paintedtime );
|
||
void ClearBuffer( void );
|
||
void UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up );
|
||
void MixBegin( int sampleCount );
|
||
void MixUpsample( int sampleCount, int filtertype );
|
||
void Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
|
||
void Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
|
||
void Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
|
||
void Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress );
|
||
|
||
void TransferSamples( int end );
|
||
void SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono);
|
||
void ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount );
|
||
|
||
const char *DeviceName( void ) { return "OpenAL"; }
|
||
int DeviceChannels( void ) { return 2; }
|
||
int DeviceSampleBits( void ) { return 16; }
|
||
int DeviceSampleBytes( void ) { return 2; }
|
||
int DeviceDmaSpeed( void ) { return SOUND_DMA_SPEED; }
|
||
int DeviceSampleCount( void ) { return m_deviceSampleCount; }
|
||
|
||
private:
|
||
void OpenWaveOut( void );
|
||
void CloseWaveOut( void );
|
||
bool ValidWaveOut( void ) const;
|
||
|
||
ALuint m_Buffer[NUM_BUFFERS_SOURCES];
|
||
ALuint m_Source[1];
|
||
int m_SndBufSize;
|
||
|
||
void *m_sndBuffers;
|
||
|
||
int m_deviceSampleCount;
|
||
|
||
int m_buffersSent;
|
||
int m_buffersCompleted;
|
||
int m_pauseCount;
|
||
bool m_bSoundsShutdown;
|
||
};
|
||
|
||
|
||
IAudioDevice *Audio_CreateOpenALDevice( void )
|
||
{
|
||
CAudioDeviceOpenAL *wave = NULL;
|
||
if ( !wave )
|
||
{
|
||
wave = new CAudioDeviceOpenAL;
|
||
}
|
||
|
||
if ( wave->Init() )
|
||
return wave;
|
||
|
||
delete wave;
|
||
wave = NULL;
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
void OnSndSurroundCvarChanged( IConVar *pVar, const char *pOldString, float flOldValue );
|
||
void OnSndSurroundLegacyChanged( IConVar *pVar, const char *pOldString, float flOldValue );
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Init, shutdown
|
||
//-----------------------------------------------------------------------------
|
||
bool CAudioDeviceOpenAL::Init( void )
|
||
{
|
||
m_SndBufSize = 0;
|
||
m_sndBuffers = NULL;
|
||
m_pauseCount = 0;
|
||
|
||
m_bSurround = false;
|
||
m_bSurroundCenter = false;
|
||
m_bHeadphone = false;
|
||
m_buffersSent = 0;
|
||
m_buffersCompleted = 0;
|
||
m_pauseCount = 0;
|
||
m_bSoundsShutdown = false;
|
||
|
||
static bool first = true;
|
||
if ( first )
|
||
{
|
||
snd_surround.SetValue( 2 );
|
||
snd_surround.InstallChangeCallback( &OnSndSurroundCvarChanged );
|
||
snd_legacy_surround.InstallChangeCallback( &OnSndSurroundLegacyChanged );
|
||
first = false;
|
||
}
|
||
|
||
OpenWaveOut();
|
||
|
||
if ( snd_firsttime )
|
||
{
|
||
DevMsg( "Wave sound initialized\n" );
|
||
}
|
||
return ValidWaveOut();
|
||
}
|
||
|
||
void CAudioDeviceOpenAL::Shutdown( void )
|
||
{
|
||
CloseWaveOut();
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// WAV out device
|
||
//-----------------------------------------------------------------------------
|
||
inline bool CAudioDeviceOpenAL::ValidWaveOut( void ) const
|
||
{
|
||
return m_sndBuffers != 0;
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Opens the windows wave out device
|
||
//-----------------------------------------------------------------------------
|
||
void CAudioDeviceOpenAL::OpenWaveOut( void )
|
||
{
|
||
m_buffersSent = 0;
|
||
m_buffersCompleted = 0;
|
||
|
||
ALenum error;
|
||
ALCcontext *newContext = NULL;
|
||
ALCdevice *newDevice = NULL;
|
||
|
||
// Create a new OpenAL Device
|
||
// Pass NULL to specify the system‚use default output device
|
||
const ALCchar *initStr = (const ALCchar *)"\'( (sampling-rate 44100 ))";
|
||
|
||
newDevice = alcOpenDevice(initStr);
|
||
if (newDevice != NULL)
|
||
{
|
||
// Create a new OpenAL Context
|
||
// The new context will render to the OpenAL Device just created
|
||
ALCint attr[] = { ALC_FREQUENCY, DeviceDmaSpeed(), ALC_SYNC, AL_FALSE, 0 };
|
||
|
||
newContext = alcCreateContext(newDevice, attr );
|
||
if (newContext != NULL)
|
||
{
|
||
// Make the new context the Current OpenAL Context
|
||
alcMakeContextCurrent(newContext);
|
||
|
||
// Create some OpenAL Buffer Objects
|
||
alGenBuffers( NUM_BUFFERS_SOURCES, m_Buffer);
|
||
if((error = alGetError()) != AL_NO_ERROR)
|
||
{
|
||
DevMsg("Error Generating Buffers: ");
|
||
return;
|
||
}
|
||
|
||
// Create some OpenAL Source Objects
|
||
alGenSources(1, m_Source);
|
||
if(alGetError() != AL_NO_ERROR)
|
||
{
|
||
DevMsg("Error generating sources! \n");
|
||
return;
|
||
}
|
||
|
||
alListener3f( AL_POSITION,0.0f,0.0f,0.0f);
|
||
int i;
|
||
for ( i = 0; i < 1; i++ )
|
||
{
|
||
alSource3f( m_Source[i],AL_POSITION,0.0f,0.0f,0.0f );
|
||
alSourcef( m_Source[i], AL_PITCH, 1.0f );
|
||
alSourcef( m_Source[i], AL_GAIN, 1.0f );
|
||
}
|
||
|
||
}
|
||
}
|
||
|
||
m_SndBufSize = NUM_BUFFERS_SOURCES*BUFFER_SIZE;
|
||
m_deviceSampleCount = m_SndBufSize / DeviceSampleBytes();
|
||
|
||
if ( !m_sndBuffers )
|
||
{
|
||
m_sndBuffers = malloc( m_SndBufSize );
|
||
memset( m_sndBuffers, 0x0, m_SndBufSize );
|
||
}
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Closes the windows wave out device
|
||
//-----------------------------------------------------------------------------
|
||
void CAudioDeviceOpenAL::CloseWaveOut( void )
|
||
{
|
||
if ( ValidWaveOut() )
|
||
{
|
||
ALCcontext *context = NULL;
|
||
ALCdevice *device = NULL;
|
||
|
||
m_bSoundsShutdown = true;
|
||
alSourceStop( m_Source[0] );
|
||
|
||
// Delete the Sources
|
||
alDeleteSources(1, m_Source);
|
||
// Delete the Buffers
|
||
alDeleteBuffers(NUM_BUFFERS_SOURCES, m_Buffer);
|
||
|
||
//Get active context
|
||
context = alcGetCurrentContext();
|
||
//Get device for active context
|
||
device = alcGetContextsDevice(context);
|
||
alcMakeContextCurrent( NULL );
|
||
alcSuspendContext(context);
|
||
//Release context
|
||
alcDestroyContext(context);
|
||
//Close device
|
||
alcCloseDevice(device);
|
||
}
|
||
|
||
if ( m_sndBuffers )
|
||
{
|
||
free( m_sndBuffers );
|
||
m_sndBuffers = NULL;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Mixing setup
|
||
//-----------------------------------------------------------------------------
|
||
int CAudioDeviceOpenAL::PaintBegin( float mixAheadTime, int soundtime, int paintedtime )
|
||
{
|
||
// soundtime - total samples that have been played out to hardware at dmaspeed
|
||
// paintedtime - total samples that have been mixed at speed
|
||
// endtime - target for samples in mixahead buffer at speed
|
||
|
||
unsigned int endtime = soundtime + mixAheadTime * DeviceDmaSpeed();
|
||
|
||
int samps = DeviceSampleCount() >> (DeviceChannels()-1);
|
||
|
||
if ((int)(endtime - soundtime) > samps)
|
||
endtime = soundtime + samps;
|
||
|
||
if ((endtime - paintedtime) & 0x3)
|
||
{
|
||
// The difference between endtime and painted time should align on
|
||
// boundaries of 4 samples. This is important when upsampling from 11khz -> 44khz.
|
||
endtime -= (endtime - paintedtime) & 0x3;
|
||
}
|
||
|
||
return endtime;
|
||
}
|
||
|
||
|
||
#ifdef OSX
|
||
ALvoid alBufferDataStaticProc(const ALint bid, ALenum format, ALvoid* data, ALsizei size, ALsizei freq)
|
||
{
|
||
static alBufferDataStaticProcPtr proc = NULL;
|
||
|
||
if (proc == NULL) {
|
||
proc = (alBufferDataStaticProcPtr) alGetProcAddress((const ALCchar*) "alBufferDataStatic");
|
||
}
|
||
|
||
if (proc)
|
||
proc(bid, format, data, size, freq);
|
||
|
||
}
|
||
#endif
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Actually performs the mixing
|
||
//-----------------------------------------------------------------------------
|
||
void CAudioDeviceOpenAL::PaintEnd( void )
|
||
{
|
||
if ( !m_sndBuffers /*|| m_bSoundsShutdown*/ )
|
||
return;
|
||
|
||
ALint state;
|
||
ALenum error;
|
||
int iloop;
|
||
|
||
int cblocks = 4 << 1;
|
||
ALint processed = 1;
|
||
ALuint lastUnqueuedBuffer = 0;
|
||
ALuint unqueuedBuffer = -1;
|
||
int nProcessedLoop = 200; // spin for a max of 200 times de-queing buffers, fixes a hang on exit
|
||
while ( processed > 0 && --nProcessedLoop > 0 )
|
||
{
|
||
alGetSourcei( m_Source[ 0 ], AL_BUFFERS_PROCESSED, &processed);
|
||
error = alGetError();
|
||
if (error != AL_NO_ERROR)
|
||
break;
|
||
|
||
if ( processed > 0 )
|
||
{
|
||
lastUnqueuedBuffer = unqueuedBuffer;
|
||
alSourceUnqueueBuffers( m_Source[ 0 ], 1, &unqueuedBuffer );
|
||
error = alGetError();
|
||
if ( error != AL_NO_ERROR && error != AL_INVALID_NAME )
|
||
{
|
||
DevMsg( "Error alSourceUnqueueBuffers %d\n", error );
|
||
break;
|
||
}
|
||
else
|
||
{
|
||
m_buffersCompleted++; // this buffer has been played
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// submit a few new sound blocks
|
||
//
|
||
// 44K sound support
|
||
while (((m_buffersSent - m_buffersCompleted) >> SAMPLE_16BIT_SHIFT) < cblocks)
|
||
{
|
||
int iBuf = m_buffersSent&BUFF_MASK;
|
||
#ifdef OSX
|
||
alBufferDataStaticProc( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, DeviceDmaSpeed() );
|
||
#else
|
||
alBufferData( m_Buffer[iBuf], AL_FORMAT_STEREO16, (char *)m_sndBuffers + iBuf*BUFFER_SIZE, BUFFER_SIZE, DeviceDmaSpeed() );
|
||
#endif
|
||
if ( (error = alGetError()) != AL_NO_ERROR )
|
||
{
|
||
DevMsg( "Error alBufferData %d %d\n", iBuf, error );
|
||
}
|
||
|
||
alSourceQueueBuffers( m_Source[0], 1, &m_Buffer[iBuf] );
|
||
if ( (error = alGetError() ) != AL_NO_ERROR )
|
||
{
|
||
DevMsg( "Error alSourceQueueBuffers %d %d\n", iBuf, error );
|
||
}
|
||
m_buffersSent++;
|
||
}
|
||
|
||
// make sure the stream is playing
|
||
alGetSourcei( m_Source[ 0 ], AL_SOURCE_STATE, &state);
|
||
if ( state != AL_PLAYING )
|
||
{
|
||
DevMsg( "Restarting sound playback\n" );
|
||
alSourcePlay( m_Source[0] );
|
||
if((error = alGetError()) != AL_NO_ERROR)
|
||
{
|
||
DevMsg( "Error alSourcePlay %d\n", error );
|
||
}
|
||
}
|
||
}
|
||
|
||
int CAudioDeviceOpenAL::GetOutputPosition( void )
|
||
{
|
||
int s = m_buffersSent * BUFFER_SIZE;
|
||
|
||
s >>= SAMPLE_16BIT_SHIFT;
|
||
|
||
s &= (DeviceSampleCount()-1);
|
||
|
||
return s / DeviceChannels();
|
||
}
|
||
|
||
|
||
//-----------------------------------------------------------------------------
|
||
// Pausing
|
||
//-----------------------------------------------------------------------------
|
||
void CAudioDeviceOpenAL::Pause( void )
|
||
{
|
||
m_pauseCount++;
|
||
if (m_pauseCount == 1)
|
||
{
|
||
alSourceStop( m_Source[0] );
|
||
}
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::UnPause( void )
|
||
{
|
||
if ( m_pauseCount > 0 )
|
||
{
|
||
m_pauseCount--;
|
||
}
|
||
|
||
if ( m_pauseCount == 0 )
|
||
{
|
||
alSourcePlay( m_Source[0] );
|
||
}
|
||
}
|
||
|
||
bool CAudioDeviceOpenAL::IsActive( void )
|
||
{
|
||
return ( m_pauseCount == 0 );
|
||
}
|
||
|
||
float CAudioDeviceOpenAL::MixDryVolume( void )
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
|
||
bool CAudioDeviceOpenAL::Should3DMix( void )
|
||
{
|
||
return false;
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::ClearBuffer( void )
|
||
{
|
||
if ( !m_sndBuffers )
|
||
return;
|
||
|
||
Q_memset( m_sndBuffers, 0x0, DeviceSampleCount() * DeviceSampleBytes() );
|
||
}
|
||
|
||
void CAudioDeviceOpenAL::UpdateListener( const Vector& position, const Vector& forward, const Vector& right, const Vector& up )
|
||
{
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::MixBegin( int sampleCount )
|
||
{
|
||
MIX_ClearAllPaintBuffers( sampleCount, false );
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::MixUpsample( int sampleCount, int filtertype )
|
||
{
|
||
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
|
||
int ifilter = ppaint->ifilter;
|
||
|
||
Assert (ifilter < CPAINTFILTERS);
|
||
|
||
S_MixBufferUpsample2x( sampleCount, ppaint->pbuf, &(ppaint->fltmem[ifilter][0]), CPAINTFILTERMEM, filtertype );
|
||
|
||
ppaint->ifilter++;
|
||
}
|
||
|
||
void CAudioDeviceOpenAL::Mix8Mono( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
|
||
{
|
||
int volume[CCHANVOLUMES];
|
||
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
|
||
|
||
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1))
|
||
return;
|
||
|
||
Mix8MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::Mix8Stereo( channel_t *pChannel, char *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
|
||
{
|
||
int volume[CCHANVOLUMES];
|
||
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
|
||
|
||
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
|
||
return;
|
||
|
||
Mix8StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, (byte *)pData, inputOffset, rateScaleFix, outCount );
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::Mix16Mono( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
|
||
{
|
||
int volume[CCHANVOLUMES];
|
||
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
|
||
|
||
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 1 ))
|
||
return;
|
||
|
||
Mix16MonoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::Mix16Stereo( channel_t *pChannel, short *pData, int outputOffset, int inputOffset, fixedint rateScaleFix, int outCount, int timecompress )
|
||
{
|
||
int volume[CCHANVOLUMES];
|
||
paintbuffer_t *ppaint = MIX_GetCurrentPaintbufferPtr();
|
||
|
||
if (!MIX_ScaleChannelVolume( ppaint, pChannel, volume, 2 ))
|
||
return;
|
||
|
||
Mix16StereoWavtype( pChannel, ppaint->pbuf + outputOffset, volume, pData, inputOffset, rateScaleFix, outCount );
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::ChannelReset( int entnum, int channelIndex, float distanceMod )
|
||
{
|
||
}
|
||
|
||
|
||
void CAudioDeviceOpenAL::TransferSamples( int end )
|
||
{
|
||
int lpaintedtime = g_paintedtime;
|
||
int endtime = end;
|
||
|
||
// resumes playback...
|
||
|
||
if ( m_sndBuffers )
|
||
{
|
||
S_TransferStereo16( m_sndBuffers, PAINTBUFFER, lpaintedtime, endtime );
|
||
}
|
||
}
|
||
|
||
void CAudioDeviceOpenAL::SpatializeChannel( int volume[CCHANVOLUMES/2], int master_vol, const Vector& sourceDir, float gain, float mono )
|
||
{
|
||
VPROF("CAudioDeviceOpenAL::SpatializeChannel");
|
||
S_SpatializeChannel( volume, master_vol, &sourceDir, gain, mono );
|
||
}
|
||
|
||
void CAudioDeviceOpenAL::StopAllSounds( void )
|
||
{
|
||
m_bSoundsShutdown = true;
|
||
alSourceStop( m_Source[0] );
|
||
}
|
||
|
||
|
||
|
||
void CAudioDeviceOpenAL::ApplyDSPEffects( int idsp, portable_samplepair_t *pbuffront, portable_samplepair_t *pbufrear, portable_samplepair_t *pbufcenter, int samplecount )
|
||
{
|
||
//SX_RoomFX( endtime, filter, timefx );
|
||
DSP_Process( idsp, pbuffront, pbufrear, pbufcenter, samplecount );
|
||
}
|
||
|
||
|
||
static uint32 GetOSXSpeakerConfig()
|
||
{
|
||
return 2;
|
||
}
|
||
|
||
static uint32 GetSpeakerConfigForSurroundMode( int surroundMode, const char **pConfigDesc )
|
||
{
|
||
uint32 newSpeakerConfig = 2;
|
||
*pConfigDesc = "stereo speaker";
|
||
return newSpeakerConfig;
|
||
}
|
||
|
||
|
||
|
||
void OnSndSurroundCvarChanged( IConVar *pVar, const char *pOldString, float flOldValue )
|
||
{
|
||
// if the old value is -1, we're setting this from the detect routine for the first time
|
||
// no need to reset the device
|
||
if ( flOldValue == -1 )
|
||
return;
|
||
|
||
// get the user's previous speaker config
|
||
uint32 speaker_config = GetOSXSpeakerConfig();
|
||
|
||
// get the new config
|
||
uint32 newSpeakerConfig = 0;
|
||
const char *speakerConfigDesc = "";
|
||
|
||
ConVarRef var( pVar );
|
||
newSpeakerConfig = GetSpeakerConfigForSurroundMode( var.GetInt(), &speakerConfigDesc );
|
||
// make sure the config has changed
|
||
if (newSpeakerConfig == speaker_config)
|
||
return;
|
||
|
||
// set new configuration
|
||
//SetWindowsSpeakerConfig(newSpeakerConfig);
|
||
|
||
Msg("Speaker configuration has been changed to %s.\n", speakerConfigDesc);
|
||
|
||
// restart sound system so it takes effect
|
||
//g_pSoundServices->RestartSoundSystem();
|
||
}
|
||
|
||
void OnSndSurroundLegacyChanged( IConVar *pVar, const char *pOldString, float flOldValue )
|
||
{
|
||
}
|
||
|
||
#endif // !DEDICATED
|
||
|