source-engine/soundsystem/soundsystem.cpp

280 lines
6.7 KiB
C++

//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: DLL interface for low-level sound utilities
//
//===========================================================================//
#include "soundsystem/isoundsystem.h"
#include "filesystem.h"
#include "tier1/strtools.h"
#include "tier1/convar.h"
#include "mathlib/mathlib.h"
#include "soundsystem/snd_device.h"
#include "datacache/idatacache.h"
#include "soundchars.h"
#include "tier1/utldict.h"
#include "snd_wave_source.h"
#include "snd_dev_wave.h"
#include "tier2/tier2.h"
#include <time.h>
//-----------------------------------------------------------------------------
// External interfaces
//-----------------------------------------------------------------------------
IAudioDevice *g_pAudioDevice = NULL;
ISoundSystem *g_pSoundSystem = NULL;
IDataCache *g_pDataCache = NULL;
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
int g_nSoundFrameCount = 0;
//-----------------------------------------------------------------------------
// Purpose: DLL interface for low-level sound utilities
//-----------------------------------------------------------------------------
class CSoundSystem : public CTier2AppSystem< ISoundSystem >
{
typedef CTier2AppSystem< ISoundSystem > BaseClass;
public:
// Inherited from IAppSystem
virtual bool Connect( CreateInterfaceFn factory );
virtual void Disconnect();
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init();
virtual void Shutdown();
void Update( float dt );
void Flush( void );
CAudioSource *FindOrAddSound( const char *filename );
CAudioSource *LoadSound( const char *wavfile );
void PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer );
bool IsSoundPlaying( CAudioMixer *pMixer );
CAudioMixer *FindMixer( CAudioSource *source );
void StopAll( void );
void StopSound( CAudioMixer *mixer );
private:
struct CSoundFile
{
char filename[ 512 ];
CAudioSource *source;
time_t filetime;
};
IAudioDevice *m_pAudioDevice;
float m_flElapsedTime;
CUtlVector < CSoundFile > m_ActiveSounds;
};
//-----------------------------------------------------------------------------
// Singleton interface
//-----------------------------------------------------------------------------
static CSoundSystem s_SoundSystem;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CSoundSystem, ISoundSystem, SOUNDSYSTEM_INTERFACE_VERSION, s_SoundSystem );
//-----------------------------------------------------------------------------
// Connect, disconnect
//-----------------------------------------------------------------------------
bool CSoundSystem::Connect( CreateInterfaceFn factory )
{
if ( !BaseClass::Connect( factory ) )
return false;
g_pDataCache = (IDataCache*)factory( DATACACHE_INTERFACE_VERSION, NULL );
g_pSoundSystem = this;
return (g_pFullFileSystem != NULL) && (g_pDataCache != NULL);
}
void CSoundSystem::Disconnect()
{
g_pSoundSystem = NULL;
g_pDataCache = NULL;
BaseClass::Disconnect();
}
//-----------------------------------------------------------------------------
// Query interface
//-----------------------------------------------------------------------------
void *CSoundSystem::QueryInterface( const char *pInterfaceName )
{
if (!Q_strncmp( pInterfaceName, SOUNDSYSTEM_INTERFACE_VERSION, Q_strlen(SOUNDSYSTEM_INTERFACE_VERSION) + 1))
return (ISoundSystem*)this;
return NULL;
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
InitReturnVal_t CSoundSystem::Init()
{
InitReturnVal_t nRetVal = BaseClass::Init();
if ( nRetVal != INIT_OK )
return nRetVal;
MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f );
m_flElapsedTime = 0.0f;
m_pAudioDevice = Audio_CreateWaveDevice();
if ( !m_pAudioDevice->Init() )
return INIT_FAILED;
return INIT_OK;
}
void CSoundSystem::Shutdown()
{
Msg( "Removing %i sounds\n", m_ActiveSounds.Size() );
for ( int i = 0 ; i < m_ActiveSounds.Size(); i++ )
{
CSoundFile *p = &m_ActiveSounds[ i ];
Msg( "Removing sound: %s\n", p->filename );
delete p->source;
}
m_ActiveSounds.RemoveAll();
if ( m_pAudioDevice )
{
m_pAudioDevice->Shutdown();
delete m_pAudioDevice;
}
BaseClass::Shutdown();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CAudioSource *CSoundSystem::FindOrAddSound( const char *filename )
{
CSoundFile *s;
int i;
for ( i = 0; i < m_ActiveSounds.Size(); i++ )
{
s = &m_ActiveSounds[ i ];
Assert( s );
if ( !stricmp( s->filename, filename ) )
{
time_t filetime = g_pFullFileSystem->GetFileTime( filename );
if ( filetime != s->filetime )
{
Msg( "Reloading sound %s\n", filename );
delete s->source;
s->source = LoadSound( filename );
s->filetime = filetime;
}
return s->source;
}
}
i = m_ActiveSounds.AddToTail();
s = &m_ActiveSounds[ i ];
strcpy( s->filename, filename );
s->source = LoadSound( filename );
s->filetime = g_pFullFileSystem->GetFileTime( filename );
return s->source;
}
CAudioSource *CSoundSystem::LoadSound( const char *wavfile )
{
if ( !m_pAudioDevice )
return NULL;
CAudioSource *wave = AudioSource_Create( wavfile );
return wave;
}
void CSoundSystem::PlaySound( CAudioSource *source, float volume, CAudioMixer **ppMixer )
{
if ( ppMixer )
{
*ppMixer = NULL;
}
if ( m_pAudioDevice )
{
CAudioMixer *mixer = source->CreateMixer();
if ( ppMixer )
{
*ppMixer = mixer;
}
mixer->SetVolume( volume );
m_pAudioDevice->AddSource( mixer );
}
}
void CSoundSystem::Update( float dt )
{
// closecaptionmanager->PreProcess( g_nSoundFrameCount );
if ( m_pAudioDevice )
{
m_pAudioDevice->Update( m_flElapsedTime );
}
// closecaptionmanager->PostProcess( g_nSoundFrameCount, dt );
m_flElapsedTime += dt;
g_nSoundFrameCount++;
}
void CSoundSystem::Flush( void )
{
if ( m_pAudioDevice )
{
m_pAudioDevice->Flush();
}
}
void CSoundSystem::StopAll( void )
{
if ( m_pAudioDevice )
{
m_pAudioDevice->StopSounds();
}
}
void CSoundSystem::StopSound( CAudioMixer *mixer )
{
int idx = m_pAudioDevice->FindSourceIndex( mixer );
if ( idx != -1 )
{
m_pAudioDevice->FreeChannel( idx );
}
}
bool CSoundSystem::IsSoundPlaying( CAudioMixer *pMixer )
{
if ( !m_pAudioDevice || !pMixer )
return false;
//
int index = m_pAudioDevice->FindSourceIndex( pMixer );
if ( index != -1 )
return true;
return false;
}
CAudioMixer *CSoundSystem::FindMixer( CAudioSource *source )
{
if ( !m_pAudioDevice )
return NULL;
return m_pAudioDevice->GetMixerForSource( source );
}