summaryrefslogtreecommitdiffstats
path: root/game/code/sound/soundrenderer
diff options
context:
space:
mode:
Diffstat (limited to 'game/code/sound/soundrenderer')
-rw-r--r--game/code/sound/soundrenderer/allsoundrenderer.cpp14
-rw-r--r--game/code/sound/soundrenderer/dasoundgroup.h100
-rw-r--r--game/code/sound/soundrenderer/dasoundplayer.cpp1191
-rw-r--r--game/code/sound/soundrenderer/fader.cpp483
-rw-r--r--game/code/sound/soundrenderer/fader.h146
-rw-r--r--game/code/sound/soundrenderer/idasoundresource.h172
-rw-r--r--game/code/sound/soundrenderer/idasoundtuner.h205
-rw-r--r--game/code/sound/soundrenderer/musicsoundplayer.cpp300
-rw-r--r--game/code/sound/soundrenderer/musicsoundplayer.h112
-rw-r--r--game/code/sound/soundrenderer/playermanager.cpp989
-rw-r--r--game/code/sound/soundrenderer/playermanager.h185
-rw-r--r--game/code/sound/soundrenderer/soundallocatedresource.cpp429
-rw-r--r--game/code/sound/soundrenderer/soundallocatedresource.h249
-rw-r--r--game/code/sound/soundrenderer/soundconstants.h0
-rw-r--r--game/code/sound/soundrenderer/sounddynaload.cpp954
-rw-r--r--game/code/sound/soundrenderer/sounddynaload.h199
-rw-r--r--game/code/sound/soundrenderer/soundnucleus.cpp594
-rw-r--r--game/code/sound/soundrenderer/soundnucleus.hpp70
-rw-r--r--game/code/sound/soundrenderer/soundplayer.h468
-rw-r--r--game/code/sound/soundrenderer/soundrenderingmanager.cpp1545
-rw-r--r--game/code/sound/soundrenderer/soundrenderingmanager.h187
-rw-r--r--game/code/sound/soundrenderer/soundresource.cpp555
-rw-r--r--game/code/sound/soundrenderer/soundresource.h152
-rw-r--r--game/code/sound/soundrenderer/soundresourcemanager.cpp527
-rw-r--r--game/code/sound/soundrenderer/soundresourcemanager.h164
-rw-r--r--game/code/sound/soundrenderer/soundsystem.h118
-rw-r--r--game/code/sound/soundrenderer/soundtuner.cpp1241
-rw-r--r--game/code/sound/soundrenderer/soundtuner.h253
-rw-r--r--game/code/sound/soundrenderer/tunerdebugpage.cpp231
-rw-r--r--game/code/sound/soundrenderer/tunerdebugpage.h68
-rw-r--r--game/code/sound/soundrenderer/wireplayers.cpp1
-rw-r--r--game/code/sound/soundrenderer/wiresystem.cpp104
32 files changed, 12006 insertions, 0 deletions
diff --git a/game/code/sound/soundrenderer/allsoundrenderer.cpp b/game/code/sound/soundrenderer/allsoundrenderer.cpp
new file mode 100644
index 0000000..f2315f3
--- /dev/null
+++ b/game/code/sound/soundrenderer/allsoundrenderer.cpp
@@ -0,0 +1,14 @@
+#include <sound/soundrenderer/dasoundplayer.cpp>
+#include <sound/soundrenderer/fader.cpp>
+#include <sound/soundrenderer/musicsoundplayer.cpp>
+#include <sound/soundrenderer/soundnucleus.cpp>
+#include <sound/soundrenderer/playermanager.cpp>
+#include <sound/soundrenderer/soundallocatedresource.cpp>
+#include <sound/soundrenderer/sounddynaload.cpp>
+#include <sound/soundrenderer/soundrenderingmanager.cpp>
+#include <sound/soundrenderer/soundresource.cpp>
+#include <sound/soundrenderer/soundresourcemanager.cpp>
+#include <sound/soundrenderer/soundtuner.cpp>
+#include <sound/soundrenderer/wireplayers.cpp>
+#include <sound/soundrenderer/wiresystem.cpp>
+#include <sound/soundrenderer/tunerdebugpage.cpp>
diff --git a/game/code/sound/soundrenderer/dasoundgroup.h b/game/code/sound/soundrenderer/dasoundgroup.h
new file mode 100644
index 0000000..884b049
--- /dev/null
+++ b/game/code/sound/soundrenderer/dasoundgroup.h
@@ -0,0 +1,100 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: dasoundgroup.hpp
+//
+// Subsystem: Dark Angel - Sound Grouping
+//
+// Description: Contains definitions, enumerations, and interfaces for a
+// Dark Angel sound group.
+//
+// Revisions:
+// + Created October 18, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _DASOUNDGROUP_HPP
+#define _DASOUNDGROUP_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Typedefs and Enumerations
+//=============================================================================
+
+//
+// The list of possible sound groups
+//
+
+enum daSoundGroup {
+ // BASIC WIRING GROUPS
+ CARSOUND,
+ NIS,
+
+ NUM_BASIC_SOUND_GROUPS,
+
+ // SYSTEM WIRING GROUPS
+ // Warning: Do not modify
+ DIALOGUE = NUM_BASIC_SOUND_GROUPS,
+ DIALOGUE_TUNE,
+ DUCKABLE,
+ MASTER,
+ MASTER_TUNE,
+ MUSIC,
+ MUSIC_TUNE,
+ AMBIENCE,
+ AMBIENCE_TUNE,
+ SOUND_EFFECTS,
+ SOUND_EFFECTS_TUNE,
+ OPTIONS_MENU_STINGERS,
+
+ NUM_SOUND_GROUPS
+};
+
+enum DuckSituations
+{
+ DUCK_FULL_FADE,
+
+ DUCK_SIT_PAUSE,
+ DUCK_SIT_MISSION,
+ DUCK_SIT_LETTERBOX,
+ DUCK_SIT_DIALOG,
+ DUCK_SIT_STORE,
+ DUCK_SIT_ONFOOT,
+ DUCK_SIT_MINIGAME,
+ DUCK_SIT_JUST_MUSIC,
+ DUCK_SIT_CREDITS,
+
+ NUM_DUCK_SITUATIONS
+};
+
+enum DuckVolumes
+{
+ DUCK_SFX,
+ DUCK_CAR,
+ DUCK_MUSIC,
+ DUCK_DIALOG,
+ DUCK_AMBIENCE,
+
+ NUM_DUCK_VOLUMES
+};
+
+//
+// A structure for holding a collection of volumes
+//
+struct DuckVolumeSet
+{
+ float duckVolume[NUM_DUCK_VOLUMES];
+};
+
+} // Namespace
+#endif //_DASOUNDGROUP_HPP
+
diff --git a/game/code/sound/soundrenderer/dasoundplayer.cpp b/game/code/sound/soundrenderer/dasoundplayer.cpp
new file mode 100644
index 0000000..0220f47
--- /dev/null
+++ b/game/code/sound/soundrenderer/dasoundplayer.cpp
@@ -0,0 +1,1191 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: dasoundplayer.cpp
+//
+// Subsystem: Dark Angel - Sound players
+//
+// Description: Implements the a Dark Angel sound player
+//
+// Revisions:
+// + Created October 16, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radlinkedclass.hpp>
+
+#include <radsound.hpp>
+#include <radsoundmath.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/soundplayer.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/soundnucleus.hpp>
+
+#include <main/commandlineoptions.h>
+
+//=============================================================================
+// Static Variables (outside namespace)
+//=============================================================================
+
+
+//
+// Initialially the player list is empty
+//
+Sound::daSoundPlayerBase* radLinkedClass< Sound::daSoundPlayerBase >::s_pLinkedClassHead = NULL;
+Sound::daSoundPlayerBase* radLinkedClass< Sound::daSoundPlayerBase >::s_pLinkedClassTail = NULL;
+Sound::daSoundClipStreamPlayer* radLinkedClass< Sound::daSoundClipStreamPlayer >::s_pLinkedClassHead = NULL;
+Sound::daSoundClipStreamPlayer* radLinkedClass< Sound::daSoundClipStreamPlayer >::s_pLinkedClassTail = NULL;
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Debug Information
+//=============================================================================
+
+//
+// Use this if you want to debug the sound player
+//
+#ifndef FINAL
+#ifndef NDEBUG
+#define DASOUNDPLAYER_DEBUG
+#ifdef DASOUNDPLAYER_DEBUG
+
+// Show sound state changes
+static bool sg_ShowSoundStates = false;
+
+#endif //DASOUNDPLAYER_DEBUG
+#endif //NDEBUG
+#endif //FINAL
+
+//=============================================================================
+// Definitions Macros and Constants
+//=============================================================================
+
+//
+// These are the minimum ranges that the given variables must range
+// over to warrant a randomization calculation
+//
+const float DASOUND_MINFLOATVARYINGRANGE = 0.0001f;
+
+//=============================================================================
+// Local functions
+//=============================================================================
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundClipStreamPlayer Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::daSoundClipStreamPlayer
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundClipStreamPlayer::daSoundClipStreamPlayer( )
+ :
+ m_Trim( 1.0f ),
+ m_GroupTrim( 1.0f ),
+ m_FaderGroupTrim( 1.0f ),
+ m_MasterTrim( 1.0f ),
+ m_State( State_DeCued ),
+ m_CueingState( CueingState_Null ),
+ m_CaptureCount( 0 ),
+ m_PauseCount( 0 ),
+ m_pAllocatedResource( NULL ),
+ m_AllocResInstanceID( 0 ),
+ m_pResource( NULL ),
+ m_pStateChangeCallback( NULL ),
+ m_pStateChangeCallbackUserData( NULL ),
+ m_Type( IDaSoundResource::UNKNOWN )
+{
+ m_IsPositional = false;
+ m_pPositionalGroup = radSoundHalPositionalGroupCreate( GetThisAllocator( ) );
+ m_pPositionalGroup->AddRef( );
+
+ m_CurrentTrim = 0.0f;
+ m_StoppingTrim = 1.0f;
+ m_VaryingTrim = 1.0f;
+
+ m_Pitch = 1.0f;
+ m_VaryingPitch = 1.0f;
+ m_CurrentPitch = 1.0f;
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::~daSoundClipStreamPlayer
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundClipStreamPlayer::~daSoundClipStreamPlayer( )
+{
+ if ( IDaSoundResource::CLIP == m_Type )
+ {
+ m_ClipInfo.m_pClipPlayer->Stop( );
+ m_ClipInfo.m_pClipPlayer->SetClip( NULL );
+ m_ClipInfo.m_pClipPlayer->Release( );
+ }
+ else
+ {
+ if ( m_StreamInfo.m_pResources != NULL )
+ {
+ Sound::SoundNucleusUnCaptureStreamerResources( m_StreamInfo.m_pResources );
+ m_StreamInfo.m_pResources->m_pStitchedDataSource->SetStitchCallback( NULL, NULL );
+ }
+
+ if ( m_StreamInfo.m_pRsdFileDataSource != NULL )
+ {
+ m_StreamInfo.m_pRsdFileDataSource->Release( );
+ }
+ }
+
+ if ( m_pResource != NULL )
+ {
+ m_pResource->Release( );
+ }
+
+ if ( m_pPositionalGroup )
+ {
+ m_pPositionalGroup->Release( );
+ }
+
+ if ( m_pAllocatedResource )
+ {
+ m_pAllocatedResource->Release( );
+ }
+
+ if ( m_pResource != NULL )
+ {
+ m_pResource->Release( );
+ }
+}
+
+void daSoundClipStreamPlayer::UpdateClip( void )
+{
+ m_ClipInfo.m_pClipPlayer->SetTrim( m_CurrentTrim );
+ m_ClipInfo.m_pClipPlayer->SetPitch( m_CurrentPitch );
+
+ IRadSoundClipPlayer * pCp = m_ClipInfo.m_pClipPlayer;
+ IRadSoundClipPlayer::State state = pCp->GetState( );
+
+ switch( m_State )
+ {
+ case State_DeCued:
+ {
+ rAssert( IRadSoundClipPlayer::NoClip == state );
+ break;
+ }
+ case State_CuedPlay:
+ case State_Cueing:
+ {
+ switch( m_CueingState )
+ {
+ case CueingState_Null:
+ {
+ rAssert( false );
+ break;
+ }
+ case CueingState_Resource:
+ {
+ rAssert( IRadSoundClipPlayer::NoClip == state );
+
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+ if ( pFileInstance->GetState( ) == daSoundFileInstance::Loaded )
+ {
+ HookUpAndCuePlayer( );
+ }
+
+ break;
+ }
+ case CueingState_Player:
+ {
+ m_CueingState = CueingState_Cued;
+ break;
+ }
+ case CueingState_Cued:
+ {
+ rAssert( IRadSoundClipPlayer::Stopped == state );
+
+ if ( State_CuedPlay == m_State )
+ {
+ if( 0 == m_PauseCount )
+ {
+ pCp->Play( );
+ }
+
+ m_CaptureCount++;
+ m_State = State_Playing;
+ }
+ else
+ {
+ m_State = State_Cued;
+ }
+
+ if ( m_pStateChangeCallback )
+ {
+ m_pStateChangeCallback->OnSoundReady( m_pStateChangeCallbackUserData );
+ }
+
+ m_CueingState = CueingState_Null;
+
+ break;
+ }
+ }
+ break;
+ }
+ case State_Cued:
+ {
+ switch( state )
+ {
+ case IRadSoundClipPlayer::Stopped:
+ break;
+ case IRadSoundClipPlayer::NoClip:
+ case IRadSoundClipPlayer::Queueing:
+ case IRadSoundClipPlayer::QueuedPlay:
+ case IRadSoundClipPlayer::Playing:
+ default:
+ rAssert( false );
+ }
+ break;
+ }
+ case State_Playing:
+ {
+ if ( m_StoppingTrim <= 1.0f )
+ {
+ m_StoppingTrim += radSoundVolumeChangeThreshold;
+
+ if ( m_StoppingTrim >= 1.0f )
+ {
+ m_StoppingTrim = 1.0f;
+ }
+ }
+ switch( state )
+ {
+ case IRadSoundClipPlayer::NoClip:
+ case IRadSoundClipPlayer::Queueing:
+ case IRadSoundClipPlayer::QueuedPlay:
+ rAssert( false );
+ break;
+ case IRadSoundClipPlayer::Playing:
+ rAssert( 0 == m_PauseCount );
+ break;
+ case IRadSoundClipPlayer::Stopped:
+ if( m_PauseCount == 0 )
+ {
+ m_State = State_Done;
+ UnCapture( );
+
+ if ( m_pStateChangeCallback )
+ {
+ m_pStateChangeCallback->OnSoundDone( m_pStateChangeCallbackUserData );
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case State_Stopping:
+ {
+ if ( m_CurrentTrim <= 0.0f )
+ {
+ m_ClipInfo.m_pClipPlayer->Stop( );
+ m_State = State_Cued;
+ m_StoppingTrim = 1.0f;
+ UnCapture( );
+ }
+ else
+ {
+ m_StoppingTrim -= radSoundVolumeChangeThreshold;
+
+ if ( m_StoppingTrim <= 0.0f )
+ {
+ m_StoppingTrim = 0.0f;
+ }
+ }
+
+ break;
+ }
+
+ case State_Done:
+ {
+ rAssert( IRadSoundClipPlayer::NoClip == state );
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ }
+ }
+}
+
+void daSoundClipStreamPlayer::UpdateStream( void )
+{
+ IRadSoundStreamPlayer::State state;
+
+ if ( NULL != m_StreamInfo.m_pResources )
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetTrim( m_CurrentTrim );
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetPitch( m_CurrentPitch );
+ state = m_StreamInfo.m_pResources->m_pStreamPlayer->GetState( );
+ }
+ else
+ {
+ state = IRadSoundStreamPlayer::NoSource;
+ }
+
+ switch( m_State )
+ {
+ case State_DeCued:
+ {
+ rAssert( IRadSoundStreamPlayer::NoSource == state );
+ break;
+ }
+ case State_CuedPlay:
+ case State_Cueing:
+ {
+ switch( m_CueingState )
+ {
+ case CueingState_Resource:
+ {
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+
+ if ( pFileInstance->GetState( ) == daSoundFileInstance::Loaded )
+ {
+ if ( NULL == m_StreamInfo.m_pRsdFileDataSource )
+ {
+ m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID )->CreateFileDataSource( & m_StreamInfo.m_pRsdFileDataSource );
+ }
+ else if ( IRadSoundRsdFileDataSource::Initialized == m_StreamInfo.m_pRsdFileDataSource->GetState( ) )
+ {
+ /* rDebugPrintf( "DASOUND: Playing Streamed File: [%s], format: [%d], channels: [%d]\n",
+ pFileInstance->GetFileName( ),
+ m_StreamInfo.m_pRsdFileDataSource->GetFormat( )->GetEncoding( ),
+ m_StreamInfo.m_pRsdFileDataSource->GetFormat( )->GetNumberOfChannels( ) ); */
+
+ HookUpAndCuePlayer( );
+ }
+ }
+
+ break;
+ }
+ case CueingState_Player:
+ {
+ switch( state )
+ {
+ case IRadSoundStreamPlayer::Queueing:
+ {
+ break;
+ }
+ case IRadSoundStreamPlayer::Paused:
+ {
+
+ if ( m_pStateChangeCallback )
+ {
+ m_pStateChangeCallback->OnSoundReady( m_pStateChangeCallbackUserData );
+ }
+
+ m_CueingState = CueingState_Cued;
+ break;
+ }
+ case IRadSoundStreamPlayer::NoSource:
+ case IRadSoundStreamPlayer::Playing:
+ case IRadSoundStreamPlayer::QueuedPlay:
+ default:
+ rAssert( false );
+ }
+
+ break;
+ }
+ case CueingState_Cued:
+ {
+ if ( State_Cueing == m_State )
+ {
+ m_State = State_Cued;
+ }
+ else
+ {
+ if ( 0 == m_PauseCount )
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->Play( );
+ }
+ m_CaptureCount++;
+ m_State = State_Playing;
+ }
+
+ m_CueingState = CueingState_Null;
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ }
+ }
+ break;
+ }
+ case State_Cued:
+ {
+ rAssert( IRadSoundStreamPlayer::Paused == state );
+ break;
+ }
+ case State_Playing:
+ {
+ m_StoppingTrim += radSoundVolumeChangeThreshold;
+
+ if ( m_StoppingTrim >= 1.0f )
+ {
+ m_StoppingTrim = 1.0f;
+ }
+
+ switch( state )
+ {
+ case IRadSoundStreamPlayer::Queueing:
+ rAssert(false);
+ break;
+ case IRadSoundStreamPlayer::Paused:
+ rAssert( 0 < m_PauseCount );
+ break;
+ case IRadSoundStreamPlayer::NoSource:
+ m_State = State_Done;
+ UnCapture( ); // Internal
+ if ( m_pStateChangeCallback )
+ {
+ m_pStateChangeCallback->OnSoundDone( m_pStateChangeCallbackUserData );
+ }
+ break;
+ case IRadSoundStreamPlayer::Playing:
+ rAssert( 0 == m_PauseCount );
+ break;
+ case IRadSoundStreamPlayer::QueuedPlay:
+ default:
+ rAssert( false );
+ }
+
+ break;
+
+ }
+ case State_Stopping:
+ {
+ if ( m_CurrentTrim <= 0.0f )
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->Stop( );
+ m_State = State_Cued;
+ m_StoppingTrim = 1.0f;
+ UnCapture( );
+ }
+ else
+ {
+ m_StoppingTrim -= radSoundVolumeChangeThreshold;
+
+ if ( m_StoppingTrim <= 0.0f )
+ {
+ m_StoppingTrim = 0.0f;
+ }
+ }
+
+ break;
+ }
+ case State_Done:
+ {
+ rAssert( IRadSoundStreamPlayer::NoSource == state );
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ }
+ }
+
+}
+
+void daSoundClipStreamPlayer::ServiceOncePerFrame( void )
+{
+ //
+ // Update the state information. This now requires polling the player.
+ //
+
+ State prevState;
+ CueingState prevCueingState;
+
+ do
+ {
+
+ CalculateCurrentTrim( );
+ CalculateCurrentPitch( );
+
+ prevState = m_State;
+ prevCueingState = m_CueingState;
+
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ UpdateClip( );
+ break;
+ case IDaSoundResource::STREAM:
+ UpdateStream( );
+ break;
+ default:
+ rAssert( 0 );
+ break;
+ }
+ }
+ while( prevState != m_State || prevCueingState != m_CueingState );
+}
+
+void daSoundClipStreamPlayer::InitializeAsClipPlayer( void )
+{
+ m_Type = IDaSoundResource::CLIP;
+
+ m_ClipInfo.m_pClipPlayer = radSoundClipPlayerCreate( GetThisAllocator( ) );
+ m_ClipInfo.m_pClipPlayer->AddRef( );
+
+#ifndef RAD_WIN32
+ // Prepare the player to listen for spacial effects
+ for( unsigned int i = 0; i < ::radSoundHalSystemGet( )->GetNumAuxSends( ); i++ )
+ {
+ m_ClipInfo.m_pClipPlayer->SetAuxMode( i, radSoundAuxMode_PostFader );
+ m_ClipInfo.m_pClipPlayer->SetAuxGain( i, 1.0f );
+ }
+#endif
+}
+
+void daSoundClipStreamPlayer::InitializeAsStreamPlayer( void )
+{
+ m_Type = IDaSoundResource::STREAM;
+
+ m_StreamInfo.m_pResources = NULL;
+ m_StreamInfo.m_pRsdFileDataSource = NULL;
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::CapturePlayer
+//=============================================================================
+// Description: Capture the sound player
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::Capture(
+ IDaSoundResource* pResource,
+ bool isPositional )
+{
+ rAssert( pResource != NULL );
+ rAssert( State_DeCued == m_State );
+
+ m_IsPositional = isPositional;
+
+ ++m_CaptureCount;
+
+ // A bit of a hack, but the resource should be connected only at this time
+ rAssert( m_CaptureCount == 1 );
+
+ rAssert( m_pAllocatedResource == NULL );
+ rAssert( m_pResource == NULL );
+
+ m_pResource = pResource;
+ m_pResource->CaptureResource( );
+
+ //
+ // Get an allocated resource
+ //
+ m_pAllocatedResource = daSoundResourceManager::GetInstance( )->FindAllocatedResource( m_pResource );
+
+ rAssertMsg( m_pAllocatedResource != NULL, "Resource not properly allocated" );
+
+ m_pAllocatedResource->AddRef( );
+
+ // Choose an instance to play...
+ m_AllocResInstanceID = m_pAllocatedResource->ChooseNextInstance( );
+
+ //
+ // Check the type of resource
+ //
+
+ rAssert( m_Type == m_pResource->GetType( ) );
+
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+ rAssert( pFileInstance != NULL );
+
+ if( pFileInstance->GetType( ) == IDaSoundResource::UNKNOWN )
+ {
+ rAssert( false); // when does this happen ? -Th
+ m_State = State_DeCued;
+ }
+ else
+ {
+ //
+ // Start initializing
+ //
+ m_State = State_Cueing;
+ m_CueingState = CueingState_Resource;
+ }
+
+ // Reset state.
+
+ m_Pitch = 1.0f;
+ m_Trim = 1.0f;
+
+ CalculateNewVaryingPitch( );
+ CalculateNewVaryingTrim( );
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::IsCaptured
+//=============================================================================
+// Description: Returns true if the player is already captured
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundClipStreamPlayer::IsCaptured( void )
+{
+ return( m_CaptureCount > 0 );
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::ReleasePlayer
+//=============================================================================
+// Description: Releases a player. Automattically detatches any
+// resources when it is no longer captured.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::UnCapture( void )
+{
+ unsigned int i = 0;
+
+ //
+ // I don't think this assertion is valid anymore. If a player is cued but not
+ // playing, then Stop() will release the resource, but the player isn't
+ // captured yet and this call shouldn't do anything -- DE
+ //
+ //rAssert( IsCaptured( ) );
+ if( m_CaptureCount > 0 )
+ {
+ --m_CaptureCount;
+
+ if( 0 == m_CaptureCount )
+ {
+ rAssert( NULL == m_pStateChangeCallback );
+ rAssert( m_pResource != NULL );
+ rAssert( m_pAllocatedResource->GetResource( ) == m_pResource );
+ rAssert( m_Type == m_pResource->GetType( ) );
+
+ // Detatch the real player
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ rAssert( m_ClipInfo.m_pClipPlayer != NULL );
+
+ // Detach the clip
+ m_ClipInfo.m_pClipPlayer->Stop( );
+ m_ClipInfo.m_pClipPlayer->SetClip( NULL );
+
+ break;
+ }
+ case IDaSoundResource::STREAM:
+ {
+ if ( m_StreamInfo.m_pResources != NULL )
+ {
+ m_StreamInfo.m_pResources->m_pStitchedDataSource->SetStitchCallback( NULL, NULL );
+
+ // Detach the stream
+ m_StreamInfo.m_pResources->m_pStreamPlayer->Stop( );
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetDataSource( NULL );
+
+ if ( m_StreamInfo.m_pResources->m_pBufferedDataSource != NULL )
+ {
+ m_StreamInfo.m_pResources->m_pBufferedDataSource->SetInputDataSource( NULL );
+ }
+
+ SoundNucleusUnCaptureStreamerResources( m_StreamInfo.m_pResources );
+ m_StreamInfo.m_pResources = NULL;
+ }
+
+ if ( m_StreamInfo.m_pRsdFileDataSource != NULL )
+ {
+ m_StreamInfo.m_pRsdFileDataSource->Release( );
+ m_StreamInfo.m_pRsdFileDataSource = NULL;
+ }
+
+ break;
+ }
+ default:
+ rAssert( 0 );
+ break;
+ }
+
+ // Release the allocated resource
+ m_pAllocatedResource->Release( );
+ m_pAllocatedResource = NULL;
+ m_pResource->ReleaseResource( );
+ m_pResource = NULL;
+
+ m_State = State_DeCued;
+ m_CueingState = CueingState_Null;
+ }
+ }
+}
+
+//=============================================================================
+// daSoundClipStreamPlayer::ChangeTrim
+//=============================================================================
+// Description: Change the trim setting for a sound group, or for the master
+// volume
+//
+// Parameters: groupName - name of group to change
+// newTrim - trim value
+//
+// Return: void
+//
+//=============================================================================
+void daSoundClipStreamPlayer::ChangeTrim( daSoundGroup groupName, float newTrim )
+{
+ daSoundGroup myGroup = GetSoundGroup();
+
+ if ( myGroup == groupName )
+ {
+ SetGroupTrim(newTrim);
+ }
+ else if ( groupName == MASTER )
+ {
+ SetMasterTrim(newTrim);
+ }
+ else if ( daSoundRenderingManagerGet()->GetTuner()->IsSlaveGroup( myGroup, groupName ) )
+ {
+ SetGroupTrim(newTrim);
+ }
+}
+
+//=============================================================================
+// daSoundClipStreamPlayer::ChangeFaderTrim
+//=============================================================================
+// Description: Change the trim setting for a sound group, or for the master
+// volume
+//
+// Parameters: groupName - name of group to change
+// newTrim - trim value
+//
+// Return: void
+//
+//=============================================================================
+void daSoundClipStreamPlayer::ChangeFaderTrim( daSoundGroup groupName, float newTrim )
+{
+ daSoundGroup myGroup = GetSoundGroup();
+
+ //
+ // ChangeTrim should be used for master volume settings
+ //
+ rAssert( groupName != MASTER );
+
+ if ( myGroup == groupName )
+ {
+ SetFaderGroupTrim(newTrim);
+ }
+ else if ( daSoundRenderingManagerGet()->GetTuner()->IsSlaveGroup( myGroup, groupName ) )
+ {
+ SetFaderGroupTrim(newTrim);
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::GetSoundGroup
+//=============================================================================
+// Description: Get the sound group that this player belongs to. This is
+// the sound group that its currently active sound is a part of.
+//
+// Returns: Returns the appropriate sound group.
+//
+//-----------------------------------------------------------------------------
+
+daSoundGroup daSoundClipStreamPlayer::GetSoundGroup( void )
+{
+ daSoundGroup soundGroup = Sound::MASTER;
+ if( m_pAllocatedResource != NULL )
+ {
+ rAssert( m_pAllocatedResource->GetResource( ) != NULL );
+ soundGroup = m_pAllocatedResource->GetResource( )->GetSoundGroup( );
+ }
+ return soundGroup;
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::RegisterSoundPlayerStateCallback
+//=============================================================================
+// Description: Register a sound player state callback
+//
+// Notes: Currently, only one callback is supported.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::RegisterSoundPlayerStateCallback
+(
+ IDaSoundPlayerState* pCallback,
+ void* pUserData
+)
+{
+ rAssertMsg( m_pStateChangeCallback == NULL, "Currently, only one callback is allowed" );
+ m_pStateChangeCallback = pCallback;
+ m_pStateChangeCallbackUserData = pUserData;
+ if( m_pStateChangeCallback != NULL )
+ {
+ m_pStateChangeCallback->AddRef( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::UnregisterSoundPlayerStateCallback
+//=============================================================================
+// Description: Unregister a sound player state callback
+//
+// Notes: Currently, only one callback is supported.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::UnregisterSoundPlayerStateCallback
+(
+ IDaSoundPlayerState* pCallback,
+ void* pUserData
+)
+{
+ rAssert( pCallback == m_pStateChangeCallback );
+ if( m_pStateChangeCallback != NULL )
+ {
+ m_pStateChangeCallback->Release( );
+ m_pStateChangeCallback = NULL;
+ m_pStateChangeCallbackUserData = NULL;
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::GetPlaybackTimeInSamples
+//=============================================================================
+// Description: Get the samples that have elapsed since playback started.
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundClipStreamPlayer::GetPlaybackTimeInSamples( void )
+{
+ // Is this synchronized with play / pause?
+ unsigned int elapsedtime = 0;
+ if( IsCaptured( ) )
+ {
+ // Update the positional information
+ IRadSoundPlayer* pPlayer = NULL;
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ pPlayer = static_cast< IRadSoundPlayer* >
+ (
+ m_ClipInfo.m_pClipPlayer
+ );
+ break;
+ }
+ case IDaSoundResource::STREAM:
+ {
+ pPlayer = static_cast< IRadSoundPlayer* >
+ (
+ m_StreamInfo.m_pResources->m_pStreamPlayer
+ );
+ break;
+ }
+ default:
+ rAssert( 0 );
+ break;
+ }
+ if( pPlayer != NULL )
+ {
+ elapsedtime = pPlayer->GetPlaybackTimeInSamples( );
+ //elapsedtime = ::radSoundHalSystemGet( )->GetReferenceClock( );
+ }
+ }
+
+ // Return the time
+ return( elapsedtime );
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::Play
+//=============================================================================
+// Description: Play the active sound resource.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::Play( void )
+{
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+ rAssert( pFileInstance != NULL );
+
+ #ifndef RAD_RELEASE
+ if ( daSoundFileInstance::Loaded != pFileInstance->GetState( ) )
+ {
+ char fileName[ 256 ];
+ pFileInstance->GetFileName( fileName, 256 );
+
+ rTunePrintf(
+ "\nAUDIO: Controlling code is not paying attention to latency: [%s]\n\n", fileName );
+ }
+ #endif
+
+ switch ( m_State )
+ {
+ case State_Cueing:
+ {
+ m_State = State_CuedPlay;
+ break;
+ }
+ case State_Cued:
+ {
+ m_StoppingTrim = 1.0f;
+
+ // fall through
+ }
+ case State_Stopping:
+ {
+ m_State = State_CuedPlay;
+ m_CueingState = CueingState_Cued;
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ break;
+ }
+ }
+}
+
+
+void daSoundClipStreamPlayer::OnStitch( IRadSoundHalDataSource ** ppHds , unsigned int frameCount, void * pUserData )
+{
+ bool loop = m_pAllocatedResource->GetResource( )->GetLooping( );
+
+ if ( loop || NULL != m_StreamInfo.m_pRsdFileDataSource )
+ {
+ if ( NULL != m_StreamInfo.m_pRsdFileDataSource )
+ {
+ // pass on ref count
+
+ *ppHds = m_StreamInfo.m_pRsdFileDataSource;
+ m_StreamInfo.m_pRsdFileDataSource = NULL;
+ }
+ else
+ {
+ ref< IRadSoundRsdFileDataSource > refFds;
+ m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID )->CreateFileDataSource( & refFds );
+
+ *ppHds = refFds;
+ (*ppHds)->AddRef( );
+ }
+ //rDebugPrintf( "DASOUND: Player: [0x%x] Stitching: [%s]\n", this, refFds->GetName( ) );
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::Pause
+//=============================================================================
+// Description: Pause the active sound resource.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::Pause( void )
+{
+ m_PauseCount++;
+
+ if ( State_Playing == m_State )
+ {
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ m_ClipInfo.m_pClipPlayer->Stop( );
+ break;
+ }
+ case IDaSoundResource::STREAM:
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->Stop( );
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ }
+ }
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::Continue
+//=============================================================================
+// Description: Continue the active sound resource.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::Continue( void )
+{
+ rAssert( m_PauseCount > 0 );
+
+ m_PauseCount--;
+
+ if ( 0 == m_PauseCount )
+ {
+ if ( State_Playing == m_State )
+ {
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ m_ClipInfo.m_pClipPlayer->Play( );
+ break;
+ }
+ case IDaSoundResource::STREAM:
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->Play( );
+ break;
+ }
+ default:
+ {
+ rAssert( false );
+ }
+ }
+ }
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::UberContinue
+//=============================================================================
+// Description: Continue the active sound resource, no matter how many times
+// it was previously paused
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::UberContinue( void )
+{
+ if( IsPaused() )
+ {
+ if( m_PauseCount > 1 )
+ {
+ m_PauseCount = 1;
+ }
+ Continue();
+ }
+}
+
+//=============================================================================
+// Function: daSoundClipStreamPlayer::Stop
+//=============================================================================
+// Description: Stop the active sound resource.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundClipStreamPlayer::Stop( void )
+{
+ if ( State_CuedPlay == m_State )
+ {
+ m_State = State_Cueing;
+ }
+ else if ( State_Playing == m_State )
+ {
+ m_State = State_Stopping;
+ }
+}
+
+void daSoundClipStreamPlayer::HookUpAndCuePlayer( void )
+{
+ rAssert( State_Cueing == m_State || State_CuedPlay == m_State );
+ rAssert( CueingState_Resource == m_CueingState );
+
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+ rAssert( pFileInstance != NULL );
+
+ //
+ // Initialize the group trims
+ //
+ daSoundGroup myGroup = m_pResource->GetSoundGroup();
+ SetMasterTrim( daSoundRenderingManagerGet()->GetTuner()->GetMasterVolume() );
+ SetGroupTrim( daSoundRenderingManagerGet()->GetTuner()->GetGroupTrim( myGroup ) );
+ SetFaderGroupTrim( daSoundRenderingManagerGet()->GetTuner()->GetFaderGroupTrim( myGroup ) );
+
+ switch( m_Type )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ IRadSoundClip * pClip = pFileInstance->GetSoundClip( );
+ rAssert( NULL != pClip );
+
+ // Attach the clip to the player
+ m_ClipInfo.m_pClipPlayer->SetClip( pClip );
+ m_ClipInfo.m_pClipPlayer->SetPositionalGroup( m_IsPositional ? m_pPositionalGroup : NULL );
+
+ break;
+ }
+
+ case IDaSoundResource::STREAM:
+ {
+ m_StreamInfo.m_pResources = SoundNucleusCaptureStreamerResources(
+ m_StreamInfo.m_pRsdFileDataSource->GetFormat( ) );
+
+ rAssert( m_StreamInfo.m_pResources != NULL );
+
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetPositionalGroup( m_IsPositional ? m_pPositionalGroup : NULL );
+
+ m_StreamInfo.m_pResources->m_pStitchedDataSource->SetStitchCallback( this, NULL );
+ m_StreamInfo.m_pResources->m_pStitchedDataSource->ResetAudioFormat( m_StreamInfo.m_pRsdFileDataSource->GetFormat( ) ); // GCN ADPCM HACK
+ m_StreamInfo.m_pResources->m_pStitchedDataSource->Reset( );
+
+ if ( NULL != m_StreamInfo.m_pResources->m_pBufferedDataSource )
+ {
+ m_StreamInfo.m_pResources->m_pBufferedDataSource->SetInputDataSource( m_StreamInfo.m_pResources->m_pStitchedDataSource );
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetDataSource( m_StreamInfo.m_pResources->m_pBufferedDataSource );
+ }
+ else
+ {
+ m_StreamInfo.m_pResources->m_pStreamPlayer->SetDataSource(
+ m_StreamInfo.m_pResources->m_pStitchedDataSource );
+ }
+
+
+ break;
+ }
+ default:
+ rAssert( 0 );
+ break;
+ }
+
+ m_CueingState = CueingState_Player;
+}
+
+const void daSoundClipStreamPlayer::GetFileName( char * pBuf, unsigned int max )
+{
+ rAssert( m_pAllocatedResource );
+
+ daSoundFileInstance* pFileInstance = m_pAllocatedResource->GetFileInstance( m_AllocResInstanceID );
+
+ return pFileInstance->GetFileName( pBuf, max );
+
+}
+
+} // Sound Namespace
+ \ No newline at end of file
diff --git a/game/code/sound/soundrenderer/fader.cpp b/game/code/sound/soundrenderer/fader.cpp
new file mode 100644
index 0000000..125fc9e
--- /dev/null
+++ b/game/code/sound/soundrenderer/fader.cpp
@@ -0,0 +1,483 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: fader.cpp
+//
+// Description: Implementation for Fader class which brings down volume on
+// associated multi-input knob. Replaces IRadSoundFade
+// objects from radsound/util.
+//
+// History: 13/08/2002 + Created -- Darren
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+#include <float.h>
+#include <radmath/radmath.hpp>
+
+//========================================
+// Project Includes
+//========================================
+#include <sound/soundrenderer/fader.h>
+
+#include <sound/soundrenderer/playermanager.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+
+using namespace Sound;
+
+//******************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//******************************************************************************
+
+Fader* Fader::s_faderUpdateList = NULL;
+
+//******************************************************************************
+//
+// Public Member Functions
+//
+//******************************************************************************
+
+//==============================================================================
+// Fader::Fader
+//==============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+Fader::Fader( globalSettings* duckSettings,
+ DuckSituations situation,
+ daSoundPlayerManager& playerMgr,
+ IDaSoundTuner& tuner ) :
+ m_duckSituation( situation ),
+ m_playerManager( playerMgr ),
+ m_tuner( tuner )
+{
+ m_Time = 750;
+ m_In = true;
+ m_State = FadedIn;
+ m_callback = NULL;
+ m_nextUpdatableFader = NULL;
+
+ ReinitializeFader( duckSettings );
+}
+
+//==============================================================================
+// Fader::~Fader
+//==============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//==============================================================================
+Fader::~Fader()
+{
+ if( s_faderUpdateList != NULL )
+ {
+ removeFromUpdateList();
+ }
+}
+
+//========================================================================
+// Fader::SetTime
+//========================================================================
+
+void Fader::SetTime( unsigned int milliseconds )
+{
+ m_Time = milliseconds;
+}
+
+//========================================================================
+// Fader::GetTime
+//========================================================================
+
+unsigned int Fader::GetTime( void )
+{
+ return m_Time;
+}
+
+//========================================================================
+// Fader::BroadCast
+//========================================================================
+
+void Fader::BroadCast( void )
+{
+ m_playerManager.PlayerFaderVolumeChange( SOUND_EFFECTS, m_currentVolumes.duckVolume[DUCK_SFX] );
+ m_playerManager.PlayerFaderVolumeChange( CARSOUND, m_currentVolumes.duckVolume[DUCK_CAR] );
+ m_playerManager.PlayerFaderVolumeChange( DIALOGUE, m_currentVolumes.duckVolume[DUCK_DIALOG] );
+ m_playerManager.PlayerFaderVolumeChange( MUSIC, m_currentVolumes.duckVolume[DUCK_MUSIC] );
+ m_playerManager.PlayerFaderVolumeChange( AMBIENCE, m_currentVolumes.duckVolume[DUCK_AMBIENCE] );
+
+ m_tuner.SetFaderGroupTrim( DUCK_SFX, m_currentVolumes.duckVolume[DUCK_SFX] );
+ m_tuner.SetFaderGroupTrim( DUCK_CAR, m_currentVolumes.duckVolume[DUCK_CAR] );
+ m_tuner.SetFaderGroupTrim( DUCK_DIALOG, m_currentVolumes.duckVolume[DUCK_DIALOG] );
+ m_tuner.SetFaderGroupTrim( DUCK_MUSIC, m_currentVolumes.duckVolume[DUCK_MUSIC] );
+ m_tuner.SetFaderGroupTrim( DUCK_AMBIENCE, m_currentVolumes.duckVolume[DUCK_AMBIENCE] );
+}
+
+//========================================================================
+// Fader::Fade
+//========================================================================
+
+void Fader::Fade( bool in, DuckVolumeSet* initialVolumes, DuckVolumeSet* targetVolumes )
+{
+ unsigned int i;
+
+ m_In = in;
+
+ //
+ // Set current values to whatever we're fading from and target values
+ // to whatever we're fading to
+ //
+ if( initialVolumes != NULL )
+ {
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ m_currentVolumes.duckVolume[i] = initialVolumes->duckVolume[i];
+ }
+ }
+ else
+ {
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ if( m_In )
+ {
+ m_currentVolumes.duckVolume[i] = m_globalDuckSettings.duckVolume[i];
+ }
+ else
+ {
+ m_currentVolumes.duckVolume[i] = 1.0f;
+ }
+ }
+ }
+
+ if( targetVolumes != NULL )
+ {
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ m_targetVolumes.duckVolume[i] = targetVolumes->duckVolume[i];
+ }
+ }
+ else
+ {
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ if( m_In )
+ {
+ m_targetVolumes.duckVolume[i] = 1.0f;
+ }
+ else
+ {
+ m_targetVolumes.duckVolume[i] = m_globalDuckSettings.duckVolume[i];
+ }
+ }
+ }
+
+ //
+ // Now calculate the time steps
+ //
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ if ( m_Time == 0 )
+ {
+ // avoid divide by zero
+
+ m_stepValues[i] = FLT_MAX / 10.0f; // Some arbitrarily large number
+ }
+ else
+ {
+ m_stepValues[i] = ( rmt::Fabs( m_currentVolumes.duckVolume[i] - m_targetVolumes.duckVolume[i] ) ) / ( m_Time );
+ }
+ }
+
+ setState( );
+
+ addToUpdateList( );
+}
+
+//========================================================================
+// Fader::RegisterStateCallback
+//========================================================================
+
+void Fader::RegisterStateCallback( FaderStateChangeCallback* callback )
+{
+ //
+ // I'm assuming only one callback is set at a time
+ //
+ rAssert( m_callback == NULL );
+ m_callback = callback;
+}
+
+//========================================================================
+// Fader::UnRegisterStateCallback
+//========================================================================
+
+void Fader::UnRegisterStateCallback( FaderStateChangeCallback* callback )
+{
+ //
+ // Accept the callback as a parameter to test my assumption that
+ // we only set one at a time
+ //
+ rAssert( m_callback == callback );
+
+ m_callback = NULL;
+}
+
+//========================================================================
+// Fader::GetState
+//========================================================================
+
+Fader::State Fader::GetState( void )
+{
+ unsigned int i;
+ float targetValue;
+ State currentState = m_In ? FadedIn : FadedOut;
+
+ //
+ // Test each of the fading volumes. If one of them hasn't hit
+ // the target yet, we're still fading
+ //
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ targetValue = m_In ? 1.0f : m_globalDuckSettings.duckVolume[i];
+
+ if( m_currentVolumes.duckVolume[i] != targetValue )
+ {
+ currentState = m_In ? FadingIn : FadingOut;
+ break;
+ }
+ }
+
+ return( currentState );
+}
+
+//========================================================================
+// Fader::OnTimerDone
+//========================================================================
+
+void Fader::Update( unsigned int elapsed )
+{
+ unsigned int i;
+ float stepValue;
+ bool allTargetsHit = true;
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ stepValue = m_stepValues[i] * elapsed; // adjust for game chug.
+
+ if ( stepValue >= radSoundVolumeChangeThreshold )
+ {
+ stepValue = radSoundVolumeChangeThreshold;
+ }
+
+ if ( m_currentVolumes.duckVolume[i] < m_targetVolumes.duckVolume[i] )
+ {
+ m_currentVolumes.duckVolume[i] += stepValue;
+
+ if ( m_currentVolumes.duckVolume[i] >= m_targetVolumes.duckVolume[i] )
+ {
+ m_currentVolumes.duckVolume[i] = m_targetVolumes.duckVolume[i];
+ }
+ else
+ {
+ allTargetsHit = false;
+ }
+ }
+ else if ( m_currentVolumes.duckVolume[i] > m_targetVolumes.duckVolume[i] )
+ {
+ m_currentVolumes.duckVolume[i] -= stepValue;
+
+ if ( m_currentVolumes.duckVolume[i] <= m_targetVolumes.duckVolume[i] )
+ {
+ m_currentVolumes.duckVolume[i] = m_targetVolumes.duckVolume[i];
+ }
+ else
+ {
+ allTargetsHit = false;
+ }
+ }
+
+ }
+
+ BroadCast();
+
+ if ( allTargetsHit )
+ {
+ removeFromUpdateList( );
+
+ setState( );
+ }
+}
+
+//=============================================================================
+// Fader::UpdateAllFaders
+//=============================================================================
+// Description: Run through the fader list and update everything
+//
+// Parameters: elapsedTime - number of elapsed msecs since last call
+//
+// Return: void
+//
+//=============================================================================
+void Fader::UpdateAllFaders( unsigned int elapsedTime )
+{
+ Fader* currFader;
+
+ currFader = s_faderUpdateList;
+ while( currFader != NULL )
+ {
+ currFader->Update( elapsedTime );
+ currFader = currFader->m_nextUpdatableFader;
+ }
+}
+
+//=============================================================================
+// Fader::ReinitializeFader
+//=============================================================================
+// Description: Get the ducking parameters from the global settings object
+//
+// Parameters: ( globalSettings* settingObj )
+//
+// Return: void
+//
+//=============================================================================
+void Fader::ReinitializeFader( globalSettings* settingObj )
+{
+ unsigned int i;
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ if( settingObj == NULL )
+ {
+ m_globalDuckSettings.duckVolume[i] = 0.0f;
+ }
+ else
+ {
+ m_globalDuckSettings.duckVolume[i] =
+ settingObj->GetDuckVolume( m_duckSituation, static_cast<Sound::DuckVolumes>(i) );
+ }
+ }
+}
+
+//=============================================================================
+// Fader::Stop
+//=============================================================================
+// Description: Fader is being interrupted, get it out of the update list
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void Fader::Stop()
+{
+ removeFromUpdateList();
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+//========================================================================
+// Fader::setState
+//========================================================================
+
+void Fader::setState( void )
+{
+
+ if ( GetState( ) != m_State )
+ {
+ m_State = GetState( );
+
+ if( m_callback != NULL )
+ {
+ m_callback->OnStateChange( m_State );
+ }
+ }
+}
+
+//========================================================================
+// Fader::addToUpdateList
+//========================================================================
+void Fader::addToUpdateList()
+{
+ if( !faderInUpdateList() )
+ {
+ //
+ // Order doesn't matter, add it to the head of the list
+ //
+ m_nextUpdatableFader = s_faderUpdateList;
+ s_faderUpdateList = this;
+ }
+}
+
+//========================================================================
+// Fader::removeFromUpdateList
+//========================================================================
+void Fader::removeFromUpdateList()
+{
+ Fader* currentFader;
+
+ //
+ // Search for position in list. The list is usually one or two faders,
+ // I think, so don't bother with double-linked lists.
+ //
+ if( s_faderUpdateList == this )
+ {
+ s_faderUpdateList = m_nextUpdatableFader;
+ }
+ else
+ {
+ currentFader = s_faderUpdateList;
+ while( ( currentFader != NULL )
+ && ( currentFader->m_nextUpdatableFader != this ) )
+ {
+ currentFader = currentFader->m_nextUpdatableFader;
+ }
+
+ if( currentFader != NULL )
+ {
+ currentFader->m_nextUpdatableFader = m_nextUpdatableFader;
+ }
+ }
+
+ m_nextUpdatableFader = NULL;
+}
+
+//=============================================================================
+// Fader::faderInUpdateList
+//=============================================================================
+// Description: Indicate whether this fader is currently in the update list
+//
+// Parameters: None
+//
+// Return: true if in list, false otherwise
+//
+//=============================================================================
+bool Fader::faderInUpdateList()
+{
+ Fader* currFader;
+
+ currFader = s_faderUpdateList;
+ while( currFader != NULL )
+ {
+ if( currFader == this )
+ {
+ return( true );
+ }
+
+ currFader = currFader->m_nextUpdatableFader;
+ }
+
+ return( false );
+}
diff --git a/game/code/sound/soundrenderer/fader.h b/game/code/sound/soundrenderer/fader.h
new file mode 100644
index 0000000..492080d
--- /dev/null
+++ b/game/code/sound/soundrenderer/fader.h
@@ -0,0 +1,146 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: fader.h
+//
+// Description: Declaration for Fader class which brings down volume on
+// associated multi-input knob. Replaces IRadSoundFade
+// objects from radsound/util.
+//
+// History: 13/08/2002 + Created -- Darren
+//
+//=============================================================================
+
+#ifndef FADER_H
+#define FADER_H
+
+//========================================
+// Nested Includes
+//========================================
+#include <radobject.hpp>
+
+#include <sound/soundrenderer/dasoundgroup.h>
+#include <sound/tuning/globalsettings.h>
+
+//========================================
+// Forward References
+//========================================
+
+struct FaderStateChangeCallback;
+
+namespace Sound
+{
+ class daSoundPlayerManager;
+ struct IDaSoundTuner;
+}
+
+//=============================================================================
+//
+// Synopsis: Fader
+//
+//=============================================================================
+
+class Fader : public radRefCount
+{
+ public:
+ IMPLEMENT_REFCOUNTED( "Fader" );
+
+ Fader( globalSettings* duckSettings,
+ Sound::DuckSituations situation,
+ Sound::daSoundPlayerManager& playerMgr,
+ Sound::IDaSoundTuner& tuner );
+ ~Fader();
+
+ void Update( unsigned int elapsed );
+ static void UpdateAllFaders( unsigned int elapsedTime );
+
+ void Stop();
+
+ void SetTime( unsigned int milliseconds );
+ unsigned int GetTime( void );
+
+ void Fade( bool in, Sound::DuckVolumeSet* initialVolumes = NULL, Sound::DuckVolumeSet* targetVolumes = NULL );
+
+ float GetCurrentVolume( Sound::DuckVolumes volumeKnob ) { return( m_currentVolumes.duckVolume[volumeKnob] ); }
+ float GetTargetSettings( Sound::DuckVolumes volumeKnob ) { return( m_globalDuckSettings.duckVolume[volumeKnob] ); }
+
+ enum State { FadedIn, FadedOut, FadingIn, FadingOut };
+
+ void RegisterStateCallback( FaderStateChangeCallback* callback );
+ void UnRegisterStateCallback( FaderStateChangeCallback* callback );
+
+ State GetState( void );
+
+ void BroadCast( void );
+
+ Sound::DuckSituations GetSituation( void ) { return( m_duckSituation ); }
+
+ void ReinitializeFader( globalSettings* settingObj );
+
+ private:
+ //Prevent wasteful constructor creation.
+ Fader();
+ Fader( const Fader& original );
+ Fader& operator=( const Fader& rhs );
+
+ void setState();
+
+ //
+ // Add and remove fader from the update list. We should only update
+ // the fader if it's not on its target value yet.
+ //
+ void addToUpdateList();
+ void removeFromUpdateList();
+ bool faderInUpdateList();
+
+ unsigned int m_Time;
+ bool m_In;
+ State m_State;
+
+ Sound::DuckVolumeSet m_currentVolumes;
+ float m_stepValues[Sound::NUM_DUCK_VOLUMES];
+ Sound::DuckVolumeSet m_targetVolumes;
+ Sound::DuckVolumeSet m_globalDuckSettings;
+
+ Sound::DuckSituations m_duckSituation;
+
+ //
+ // Callback object for state change notification. Was a list of objects
+ // in radSoundFade
+ //
+ FaderStateChangeCallback* m_callback;
+
+ //
+ // Static fader list, used for updates
+ //
+ static Fader* s_faderUpdateList;
+
+ //
+ // Pointer used to hold place in update list
+ //
+ Fader* m_nextUpdatableFader;
+
+ //
+ // Player manager, used to actually do the fading
+ //
+ Sound::daSoundPlayerManager& m_playerManager;
+
+ //
+ // Tuner, stores the results
+ //
+ Sound::IDaSoundTuner& m_tuner;
+};
+
+//=============================================================================
+//
+// Synopsis: FaderStateChangeCallback
+//
+//=============================================================================
+struct FaderStateChangeCallback
+{
+ virtual void OnStateChange( Fader::State newState );
+};
+
+
+#endif // FADER_H
+
diff --git a/game/code/sound/soundrenderer/idasoundresource.h b/game/code/sound/soundrenderer/idasoundresource.h
new file mode 100644
index 0000000..f6564db
--- /dev/null
+++ b/game/code/sound/soundrenderer/idasoundresource.h
@@ -0,0 +1,172 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: idasoundresource.hpp
+//
+// Subsystem: Dark Angel - Sound resources
+//
+// Description: Defines the interface for a sound resource
+//
+// WARNING: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// IF THIS FILE IS MODIFIED THE TYPE INFO FILE MUST BE REGENERATED
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//
+// Revisions:
+// + Created October 3, 2001 -- aking
+//
+//=============================================================================
+
+#ifndef _IDASOUNDRESOURCE_HPP
+#define _IDASOUNDRESOURCE_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+
+#include <sound/soundrenderer/dasoundgroup.h>
+
+//=============================================================================
+// Definitions and macros
+//=============================================================================
+
+//
+// This is the maximum number of file variations that can exist in a resource.
+//
+#define DASound_MaxNumSoundResourceFiles 7
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+struct IDaSoundResource;
+
+//=============================================================================
+// Typedefs and enumerations
+//=============================================================================
+
+//
+// A procedure used to modify a sound resource
+//
+typedef void daSoundResourceProc( IDaSoundResource* pRes, void* pUserData );
+
+//=============================================================================
+// Interface Definitions
+//=============================================================================
+
+//
+// IDaSoundResourceData contains sound resource data.
+//
+struct IDaSoundResourceData : public IRefCount
+{
+ // SCRIPTED FEATURES THAT CAN BE TUNED IN REAL TIME
+
+ //
+ // Add files to the resource
+ //
+ virtual void AddFilename
+ (
+ const char* newFileName,
+ float trim
+ ) = 0;
+
+ //
+ // Set the pitch variation
+ //
+ virtual void SetPitchRange
+ (
+ float minPitch,
+ float maxPitch
+ ) = 0;
+
+ //
+ // Set the trim variation
+ //
+ virtual void SetTrimRange
+ (
+ float minTrim,
+ float maxTrim
+ ) = 0;
+
+ //
+ // Set the trim to one value
+ //
+ virtual void SetTrim( float trim ) = 0;
+
+ // SCRIPTED FEATURES THAT CAN NOT BE TUNED IN REAL TIME
+
+ // Is this a streaming sound resource?
+ virtual void SetStreaming( bool streaming ) = 0;
+
+ // Is this a looping sound resource?
+ virtual void SetLooping( bool looping ) = 0;
+
+ // SCRIPTED FEATURES AVAILABLE ONLY FOR TUNERS
+
+ // Play the resource
+ virtual void Play( void ) = 0;
+};
+
+//
+// IDaSoundResource is based on an IDaSoundResourceData. It adds functionality
+// to get parameters, and to capture/release resources.
+//
+struct IDaSoundResource : public IDaSoundResourceData
+{
+ // A resource file description
+ struct daSoundResourceFileDesc
+ {
+ char* m_Filename;
+ float m_Trim;
+ int m_TableIndex;
+ };
+
+ //
+ // Monitor files in the resource
+ //
+ virtual unsigned int GetNumFiles( void ) = 0;
+
+ virtual void GetFileNameAt( unsigned int index, char* buffer, unsigned int max ) = 0;
+ virtual void GetFileKeyAt( unsigned int index, char* buffer, unsigned int max ) = 0;
+ //
+ // Get parameters set in IDaSoundResourceData
+ //
+ virtual void GetPitchRange
+ (
+ float* pMinPitch,
+ float* pMaxPitch
+ ) = 0;
+ virtual void GetTrimRange
+ (
+ float* pMinTrim,
+ float* pMaxTrim
+ ) = 0;
+ virtual bool GetLooping( void ) = 0;
+
+ //
+ // Find out what kind of resource this is
+ //
+ enum Type {
+ UNKNOWN,
+ CLIP,
+ STREAM
+ };
+ virtual Type GetType( void ) = 0;
+
+ //
+ // Modify the sound group that this resource belongs to
+ //
+ virtual void SetSoundGroup( Sound::daSoundGroup soundGroup ) = 0;
+ virtual Sound::daSoundGroup GetSoundGroup( void ) = 0;
+
+ //
+ // Capture and release the resource
+ //
+ virtual void CaptureResource( void ) = 0;
+ virtual bool IsCaptured( void ) = 0;
+ virtual void ReleaseResource( void ) = 0;
+};
+
+//}; //Sound Namespace
+#endif // _IDASOUNDRESOURCE_HPP
diff --git a/game/code/sound/soundrenderer/idasoundtuner.h b/game/code/sound/soundrenderer/idasoundtuner.h
new file mode 100644
index 0000000..c537af2
--- /dev/null
+++ b/game/code/sound/soundrenderer/idasoundtuner.h
@@ -0,0 +1,205 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: idasoundtuner.hpp
+//
+// Subsystem: Dark Angel - Sound Tuner System
+//
+// Description: Description of the DA sound tuner interface
+//
+// Revisions:
+// + Created October 4, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _IDASOUNDTUNER_HPP
+#define _IDASOUNDTUNER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+
+#include <sound/soundrenderer/dasoundgroup.h>
+#include <sound/soundrenderer/soundsystem.h>
+
+#include <sound/tuning/globalsettings.h>
+
+//=============================================================================
+// Global namespace forward declarations
+//=============================================================================
+
+struct IRadSoundMultiInputKnob;
+class Fader;
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+struct IDaSoundWiring;
+struct IDaSoundTuner;
+struct IDaSoundFadeState;
+
+//=============================================================================
+// Interfaces
+//=============================================================================
+
+//
+// Wire together various sound groups that take the form of multi-input
+// knobs.
+//
+struct IDaSoundWiring : public IRefCount
+{
+ //
+ // Wire a sound group to a path
+ //
+ virtual void WirePath
+ (
+ daSoundGroup soundGroup,
+ const char* path
+ ) = 0;
+
+ //
+ // Initialize the sound groups
+ //
+ virtual void WireGroup( daSoundGroup slaveGroup, daSoundGroup masterGroup ) = 0;
+};
+
+//
+// The sound tuner is responsible for managing global settings and various
+// "wirings" of the sound system. It allows the generation of tuner instances
+// for controlling various game parameters, and it manages common global
+// sound settings (like ducking, master volume, pause/continue/cancel,
+// mono/stereo).
+//
+struct IDaSoundTuner : public IDaSoundWiring
+{
+ //
+ // Initialize and perform all wiring. This will lock down the resources
+ // if they have not been locked already.
+ //
+ virtual void Initialize( void ) = 0;
+
+ //
+ // Create faders after we've got scripts to latch them to
+ //
+ virtual void PostScriptLoadInitialize() = 0;
+
+ //
+ // Service the tuner
+ //
+ virtual void ServiceOncePerFrame( unsigned int elapsedTime ) = 0;
+
+ //
+ // Modify the sound output mode
+ //
+ enum SoundOutputMode
+ {
+ MONO,
+ STEREO,
+ SURROUND
+ };
+ virtual void SetSoundOutputMode
+ (
+ SoundOutputMode outputMode
+ ) = 0;
+ virtual SoundOutputMode GetSoundOutputMode( void ) = 0;
+
+ // SPECIALIZED SOUND SETTINGS FOR COMMON CONTROL
+
+ //
+ // Duck sounds
+ //
+ virtual void ActivateDuck( IDaSoundFadeState* pObject,
+ void* pUserData,
+ bool fadeIn ) = 0;
+
+ virtual void ActivateSituationalDuck( IDaSoundFadeState* pObject,
+ DuckSituations situation,
+ void* pUserData,
+ bool fadeIn ) = 0;
+ virtual void ResetDuck() = 0;
+
+ //
+ // Common volume controls
+ //
+ virtual void SetMasterVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetMasterVolume( void ) = 0;
+
+ virtual void SetDialogueVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetDialogueVolume( void ) = 0;
+
+ virtual void SetMusicVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetMusicVolume( void ) = 0;
+
+ virtual void SetAmbienceVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetAmbienceVolume( void ) = 0;
+
+ virtual void SetSfxVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetSfxVolume( void ) = 0;
+
+ virtual void SetCarVolume( daTrimValue volume ) = 0;
+ virtual daTrimValue GetCarVolume( void ) = 0;
+
+ virtual daTrimValue GetGroupTrim( daSoundGroup group ) = 0;
+ virtual daTrimValue GetFaderGroupTrim( daSoundGroup group ) = 0;
+
+ virtual void MuteNIS() = 0;
+ virtual void UnmuteNIS() = 0;
+
+ virtual void SetFaderGroupTrim( Sound::DuckVolumes group, daTrimValue trim ) = 0;
+
+ // GENERAL SOUND SETTINGS
+
+ //
+ // Fade a sound group
+ //
+ virtual void FadeSounds( IDaSoundFadeState* pObject,
+ void* pUserData,
+ Fader* pFader,
+ bool fadeIn,
+ DuckVolumeSet* initialVolumes = NULL ) = 0;
+
+
+ //
+ // Sound group info
+ //
+ virtual bool IsSlaveGroup( daSoundGroup slave, daSoundGroup master ) = 0;
+
+};
+
+//=============================================================================
+// Public functions
+//=============================================================================
+
+//
+// Do the wiring of the sound system
+//
+void daSoundTunerWireSystem
+(
+ IDaSoundWiring* pWiring
+);
+
+//=============================================================================
+// Factory functions
+//=============================================================================
+
+//
+// Create the tuner manager
+//
+void daSoundTunerCreate
+(
+ IDaSoundTuner** ppTuner,
+ radMemoryAllocator allocator
+);
+
+} // Sound Namespace
+#endif //_IDASOUNDTUNER_HPP
+
diff --git a/game/code/sound/soundrenderer/musicsoundplayer.cpp b/game/code/sound/soundrenderer/musicsoundplayer.cpp
new file mode 100644
index 0000000..365b8ef
--- /dev/null
+++ b/game/code/sound/soundrenderer/musicsoundplayer.cpp
@@ -0,0 +1,300 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: musicsoundplayer.cpp
+//
+// Subsystem: Dark Angel - Sound players
+//
+// Description: Implements the a Dark Angel sound player
+//
+// Revisions:
+// + Created October 16, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <sound/soundrenderer/musicsoundplayer.h>
+
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+
+#include <sound/soundmanager.h>
+
+//=============================================================================
+// Static Variables (outside namespace)
+//=============================================================================
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Debug Information
+//=============================================================================
+
+//=============================================================================
+// Definitions Macros and Constants
+//=============================================================================
+
+//=============================================================================
+// Local functions
+//=============================================================================
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// MusicSoundPlayer Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: MusicSoundPlayer::MusicSoundPlayer
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+MusicSoundPlayer::MusicSoundPlayer( )
+ :
+ m_isMusic( true ),
+ m_PlayerTrim( 1.0f ),
+ m_ResourceTrim( 1.0f ),
+ m_ExternalTrim( 1.0f ),
+ m_GroupTrim( 1.0f ),
+ m_FaderGroupTrim( 1.0f ),
+ m_MasterTrim( 1.0f )
+{
+}
+
+//=============================================================================
+// Function: MusicSoundPlayer::~MusicSoundPlayer
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+MusicSoundPlayer::~MusicSoundPlayer( )
+{
+}
+
+//=============================================================================
+// Function: MusicSoundPlayer::Initialize
+//=============================================================================
+// Description: Initialize the sound player to determine whether it will
+// set the trim for music or ambience
+//
+//-----------------------------------------------------------------------------
+void MusicSoundPlayer::Initialize( bool isMusic )
+{
+ m_isMusic = isMusic;
+
+ //
+ // Set the group trim
+ //
+ if( m_isMusic )
+ {
+ SetGroupTrim( daSoundRenderingManagerGet()->GetTuner()->GetGroupTrim( Sound::MUSIC ) );
+ }
+ else
+ {
+ SetGroupTrim( daSoundRenderingManagerGet()->GetTuner()->GetGroupTrim( Sound::AMBIENCE ) );
+ }
+}
+
+//=============================================================================
+// MusicSoundPlayer::GetSoundGroup
+//=============================================================================
+// Description: Unlike regular sound players, our group is determined by
+// the music/ambience specification from initialization, not
+// by an associated sound resource
+//
+// Parameters: None
+//
+// Return: sound group (either MUSIC or AMBIENCE)
+//
+//=============================================================================
+daSoundGroup MusicSoundPlayer::GetSoundGroup()
+{
+ if( m_isMusic )
+ {
+ return( Sound::MUSIC );
+ }
+ else
+ {
+ return( Sound::AMBIENCE );
+ }
+}
+
+//=============================================================================
+// MusicSoundPlayer::SetExternalTrim
+//=============================================================================
+// Description: Set arbitrary player trim. May not be needed.
+//
+// Parameters: newTrim - new trim value
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::SetExternalTrim( float newTrim )
+{
+ m_ExternalTrim = newTrim;
+ m_PlayerTrim = m_ResourceTrim * m_ExternalTrim * m_GroupTrim * m_FaderGroupTrim * m_MasterTrim;
+
+ ResetMusicTrim();
+}
+
+//=============================================================================
+// MusicSoundPlayer::SetGroupTrim
+//=============================================================================
+// Description: Set sound group trim
+//
+// Parameters: newTrim - new trim setting
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::SetGroupTrim( float newTrim )
+{
+ m_GroupTrim = newTrim;
+ m_PlayerTrim = m_ResourceTrim * m_ExternalTrim * m_GroupTrim * m_FaderGroupTrim * m_MasterTrim;
+
+ ResetMusicTrim();
+}
+
+//=============================================================================
+// MusicSoundPlayer::SetFaderGroupTrim
+//=============================================================================
+// Description: Set sound group fader trim
+//
+// Parameters: newTrim - new trim setting
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::SetFaderGroupTrim( float newTrim )
+{
+ m_FaderGroupTrim = newTrim;
+ m_PlayerTrim = m_ResourceTrim * m_ExternalTrim * m_GroupTrim * m_FaderGroupTrim * m_MasterTrim;
+
+ ResetMusicTrim();
+}
+
+//=============================================================================
+// MusicSoundPlayer::SetMasterTrim
+//=============================================================================
+// Description: Set master trim. Duh.
+//
+// Parameters: newTrim - new trim setting
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::SetMasterTrim( float newTrim )
+{
+ m_MasterTrim = newTrim;
+ m_PlayerTrim = m_ResourceTrim * m_ExternalTrim * m_GroupTrim * m_FaderGroupTrim * m_MasterTrim;
+
+ ResetMusicTrim();
+}
+
+//
+// TODO: revisit trim functions below. They're identical to the one in the base
+// class, should be virtual.
+//
+
+//=============================================================================
+// MusicSoundPlayer::ChangeTrim
+//=============================================================================
+// Description: Change the trim setting for a sound group, or for the master
+// volume
+//
+// Parameters: groupName - name of group to change
+// newTrim - trim value
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::ChangeTrim( daSoundGroup groupName, float newTrim )
+{
+ daSoundGroup myGroup = GetSoundGroup();
+
+ if ( myGroup == groupName )
+ {
+ SetGroupTrim(newTrim);
+ }
+ else if ( groupName == MASTER )
+ {
+ SetMasterTrim(newTrim);
+ }
+ else if ( daSoundRenderingManagerGet()->GetTuner()->IsSlaveGroup( myGroup, groupName ) )
+ {
+ SetGroupTrim(newTrim);
+ }
+}
+
+//=============================================================================
+// MusicSoundPlayer::ChangeFaderTrim
+//=============================================================================
+// Description: Change the trim setting for a sound group, or for the master
+// volume
+//
+// Parameters: groupName - name of group to change
+// newTrim - trim value
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::ChangeFaderTrim( daSoundGroup groupName, float newTrim )
+{
+ daSoundGroup myGroup = GetSoundGroup();
+
+ //
+ // Shouldn't change master volume here, use ChangeTrim
+ //
+ rAssert( groupName != MASTER );
+
+ if ( myGroup == groupName )
+ {
+ SetFaderGroupTrim(newTrim);
+ }
+ else if ( daSoundRenderingManagerGet()->GetTuner()->IsSlaveGroup( myGroup, groupName ) )
+ {
+ SetFaderGroupTrim(newTrim);
+ }
+}
+
+
+//=============================================================================
+// Private functions
+//=============================================================================
+
+//=============================================================================
+// MusicSoundPlayer::resetMusicTrim
+//=============================================================================
+// Description: Update the music player with the given trim setting
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void MusicSoundPlayer::ResetMusicTrim()
+{
+ if( m_isMusic )
+ {
+ GetSoundManager()->SetMusicVolumeWithoutTuner( m_PlayerTrim );
+ }
+ else
+ {
+ GetSoundManager()->SetAmbienceVolumeWithoutTuner( m_PlayerTrim );
+ }
+}
+
+} // Sound Namespace
+
diff --git a/game/code/sound/soundrenderer/musicsoundplayer.h b/game/code/sound/soundrenderer/musicsoundplayer.h
new file mode 100644
index 0000000..15cedb3
--- /dev/null
+++ b/game/code/sound/soundrenderer/musicsoundplayer.h
@@ -0,0 +1,112 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: musicsoundplayer.hpp
+//
+// Subsystem: Dark Angel - Sound players
+//
+// Description: Used to hack in volume control for RadMusic, even though
+// it doesn't go through the DA system
+//
+// Revisions:
+// + Hacked 5 Mar 03 -- Esan
+//
+//=============================================================================
+
+#ifndef _MUSICSOUNDPLAYER_HPP
+#define _MUSICSOUNDPLAYER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <sound/soundrenderer/soundplayer.h>
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+//=============================================================================
+// Typdefs and enumerations
+//=============================================================================
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+//
+// This contains a DA player instance.
+//
+class MusicSoundPlayer : public daSoundPlayerBase
+{
+public:
+ //
+ // Constructor and destructor
+ //
+ MusicSoundPlayer ( );
+ virtual ~MusicSoundPlayer ( );
+
+ void Initialize ( bool isMusic );
+
+ // Suspend the player if it should be playing, but no one can hear it
+ void Suspend ( void );
+
+ void SetExternalTrim( float newTrim );
+ void SetGroupTrim( float newTrim );
+ void SetFaderGroupTrim( float newTrim );
+ void SetMasterTrim( float newTrim );
+
+ daSoundGroup GetSoundGroup ( void );
+
+ unsigned int GetPlaybackTimeInSamples ( void );
+
+ // daSoundPlayerBase
+
+ virtual void ServiceOncePerFrame( void ) { }
+ virtual bool IsCaptured ( void ) { return true; }
+ virtual void Pause ( void ) { }
+ virtual bool IsPaused( void ) { return false; }
+ virtual void Continue ( void ) { }
+ virtual void UberContinue( void ) { }
+ virtual void Stop ( void ) { }
+ virtual void SetPitch( float pitch ) { }
+
+ virtual void ChangeTrim( daSoundGroup groupName, float newTrim );
+ virtual void ChangeFaderTrim( daSoundGroup groupName, float newTrim );
+
+
+private:
+ void ResetMusicTrim( );
+
+ bool m_isMusic;
+
+ //
+ // Trim values
+ //
+ float m_PlayerTrim;
+ float m_ResourceTrim;
+ float m_ExternalTrim;
+ float m_GroupTrim;
+ float m_FaderGroupTrim;
+ float m_MasterTrim;
+
+};
+
+
+//=============================================================================
+// Public Functions
+//=============================================================================
+
+} // Sound Namespace
+#endif //_MUSICSOUNDPLAYER_HPP
+
diff --git a/game/code/sound/soundrenderer/playermanager.cpp b/game/code/sound/soundrenderer/playermanager.cpp
new file mode 100644
index 0000000..9a92b77
--- /dev/null
+++ b/game/code/sound/soundrenderer/playermanager.cpp
@@ -0,0 +1,989 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: playermagaer.cpp
+//
+// Subsystem: Dark Angel - Player Manager System
+//
+// Description: Implementation of the DA sound player manager
+//
+// Revisions:
+// + Created October 16, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radobjectlist.hpp>
+#include <raddebug.hpp>
+#include <radlinkedclass.hpp>
+#include <radnamespace.hpp>
+#include <radsound_hal.hpp>
+
+#include <memory/srrmemory.h>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/dasoundgroup.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/playermanager.h>
+#include <sound/soundrenderer/soundplayer.h>
+#include <sound/soundrenderer/musicsoundplayer.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/fader.h>
+#include <sound/soundrenderer/soundconstants.h>
+#include <sound/soundrenderer/soundnucleus.hpp>
+
+#include <pddi/pddi.hpp>
+#include <p3d/utility.hpp>
+#include <p3d/p3dtypes.hpp>
+
+#include <radobjectbtree.hpp>
+
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Debug Information
+//=============================================================================
+
+daSoundPlayerManager * daSoundPlayerManager::s_pInstance = 0;
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundAsyncFadeCallback Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::daSoundAsyncFadeCallback
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundAsyncFadeCallback::daSoundAsyncFadeCallback( )
+:
+radObject( ),
+m_Action( 0 ),
+m_pPlayerManager( NULL ),
+m_pCallback( NULL ),
+m_pUserData( NULL )
+{
+
+}
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::~daSoundAsyncFadeCallback
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundAsyncFadeCallback::~daSoundAsyncFadeCallback( )
+{
+
+ if( m_pCallback != NULL )
+ {
+ m_pCallback->Release( );
+ }
+ if( m_pPlayerManager != NULL )
+ {
+ m_pPlayerManager->Release( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::SetPlayerManager
+//=============================================================================
+// Description: Set the player manager
+//
+//-----------------------------------------------------------------------------
+
+void daSoundAsyncFadeCallback::SetPlayerManager
+(
+ daSoundPlayerManager* pPlayerManager
+)
+{
+ rAssert( m_pPlayerManager == NULL );
+ rAssert( pPlayerManager != NULL );
+
+ m_pPlayerManager = pPlayerManager;
+ m_pPlayerManager->AddRef( );
+}
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::GetPlayerManager
+//=============================================================================
+// Description: Get the player manager
+//
+//-----------------------------------------------------------------------------
+
+daSoundPlayerManager* daSoundAsyncFadeCallback::GetPlayerManager( void )
+{
+ return m_pPlayerManager;
+}
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::SetCallback
+//=============================================================================
+// Description: Set the fade callback
+//
+//-----------------------------------------------------------------------------
+
+void daSoundAsyncFadeCallback::SetCallback
+(
+ IDaSoundFadeState* pCallback,
+ void* pUserData
+)
+{
+ rAssert( m_pCallback == NULL );
+ m_pCallback = pCallback;
+ m_pUserData = pUserData;
+
+ if( m_pCallback != NULL )
+ {
+ m_pCallback->AddRef( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundAsyncFadeCallback::GetCallback
+//=============================================================================
+// Description: Get the fade callback
+//
+//-----------------------------------------------------------------------------
+
+void daSoundAsyncFadeCallback::GetCallback( IDaSoundFadeState** ppCallback, void** ppUserData )
+{
+ rAssert( ppCallback != NULL );
+ rAssert( ppUserData != NULL );
+
+ *ppCallback = m_pCallback;
+ *ppUserData = m_pUserData;
+}
+
+
+//=============================================================================
+// daSoundPlayerManager Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundPlayerManager::daSoundPlayerManager
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundClipStreamPlayer * gClipPlayerArray[ SOUND_NUM_CLIP_PLAYERS ];
+daSoundClipStreamPlayer * gStreamPlayerArray [ SOUND_NUM_STREAM_PLAYERS ];
+
+daSoundPlayerManager::daSoundPlayerManager( )
+ :
+ radRefCount( 0 )
+{
+ m_pIngameFadeIn = NULL;
+ m_pIngameFadeOut = NULL;
+ m_pMusicPlayer = NULL;
+ m_pAmbiencePlayer = NULL;
+ m_Initialized = false;
+
+ s_pInstance = this;
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::~daSoundPlayerManager
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundPlayerManager::~daSoundPlayerManager( )
+{
+ s_pInstance = NULL;
+ // Release our faders
+ if( m_pIngameFadeOut != NULL )
+ {
+ m_pIngameFadeOut->Release();
+ m_pIngameFadeOut = NULL;
+ }
+ if( m_pIngameFadeIn != NULL )
+ {
+ m_pIngameFadeIn->Release();
+ m_pIngameFadeIn = NULL;
+ }
+
+ // Release music players
+ if( m_pMusicPlayer != NULL )
+ {
+ m_pMusicPlayer->Release();
+ m_pMusicPlayer = NULL;
+ }
+ if( m_pAmbiencePlayer != NULL )
+ {
+ m_pAmbiencePlayer->Release();
+ m_pAmbiencePlayer = NULL;
+ }
+
+ for( unsigned int c = 0; c < SOUND_NUM_CLIP_PLAYERS; c ++ )
+ {
+ gClipPlayerArray[ c ]->Release( );
+ }
+
+ for( unsigned int s = 0; s < SOUND_NUM_STREAM_PLAYERS; s ++ )
+ {
+ gStreamPlayerArray[ s ]->Release( );
+ }
+}
+
+//=============================================================================
+// daSoundPlayerManager::UglyHackPostInitialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( IDaSoundTuner* pTuner )
+//
+// Return: void
+//
+//=============================================================================
+void daSoundPlayerManager::UglyHackPostInitialize( IDaSoundTuner* pTuner )
+{
+ // Ingame faders
+ m_pIngameFadeIn = new( GMA_PERSISTENT ) Fader( NULL, DUCK_FULL_FADE, *this, *pTuner );
+ rAssert( m_pIngameFadeIn != NULL );
+
+ m_pIngameFadeOut = new( GMA_PERSISTENT ) Fader( NULL, DUCK_FULL_FADE, *this, *pTuner );
+ rAssert( m_pIngameFadeOut != NULL );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::GetObjectSize
+//=============================================================================
+// Description: Get the size of the sound player object
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundPlayerManager::GetObjectSize( void )
+{
+ unsigned int thisSize = sizeof( *this );
+ return thisSize;
+}
+
+unsigned int daSoundPlayerManager::GetNumUsedClipPlayers()
+{
+ unsigned int playerCount = 0;
+
+ for( unsigned int c = 0; c < SOUND_NUM_CLIP_PLAYERS; c ++ )
+ {
+ if ( gClipPlayerArray[ c ]->IsCaptured( ) )
+ {
+ playerCount++;
+ }
+ }
+
+ return( playerCount );
+}
+
+unsigned int daSoundPlayerManager::GetNumUsedStreamPlayers()
+{
+ unsigned int playerCount = 0;
+
+ for( unsigned int s = 0; s < SOUND_NUM_STREAM_PLAYERS; s ++ )
+ {
+ if ( gStreamPlayerArray[ s ]->IsCaptured( ) )
+ {
+ playerCount++;
+ }
+ }
+
+ return playerCount;
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::Initialize
+//=============================================================================
+// Description: Initialize the player manager
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::Initialize( void )
+{
+ // The stream players are tuned from associated radscripts
+
+ IRadSoundClipPlayer* pClipPlayer = NULL;
+ IRadSoundStreamPlayer* pStreamPlayer = NULL;
+ IRadSoundStitchedDataSource* pStitchedDataSource = NULL;
+
+ // CLIP PLAYERS ///////////////////////////////////////////////////////////
+
+ for( unsigned int c = 0; c < SOUND_NUM_CLIP_PLAYERS; c++ )
+ {
+ gClipPlayerArray[ c ] = new (GetThisAllocator( ) ) daSoundClipStreamPlayer( );
+ gClipPlayerArray[ c ]->AddRef( );
+ gClipPlayerArray[ c ]->InitializeAsClipPlayer( );
+ }
+
+ // STREAM PLAYERS /////////////////////////////////////////////////////////
+
+ for( unsigned int s = 0; s < SOUND_NUM_STREAM_PLAYERS; s++ )
+ {
+
+ gStreamPlayerArray[ s ] = new ( GetThisAllocator() ) daSoundClipStreamPlayer;
+ gStreamPlayerArray[ s ]->AddRef( );
+ gStreamPlayerArray[ s ]->InitializeAsStreamPlayer( );
+ }
+
+ //
+ // Make a couple of fake players for controlling music and
+ // ambience trim
+ //
+
+ // Create a music and an ambience sound player
+ m_pMusicPlayer = new( GetThisAllocator() ) MusicSoundPlayer;
+ m_pMusicPlayer->AddRef( );
+ m_pMusicPlayer->Initialize( true );
+
+ m_pAmbiencePlayer = new( GetThisAllocator() ) MusicSoundPlayer;
+ m_pAmbiencePlayer->AddRef( );
+ m_pAmbiencePlayer->Initialize( false );
+
+ m_Initialized = true;
+
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::ServiceOncePerFrame
+//=============================================================================
+// Description: Service once per frame
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::ServiceOncePerFrame( void )
+{
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ pPlayer->ServiceOncePerFrame( );
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::CaptureFreePlayer
+//=============================================================================
+// Description: This function finds and captures a sound player
+// and connects the given resource to it.
+//
+// Parameters: ppPlayer - (out) the captured player or NULL if one can't be
+// found
+// pResource - a pointer to a sound resource
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::CaptureFreePlayer
+(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource,
+ bool positional
+)
+{
+ rAssert( ppPlayer != NULL );
+ rAssert( pResource != NULL );
+
+ // Find out where to look
+ unsigned int i = 0;
+ bool playerFound = false;
+ daSoundGroup soundGroup = pResource->GetSoundGroup( );
+ IDaSoundResource::Type resourceType = pResource->GetType( );
+
+ switch( pResource->GetType( ) )
+ {
+ case IDaSoundResource::CLIP:
+ {
+ // Look in the clip player list
+ playerFound = FindFreeClipPlayer( ppPlayer, pResource );
+ break;
+ }
+ case IDaSoundResource::STREAM:
+ {
+ // Look in the stream player list
+ playerFound = FindFreeStreamPlayer( ppPlayer, pResource );
+ break;
+ }
+ default:
+ {
+ rAssert( 0 );
+ break;
+ }
+ }
+ if( playerFound )
+ {
+ // Capture it
+ (*ppPlayer)->Capture( pResource, positional );
+ }
+ else
+ {
+ (*ppPlayer) = NULL;
+ }
+
+}
+
+bool daSoundPlayerManager::FindFreePlayer(
+ daSoundClipStreamPlayer** ppPlayerArray,
+ unsigned int numPlayers,
+ daSoundClipStreamPlayer ** ppPlayer )
+{
+ *ppPlayer = 0;
+
+ for( unsigned int c = 0; c < numPlayers; c ++ )
+ {
+ if ( false == ppPlayerArray[ c ]->IsCaptured( ) )
+ {
+ *ppPlayer = ppPlayerArray[ c ];
+ break;
+ }
+ }
+
+ return NULL != *ppPlayer;
+}
+
+
+//=============================================================================
+// Function: daSoundPlayerManager::FindFreeClipPlayer
+//=============================================================================
+// Description: Find a free clip player
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundPlayerManager::FindFreeClipPlayer(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource
+)
+{
+ return FindFreePlayer( gClipPlayerArray, SOUND_NUM_CLIP_PLAYERS, ppPlayer );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::FindFreeStreamPlayer
+//=============================================================================
+// Description: Find a free stream player
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundPlayerManager::FindFreeStreamPlayer(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource )
+{
+ return FindFreePlayer( gStreamPlayerArray, SOUND_NUM_STREAM_PLAYERS, ppPlayer );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::PausePlayers
+//=============================================================================
+// Description: Pause the sound players
+//
+// Parameters: stackFrame - the stack frame that a player is associated with.
+// If NULL, all players pause.
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::PausePlayers
+(
+)
+{
+ //
+ // Pause all players
+ //
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ pPlayer->Pause( );
+
+ // Move on
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::PausePlayersWithFade
+//=============================================================================
+// Description: Fade out the players and then pause
+//
+// Parameters: see PausePlayers
+// pCallback - the asynchronous callback to call when done
+// pUserData - the user data to pass into the callback
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::PausePlayersWithFade
+(
+ IDaSoundFadeState* pCallback,
+ void* pUserData
+)
+{
+ // Create the fade info
+ daSoundAsyncFadeCallback* pFadeInfo = new( GMA_TEMP ) daSoundAsyncFadeCallback( );
+ rAssert( pFadeInfo != NULL );
+ pFadeInfo->SetPlayerManager( this );
+ pFadeInfo->SetAction( OnFade_PausePlayers );
+ pFadeInfo->SetCallback( pCallback, pUserData );
+
+ // Start fading the sounds
+ rAssert( m_pIngameFadeOut != NULL );
+ Sound::daSoundRenderingManagerGet( )->GetTuner( )->FadeSounds
+ (
+ this,
+ pFadeInfo,
+ m_pIngameFadeOut,
+ false
+ );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::ContinuePlayers
+//=============================================================================
+// Description: Continue the sound players
+//
+// Parameters: stackFrame - the stack frame that a player is associated with.
+// If NULL, all players continue.
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::ContinuePlayers
+(
+)
+{
+ //
+ // Continue all players
+ //
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ if( pPlayer->IsPaused() )
+ {
+ pPlayer->Continue( );
+ }
+
+ // Move on
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::ContinuePlayersWithFade
+//=============================================================================
+// Description: Continue the players and then fade in.
+//
+// Parameters: see PausePlayers
+// pCallback - the asynchronous callback to call when done
+// pUserData - the user data to pass into the callback
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::ContinuePlayersWithFade
+(
+ IDaSoundFadeState* pCallback,
+ void* pUserData
+)
+{
+ // Create the fade info
+ daSoundAsyncFadeCallback* pFadeInfo =
+ new( GMA_TEMP ) daSoundAsyncFadeCallback( );
+ rAssert( pFadeInfo != NULL );
+ pFadeInfo->SetPlayerManager( this );
+ pFadeInfo->SetAction( OnFade_ContinuePlayers );
+ pFadeInfo->SetCallback( pCallback, pUserData );
+
+ // Continue the players
+ ContinuePlayers();
+
+ // Start fading the sounds
+ rAssert( m_pIngameFadeIn != NULL );
+ Sound::daSoundRenderingManagerGet( )->GetTuner( )->FadeSounds
+ (
+ this,
+ pFadeInfo,
+ m_pIngameFadeIn,
+ true
+ );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::CancelPlayers
+//=============================================================================
+// Description: Stop the sound players
+//
+// Parameters: stackFrame - the stack frame that a player is associated with.
+// If NULL, all players stop.
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::CancelPlayers
+(
+)
+{
+ //
+ // Stop all players
+ //
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ if( pPlayer->IsCaptured( ) )
+ {
+ // Stop the player
+ pPlayer->Stop( );
+ }
+
+ // Move on
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+
+ //
+ // Since this command may be called by the sound manager destructor,
+ // we must make sure that we service the sound system at least one
+ // more time so that we can actually stop all the sounds.
+ //
+ ::radSoundHalSystemGet( )->Service( );
+ ::radSoundHalSystemGet( )->ServiceOncePerFrame( );
+}
+
+//=============================================================================
+// daSoundPlayerManager::AreAllPlayersStopped
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: bool
+//
+//=============================================================================
+bool daSoundPlayerManager::AreAllPlayersStopped()
+{
+ unsigned int c;
+ daSoundClipStreamPlayer::State playerState;
+
+ for( c = 0; c < SOUND_NUM_CLIP_PLAYERS; c++ )
+ {
+ if( gClipPlayerArray[c] != NULL )
+ {
+ playerState = gClipPlayerArray[c]->GetState();
+
+ if( ( playerState == daSoundClipStreamPlayer::State_Cueing )
+ || ( playerState == daSoundClipStreamPlayer::State_CuedPlay )
+ || ( playerState == daSoundClipStreamPlayer::State_Playing ) )
+ {
+ if( !(gClipPlayerArray[c]->IsPaused()) )
+ {
+ return( false );
+ }
+ }
+ }
+ }
+
+ for( c = 0; c < SOUND_NUM_STREAM_PLAYERS; c ++ )
+ {
+ if( gStreamPlayerArray[c] != NULL )
+ {
+ playerState = gStreamPlayerArray[c]->GetState();
+
+ if( ( playerState == daSoundClipStreamPlayer::State_Cueing )
+ || ( playerState == daSoundClipStreamPlayer::State_CuedPlay )
+ || ( playerState == daSoundClipStreamPlayer::State_Playing )
+ || ( playerState == daSoundClipStreamPlayer::State_Stopping ) )
+ {
+ if( !(gStreamPlayerArray[c]->IsPaused()) )
+ {
+ return( false );
+ }
+ }
+ }
+ }
+
+ return( true );
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::PlayerVolumeChange
+//=============================================================================
+// Description: updates all of the players with the new volume value
+//
+//-----------------------------------------------------------------------------
+void daSoundPlayerManager::PlayerVolumeChange( daSoundGroup groupName, float trim )
+{
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ pPlayer->ChangeTrim(groupName,trim);
+
+ // Move on
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::PlayerFaderVolumeChange
+//=============================================================================
+// Description: updates all of the players with the new fader volume value
+//
+//-----------------------------------------------------------------------------
+void daSoundPlayerManager::PlayerFaderVolumeChange( daSoundGroup groupName, float trim )
+{
+ daSoundPlayerBase* pPlayer = daSoundPlayerBase::GetLinkedClassHead( );
+ while( pPlayer != NULL )
+ {
+ pPlayer->ChangeFaderTrim(groupName,trim);
+
+ // Move on
+ pPlayer = pPlayer->GetLinkedClassNext( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundPlayerManager::OnFadeDone
+//=============================================================================
+// Description: React when the fade is done
+//
+// Parameters: pUserData - a void* to a daSoundAsyncFadeCallback
+//
+//-----------------------------------------------------------------------------
+
+void daSoundPlayerManager::OnFadeDone( void* pUserData )
+{
+ daSoundAsyncFadeCallback* pFadeInfo =
+ reinterpret_cast< daSoundAsyncFadeCallback* >( pUserData );
+ rAssert( pFadeInfo != NULL );
+
+ // Perform the appropriate action
+ switch( pFadeInfo->GetAction( ) )
+ {
+ case OnFade_PausePlayers:
+ {
+ PausePlayers();
+ break;
+ }
+ case OnFade_ContinuePlayers:
+ {
+ break;
+ }
+ case OnFade_CancelPlayers:
+ {
+ CancelPlayers();
+ Sound::daSoundRenderingManagerGet( )->
+ GetTuner( )->
+ SetMasterVolume( 1.0f );
+ break;
+ }
+ default:
+ {
+ rAssert( 0 );
+ break;
+ }
+ }
+
+ // Call the callback
+ IDaSoundFadeState* pCallback = NULL;
+ void* pData = NULL;
+ pFadeInfo->GetCallback( &pCallback, &pData );
+
+ if( pCallback != NULL )
+ {
+ pCallback->OnFadeDone( pData );
+ }
+
+ // Delete the fade info
+ delete pFadeInfo;
+}
+
+void TrimFileName( char * pS, int len )
+{
+ int sl = strlen( pS );
+
+ char * pStart;
+ char * pEnd;
+
+ pEnd = pS + sl - 4;
+ pStart = pEnd - len;
+
+ if ( pStart < pS )
+ {
+ pStart = pS;
+ }
+
+ if ( pEnd < pStart )
+ {
+ pEnd = pS + 1;
+ }
+
+ int chars = pEnd - pStart;
+
+ ::memcpy( pS, pStart, chars);
+ pS[ chars ] = 0;
+}
+
+void RenderPlayer( daSoundClipStreamPlayer * pPlayer, int row, int col )
+{
+ char buf[ 256 ];
+
+ if ( false == pPlayer->IsCaptured( ) )
+ {
+ sprintf( buf, "free" );
+ }
+ else
+ {
+ float fDistToListener;
+ char sDistToListener[ 64 ];
+ char sFileName[ 64 ];
+ char sMaxDistance[ 64 ];
+
+ pPlayer->GetFileName( sFileName, 64 );
+
+ TrimFileName( sFileName, 8 );
+
+ IRadSoundHalPositionalGroup * pPosGroup = pPlayer->GetPositionalGroup( );
+
+ if ( pPosGroup )
+ {
+ radSoundVector listenerPos;
+ radSoundVector position;
+
+ float minDist;
+ float maxDist;
+
+ radSoundHalListenerGet( )->GetPosition( & listenerPos );
+
+ pPosGroup->GetPosition( & position );
+ pPosGroup->GetMinMaxDistance( & minDist, & maxDist );
+
+ fDistToListener = listenerPos.GetDistanceBetween( position );
+
+ sprintf( sDistToListener, "%.2f", fDistToListener );
+ sprintf( sMaxDistance, "%.2f", maxDist );
+ }
+ else
+ {
+ strcpy( sDistToListener, "--" );
+ strcpy( sMaxDistance, "--" );
+ }
+
+
+ // gClipPlayerArray[ c ]->
+ sprintf( buf, "[%s](%s)[%d][%s][%s]",
+ sFileName,
+ pPlayer->IsPaused( ) ? "-" : "*",
+ pPlayer->GetState( ),
+ sDistToListener,
+ sMaxDistance );
+ }
+
+ p3d::pddi->DrawString( buf, 40 + col * 320
+ , 36 + row * 16, pddiColour( 255, 255, 0 ) );
+
+}
+
+void daSoundPlayerManager::Render( void )
+{
+ if( m_Initialized )
+ {
+ int col = 0;
+ int row = 0;
+
+ unsigned int freeMem;
+ unsigned int numObjects;
+ unsigned int largestBlock;
+ unsigned int size;
+
+ radSoundHalSystemGet( )->GetRootMemoryRegion( )->GetStats(
+ & freeMem,
+ & numObjects,
+ & largestBlock,
+ true );
+
+ size = radSoundHalSystemGet( )->GetRootMemoryRegion( )->GetSize( );
+
+ char memStr[ 256 ];
+ sprintf(
+ memStr,
+ "Usd %dK Fre %dK Lrg %dK Objs: %d",
+ ( size - freeMem ) / 1024,
+ freeMem / 1024,
+ largestBlock / 1024,
+ numObjects );
+
+ p3d::pddi->DrawString( memStr, 40 + col * 320, 36 + row * 16, pddiColour( 255, 255, 0 ) );
+
+ row++;
+
+ unsigned int usedBTreeNodes = radObjectBTree::GetNumAllocatedNodes( );
+ unsigned int nodeSize = sizeof( radObjectBTreeNode );
+
+ sprintf( memStr,
+ "BTree Nodes: [0x%x], size: [0x%x]",
+ usedBTreeNodes,
+ nodeSize );
+
+ p3d::pddi->DrawString( memStr, 40 + col * 320, 36 + row * 16, pddiColour( 255, 255, 0 ) );
+
+ row++;
+
+ char listenerStr[ 128 ];
+ radSoundVector lp;
+ radSoundVector lv;
+ radSoundHalListenerGet( )->GetPosition( & lp );
+ radSoundHalListenerGet( )->GetVelocity( & lv );
+
+ sprintf( listenerStr, "Pos:[%.2f][%.2f][%.2f] Vel:[%.2f][%.2f][%.2f]\n",
+ lp.m_x, lp.m_y, lp.m_z, lv.m_x, lv.m_y, lv.m_z );
+
+ p3d::pddi->DrawString( listenerStr, 40 + col * 320, 36 + row * 16, pddiColour( 255, 255, 0 ) );
+
+ row++;
+
+ for( unsigned int c = 0; c < SOUND_NUM_CLIP_PLAYERS / 2; c ++ )
+ {
+ RenderPlayer( gClipPlayerArray[ c ], row, col );
+
+ col++;
+
+ if ( col >= 2 )
+ {
+ row++;
+ col = 0;
+ }
+ }
+
+ row++;
+
+ for( unsigned int c = 0; c < SOUND_NUM_STREAM_PLAYERS; c ++ )
+ {
+ RenderPlayer( gStreamPlayerArray[ c ], row, col );
+
+ col++;
+
+ if ( col >= 2 )
+ {
+ row++;
+ col = 0;
+ }
+ }
+ }
+}
+
+} // Sound Namespace
+
diff --git a/game/code/sound/soundrenderer/playermanager.h b/game/code/sound/soundrenderer/playermanager.h
new file mode 100644
index 0000000..09fa4eb
--- /dev/null
+++ b/game/code/sound/soundrenderer/playermanager.h
@@ -0,0 +1,185 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: playermanager.h
+//
+// Subsystem: Dark Angel - Player Manager System
+//
+// Description: Description of the DA sound player manager
+//
+// Revisions:
+// + Created October 16, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _PLAYERMANAGER_HPP
+#define _PLAYERMANAGER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/musicsoundplayer.h>
+#include <radsound.hpp>
+
+//=============================================================================
+// Global namespace forward declarations
+//=============================================================================
+
+struct IRadObjectList;
+
+class Fader;
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundPlayerGroupWiring;
+class daSoundPlayerManager;
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+class daSoundClipStreamPlayer;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+//
+// This class is created for our asynchronous fades
+//
+
+class daSoundAsyncFadeCallback : public radObject
+{
+public:
+ IMPLEMENT_BASEOBJECT( "daSoundAsyncFadeCallback" )
+
+ daSoundAsyncFadeCallback( );
+ virtual ~daSoundAsyncFadeCallback( );
+
+ void SetAction( int action ) { m_Action = action; }
+ int GetAction( void ) { return m_Action; }
+
+ void SetPlayerManager( daSoundPlayerManager* pPlayerManager );
+ daSoundPlayerManager* GetPlayerManager( void );
+
+ void SetCallback( IDaSoundFadeState* pCallback, void* pUserData );
+ void GetCallback( IDaSoundFadeState** ppCallback, void** ppUserData );
+
+private:
+
+ int m_Action;
+ daSoundPlayerManager* m_pPlayerManager;
+ IDaSoundFadeState* m_pCallback;
+ void* m_pUserData;
+};
+
+//
+// The player manager is responsible for creating and managing daSoundClipStreamPlayer
+// objects. These objects allow the user to play sound resources.
+//
+class daSoundPlayerManager : public IDaSoundFadeState,
+ public radRefCount
+{
+public:
+ IMPLEMENT_REFCOUNTED_NOSIZE( "daSoundPlayerManager" );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundPlayerManager( );
+ virtual ~daSoundPlayerManager( );
+
+ inline daSoundPlayerManager * GetInstance( void );
+
+ bool FindFreeClipPlayer(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource );
+ bool FindFreeStreamPlayer(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource );
+
+ unsigned int GetNumUsedClipPlayers();
+ unsigned int GetNumUsedStreamPlayers();
+ void Initialize( void );
+ void UglyHackPostInitialize( IDaSoundTuner* pTuner );
+ void ServiceOncePerFrame( void );
+ unsigned int GetObjectSize( void );
+ void CaptureFreePlayer(
+ daSoundClipStreamPlayer** ppPlayer,
+ IDaSoundResource* pResource,
+ bool positional );
+
+ void PausePlayers ( );
+ void PausePlayersWithFade(
+ IDaSoundFadeState* pCallback,
+ void* pUserData );
+
+ void ContinuePlayers ( );
+
+ void ContinuePlayersWithFade(
+ IDaSoundFadeState* pCallback,
+ void* pUserData );
+
+ void CancelPlayers ( );
+
+ bool AreAllPlayersStopped();
+
+ //
+ // Volume controls
+ //
+ void PlayerVolumeChange( daSoundGroup soundGroup, daTrimValue trim );
+ void PlayerFaderVolumeChange( daSoundGroup soundGroup, daTrimValue trim );
+
+ void Render( void );
+
+protected:
+ // When a fade is done go here and call our callback
+ enum FadeTypesEnum {
+ OnFade_PausePlayers,
+ OnFade_ContinuePlayers,
+ OnFade_CancelPlayers
+ };
+ void OnFadeDone( void* pUserData );
+
+private:
+
+ bool FindFreePlayer( daSoundClipStreamPlayer** ppPlayerArray, unsigned int numPlayers, daSoundClipStreamPlayer ** ppPlayer );
+
+ MusicSoundPlayer* m_pMusicPlayer;
+ MusicSoundPlayer* m_pAmbiencePlayer;
+
+ //
+ // The ingame faders
+ //
+ Fader* m_pIngameFadeIn;
+ Fader* m_pIngameFadeOut;
+
+ bool m_Initialized;
+
+ static daSoundPlayerManager * s_pInstance;
+
+};
+
+inline daSoundPlayerManager * daSoundPlayerManager::GetInstance( void )
+{
+ return s_pInstance;
+}
+
+} // Sound Namespace
+#endif //_PLAYERMANAGER_HPP
+
+
diff --git a/game/code/sound/soundrenderer/soundallocatedresource.cpp b/game/code/sound/soundrenderer/soundallocatedresource.cpp
new file mode 100644
index 0000000..e6678ca
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundallocatedresource.cpp
@@ -0,0 +1,429 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundallocatedresource.cpp
+//
+// Subsystem: Dark Angel - Sound Resource Management System
+//
+// Description: Implementation of an allocated sound resource
+//
+// Revisions:
+// + Created October 18, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radsound.hpp>
+#include <raddebugwatch.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/soundallocatedresource.h>
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/soundnucleus.hpp>
+
+#include <memory/srrmemory.h>
+
+//=============================================================================
+// Static Variables (outside namespace)
+//=============================================================================
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Static Variables (inside namespace)
+//=============================================================================
+
+//=============================================================================
+// Constants
+//=============================================================================
+
+#ifndef RAD_RELEASE
+
+#ifdef RAD_DEBUG
+static bool s_displayMemoryInfo = true;
+#else
+static bool s_displayMemoryInfo = false;
+#endif
+
+static bool s_isInitialized = false;
+static int s_memoryRemaining = 0;
+
+#endif // RAD_RELEASE
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundAllocatedResource Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundFileInstance::daSoundFileInstance
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance::daSoundFileInstance(
+ IDaSoundResource* pResource,
+ unsigned int fileIndex )
+{
+ rAssert( pResource != NULL );
+
+ m_RefCount = 0;
+ m_State = UnLoaded;
+ m_pSoundClip = NULL;
+
+ m_State = UnLoaded;
+
+ m_FileIndex = fileIndex;
+
+ m_pResource = pResource;
+ m_pResource->AddRef( );
+
+ // Set the type of resource
+
+ IDaSoundResource::Type type = pResource->GetType( );
+
+ if( type == IDaSoundResource::CLIP )
+ {
+ m_Type = IDaSoundResource::CLIP;
+ }
+ else
+ {
+ rAssert( type == IDaSoundResource::STREAM );
+ m_Type = IDaSoundResource::STREAM;
+ }
+
+#ifndef RAD_RELEASE
+ if( !s_isInitialized )
+ {
+ radDbgWatchAddBoolean( &s_displayMemoryInfo, "Show Loading Spew", "Sound Info", 0, 0 );
+
+ s_isInitialized = true;
+ }
+#endif
+}
+
+//=============================================================================
+// Function: daSoundFileInstance::~daSoundFileInstance
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance::~daSoundFileInstance( )
+{
+ m_pResource->Release( );
+
+ rAssert( m_State == UnLoaded );
+ rAssert( NULL == m_pSoundClip );
+
+}
+
+//=============================================================================
+// Function: daSoundFileInstance::CreateFileDataSource
+//=============================================================================
+// Description: Get the sound stream.
+//
+// Returns: Returns the sound stream if it is allocated for this resource,
+// or NULL if it is not.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundFileInstance::CreateFileDataSource(
+ IRadSoundRsdFileDataSource** ppFds )
+{
+ rAssert( GetType( ) == IDaSoundResource::STREAM );
+ rAssert( Loaded == m_State );
+
+ char fileName[ 256 ];
+ m_pResource->GetFileKeyAt( m_FileIndex, fileName, 256 );
+
+ *ppFds = radSoundRsdFileDataSourceCreate( GMA_AUDIO_PERSISTENT );
+ (*ppFds)->AddRef( );
+
+ (*ppFds)->InitializeFromFileName(
+ fileName,
+ true,
+ 0,
+ IRadSoundHalAudioFormat::Milliseconds,
+ SoundNucleusGetStreamFileAudioFormat( ) );
+
+}
+
+//=============================================================================
+// Function: daSoundFileInstance::OnDynaLoadObjectCreate
+//=============================================================================
+// Description: Called when this object is being created (by dynamic loading)
+//
+//-----------------------------------------------------------------------------
+
+void daSoundFileInstance::Load( IRadSoundHalMemoryRegion* pRegion )
+{
+ rAssert( m_State == UnLoaded );
+
+ rAssert( m_Type == IDaSoundResource::UNKNOWN || m_pResource != NULL );
+
+ // Create each type of object
+ if( m_Type == IDaSoundResource::CLIP )
+ {
+ char fileName[ 256 ];
+ m_pResource->GetFileKeyAt( m_FileIndex, fileName, 256 );
+
+ SoundNucleusLoadClip( fileName, m_pResource->GetLooping( ) );
+ }
+
+ m_State = Loading;
+}
+
+//=============================================================================
+// Function: daSoundFileInstance::OnDynaLoadObjectCreate
+//=============================================================================
+// Description: Is this object ready and stable?
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundFileInstance::UpdateLoading( void )
+{
+ rAssert( Loading == m_State );
+
+ if( m_Type == IDaSoundResource::CLIP )
+ {
+ if ( SoundNucleusIsClipLoaded( ) )
+ {
+ SoundNucleusFinishClipLoad( & m_pSoundClip );
+ m_State = Loaded;
+ }
+ }
+ else
+ {
+ m_State = Loaded;
+ }
+
+ return Loaded == m_State;
+}
+
+//=============================================================================
+// Function: daSoundFileInstance::OnDynaLoadObjectDestroy
+//=============================================================================
+// Description: Destroy this dynamically loading object
+//
+//-----------------------------------------------------------------------------
+
+void daSoundFileInstance::UnLoad( void )
+{
+ rAssert( m_State == Loaded || Loading == m_State );
+
+ if ( m_Type == IDaSoundResource::CLIP )
+ {
+ if ( Loading == m_State )
+ {
+ SoundNucleusCancelClipLoad( );
+ }
+ else if ( Loaded == m_State )
+ {
+ rAssert( m_pSoundClip != NULL );
+ m_pSoundClip->Release( );
+ m_pSoundClip = NULL;
+ }
+ }
+
+ m_State = UnLoaded;
+}
+
+//=============================================================================
+// daSoundAllocatedResource Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundAllocatedResource::daSoundAllocatedResource
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundAllocatedResource::daSoundAllocatedResource( )
+ :
+ m_RefCount( 0 )
+{
+ unsigned int i = 0;
+
+ for( i = 0; i < DASound_MaxNumSoundResourceFiles; i++ )
+ {
+ m_pFileInstance[ i ] = NULL;
+ m_pDynaLoadRegion[ i ] = NULL;
+ }
+}
+
+//=============================================================================
+// Function: daSoundAllocatedResource::~daSoundAllocatedResource
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundAllocatedResource::~daSoundAllocatedResource( void )
+{
+ if( GetResource( ) != NULL )
+ {
+ unsigned int i = 0;
+ unsigned int j = 0;
+ for( i = 0; i < DASound_MaxNumSoundResourceFiles; i++ )
+ {
+ // Release the dynamic loading region
+ if( m_pDynaLoadRegion[ i ] != NULL )
+ {
+ for( j = 0; j < m_pDynaLoadRegion[ i ]->GetNumSlots( ); j++ )
+ {
+ m_pDynaLoadRegion[ i ]->SwapInObject( j, NULL );
+ }
+ m_pDynaLoadRegion[ i ]->Release( );
+ m_pDynaLoadRegion[ i ] = NULL;
+ }
+
+ // Release file instance
+ if( m_pFileInstance[ i ] != NULL )
+ {
+ m_pFileInstance[ i ]->Release( );
+ m_pFileInstance[ i ] = NULL;
+ }
+ }
+
+ // Release the resource
+ m_pResource->Release( );
+ }
+
+}
+
+//=============================================================================
+// Function: daSoundAllocatedResource::Initialize
+//=============================================================================
+// Description: Intialize the allocated resource by giving it a normal
+// resource.
+//
+// Parameters: pResource - the resource for this instance to associate with
+// index - the index of the resource file to use
+//
+//-----------------------------------------------------------------------------
+
+void daSoundAllocatedResource::Initialize
+(
+ IDaSoundResource* pResource
+)
+{
+ rAssert( pResource != NULL );
+
+ m_pResource = pResource;
+ m_pResource->AddRef( );
+
+ // Look in the resource manager's tree of allocated resources
+ // If the file is already loaded, just addref the object
+ Sound::daSoundResourceManager* pResManager = Sound::daSoundResourceManager::GetInstance( );
+
+ // Load and initialize the files;
+
+ unsigned int numFiles = m_pResource->GetNumFiles( );
+
+ for( unsigned int i = 0; i < numFiles; i++ )
+ {
+
+#ifdef RAD_XBOX
+ daSoundFileInstance* pFileInstance = new( GMA_XBOX_SOUND_MEMORY ) daSoundFileInstance( m_pResource, i );
+#else
+ daSoundFileInstance* pFileInstance = new( GMA_AUDIO_PERSISTENT ) daSoundFileInstance( m_pResource, i );
+#endif
+ pFileInstance->AddRef( );
+
+ //
+ // Generate a dyna load region for this object
+ //
+
+ unsigned int size = 0;
+ daSoundDynaLoadRegion* pRegion = NULL;
+ m_pDynaLoadRegion[ i ] = Sound::daSoundRenderingManagerGet( )->
+ GetDynaLoadManager( )->
+ CreateRegion
+ (
+ ::radSoundHalSystemGet( )->GetRootMemoryRegion( ),
+ size,
+ 1
+ );
+ rAssert( m_pDynaLoadRegion[ i ] != NULL );
+ m_pDynaLoadRegion[ i ]->AddRef( );
+ m_pDynaLoadRegion[ i ]->SwapInObject( 0, pFileInstance );
+
+ // Set the file instance internally
+ // (The AddRef is just copied)
+
+ m_pFileInstance[ i ] = pFileInstance;
+ }
+}
+
+//=============================================================================
+// Function: daSoundAllocatedResource::ChooseNextInstance
+//=============================================================================
+// Description: Choose the next instance to play in this allocated resource
+//
+// Notes:
+// The resource automatically keeps track of what files
+// are being used. It will try not to let anything repeat
+// based on the following rules:
+// (1) IF ( numfiles <= DASound_NumLastPlayedFilesToRemember ) THEN
+// Choose a file randomly
+// (2) IF ( numfiles == DASound_NumLastPlayedFilesToRemember + 1 ) THEN
+// Choose randomly out of all files except the last one
+// used.
+// (2) ELSE
+// Don't choose one of the DASound_NumLastPlayedFilesToRemember
+// last files, but choose randomly out of the rest
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundAllocatedResource::ChooseNextInstance( void )
+{
+ rAssert( GetResource( ) != NULL );
+
+ // Get the number of resource files
+ unsigned int numResourceFiles = GetResource( )->GetNumFiles( );
+ rAssert( numResourceFiles > 0 );
+
+ // Return the chosen file
+ return( rand( ) % numResourceFiles );
+}
+
+//=============================================================================
+// Function: daSoundAllocatedResource::GetFileInstance
+//=============================================================================
+// Description: Get the file instance at the given index
+//
+// Returns: Returns a pointer to the file instance
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance* daSoundAllocatedResource::GetFileInstance
+(
+ unsigned int index
+)
+{
+ rAssert( GetResource( ) != NULL );
+ rAssert( index < GetResource( )->GetNumFiles( ) );
+
+ return m_pFileInstance[ index ];
+}
+
+} // Sound Namespace
+
diff --git a/game/code/sound/soundrenderer/soundallocatedresource.h b/game/code/sound/soundrenderer/soundallocatedresource.h
new file mode 100644
index 0000000..599e4ca
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundallocatedresource.h
@@ -0,0 +1,249 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundallocatedresource.hpp
+//
+// Subsystem: Dark Angel - Sound Resource Management System
+//
+// Description: Description of an allocated sound resource
+//
+// Revisions:
+// + Created October 19, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _SOUNDALLOCATEDRESOURCE_HPP
+#define _SOUNDALLOCATEDRESOURCE_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radlinkedclass.hpp>
+#include <radsound_hal.hpp>
+#include <radsound.hpp>
+
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/sounddynaload.h>
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundAllocatedResource;
+
+class daSoundFileInstance
+{
+public:
+
+ inline void * operator new ( size_t size, radMemoryAllocator allocator );
+ inline void operator delete( void * pMem );
+
+ inline void AddRef( void );
+ inline void Release( void );
+
+ // Constructor and destructor
+ daSoundFileInstance( IDaSoundResource* pResource, unsigned int fileIndex );
+ ~daSoundFileInstance( );
+
+ void Load( IRadSoundHalMemoryRegion* pRegion );
+ bool UpdateLoading( void );
+ void UnLoad( void );
+
+ inline IDaSoundResource::Type GetType( void );
+
+ inline IRadSoundClip* GetSoundClip( void );
+ void CreateFileDataSource( IRadSoundRsdFileDataSource** );
+
+ // Internal state
+ enum State { Loading, Loaded, UnLoaded };
+
+ inline State GetState( void );
+
+ inline void GetFileName( char * pFileName, unsigned int maxChars );
+
+protected:
+
+private:
+
+ unsigned int m_FileIndex;
+ unsigned int m_RefCount;
+
+ // Store the resource
+ IDaSoundResource * m_pResource;
+
+ // Store the actual allocated resource based on the attached
+ IDaSoundResource::Type m_Type;
+
+ IRadSoundClip* m_pSoundClip;
+
+ State m_State;
+};
+
+//
+// The resource library stores a giant array of resources, and provides helpfull
+// ways to get at the information. Notices that there is no
+// way to remove a resource file from this library.
+//
+class daSoundAllocatedResource : public IRefCount
+{
+
+public:
+
+ inline void AddRef( void );
+ inline void Release( void );
+
+ inline void * operator new ( size_t size, radMemoryAllocator allocator );
+ inline void operator delete( void * pMem );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundAllocatedResource( );
+ ~daSoundAllocatedResource( );
+
+ //
+ // IDaSoundAllocatedResource
+ //
+ void Initialize( IDaSoundResource* pResource );
+ inline IDaSoundResource* GetResource( void );
+ unsigned int ChooseNextInstance( void );
+
+ daSoundFileInstance* GetFileInstance( unsigned int index );
+
+protected:
+ void ApplyResourceSettings_Internal( unsigned int index );
+
+private:
+ // Store the attached resource
+ IDaSoundResource* m_pResource;
+
+ unsigned int m_RefCount;
+
+ // Store the file instances
+ daSoundFileInstance* m_pFileInstance[ DASound_MaxNumSoundResourceFiles ];
+
+ // Dynamic loading region
+ daSoundDynaLoadRegion* m_pDynaLoadRegion[ DASound_MaxNumSoundResourceFiles ];
+};
+
+//=============================================================================
+// Function: daSoundFileInstance::GetType
+//=============================================================================
+// Description: Get the type of the allocated res
+//
+//-----------------------------------------------------------------------------
+
+inline IDaSoundResource::Type daSoundFileInstance::GetType( void )
+{
+ return m_Type;
+}
+
+
+//=============================================================================
+// Function: daSoundFileInstance::GetSoundClip
+//=============================================================================
+// Description: Get the sound clip.
+//
+// Returns: Returns the sound clip if it is allocated for this resource,
+// or NULL if it is not.
+//
+//-----------------------------------------------------------------------------
+
+inline IRadSoundClip* daSoundFileInstance::GetSoundClip( void )
+{
+ rAssert( IDaSoundResource::CLIP == GetType( ) );
+ rAssert( Loaded == m_State );
+
+ return m_pSoundClip;
+}
+
+
+//=============================================================================
+// Function: daSoundAllocatedResource::GetResource
+//=============================================================================
+// Description: Get the resource data from the allocated resource
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundResource* daSoundAllocatedResource::GetResource( void )
+{
+ return m_pResource;
+}
+
+inline daSoundFileInstance::State daSoundFileInstance::GetState( void )
+{
+ return m_State;
+}
+
+inline void daSoundFileInstance::GetFileName( char * pBuffer, unsigned int max )
+{
+ m_pResource->GetFileKeyAt( m_FileIndex, pBuffer, max );
+}
+
+
+inline void daSoundFileInstance::AddRef( void )
+{
+ m_RefCount++;
+}
+
+inline void daSoundFileInstance::Release( void )
+{
+ rAssert( m_RefCount > 0 );
+
+ m_RefCount--;
+
+ if( 0 == m_RefCount )
+ {
+ delete this;
+ }
+}
+
+
+inline void * daSoundFileInstance::operator new ( size_t size, radMemoryAllocator allocator )
+{
+ return radMemoryAlloc( allocator, size );
+}
+
+inline void daSoundFileInstance::operator delete( void * pMem )
+{
+ return radMemoryFree( pMem );
+}
+
+inline void daSoundAllocatedResource::AddRef( void )
+{
+ m_RefCount++;
+}
+
+inline void daSoundAllocatedResource::Release( void )
+{
+ rAssert( m_RefCount > 0 );
+
+ m_RefCount--;
+
+ if( 0 == m_RefCount )
+ {
+ delete this;
+ }
+}
+
+inline void * daSoundAllocatedResource::operator new ( size_t size, radMemoryAllocator allocator )
+{
+ return radMemoryAlloc( allocator, size );
+}
+
+inline void daSoundAllocatedResource::operator delete( void * pMem )
+{
+ return radMemoryFree( pMem );
+}
+
+} // Sound Namespace
+#endif //_SOUNDALLOCATEDRESOURCE_HPP
+
diff --git a/game/code/sound/soundrenderer/soundconstants.h b/game/code/sound/soundrenderer/soundconstants.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundconstants.h
diff --git a/game/code/sound/soundrenderer/sounddynaload.cpp b/game/code/sound/soundrenderer/sounddynaload.cpp
new file mode 100644
index 0000000..8a5f7b4
--- /dev/null
+++ b/game/code/sound/soundrenderer/sounddynaload.cpp
@@ -0,0 +1,954 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: sounddynaload.cpp
+//
+// Subsystem: Dark Angel - Dynamic Loading System
+//
+// Description: Implementation of the DA Dynamic Sound Loading System
+//
+// Revisions:
+// + Created: Novemeber 22, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radkey.hpp>
+#include <radsound.hpp>
+
+#include <sound/soundrenderer/sounddynaload.h>
+#include <sound/soundrenderer/soundallocatedresource.h>
+
+//=============================================================================
+// Static Variables (outside namespace)
+//=============================================================================
+
+Sound::daSoundDynaLoadRegion* radLinkedClass< Sound::daSoundDynaLoadRegion >::s_pLinkedClassHead = NULL;
+Sound::daSoundDynaLoadRegion* radLinkedClass< Sound::daSoundDynaLoadRegion >::s_pLinkedClassTail = NULL;
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Debug Information
+//=============================================================================
+
+//
+// Use this if you want to debug the sound player
+//
+#ifndef FINAL
+#ifndef NDEBUG
+#define DASOUNDDYNALOAD_DEBUG
+#ifdef DASOUNDDYNALOAD_DEBUG
+
+// Show the creation and destruction of dynamic loading regions
+static bool sg_ShowDynaLoadRegionCreation = false;
+
+#endif //DASOUNDDYNALOAD_DEBUG
+#endif //NDEBUG
+#endif //FINAL
+
+//=============================================================================
+// Static Variables
+//=============================================================================
+
+daSoundDynaLoadManager* daSoundDynaLoadManager::s_pSingleton = NULL;
+daSoundDynaLoadRegion* daSoundDynaLoadRegion::s_pActiveRegion = NULL;
+unsigned int daSoundDynaLoadRegion::s_ActiveSlot = 0;
+unsigned int daSoundDynaLoadRegion::s_GlobalPendingSwapCount = 0;
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundFileInstance;
+class daSoundDynaLoadRegion;
+
+//=============================================================================
+// Class Implementation
+//=============================================================================
+
+//=============================================================================
+// daSoundDynaLoadRegion Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::daSoundDynaLoadRegion
+//=============================================================================
+// Description: Constructor.
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadRegion::daSoundDynaLoadRegion( )
+:
+radRefCount( 0 ),
+m_IsInitialized( false ),
+m_NumSlots( 0 ),
+m_SlotSize( 0 ),
+m_ppSlot( NULL ),
+m_ppSlotObjects( NULL ),
+m_ppPendingSwapObjects( NULL ),
+m_PendingSwapCount( 0 )
+{
+ //
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::~daSoundDynaLoadRegion
+//=============================================================================
+// Description: Destructor.
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadRegion::~daSoundDynaLoadRegion( )
+{
+ // Destroy everything
+ Destroy( );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::~daSoundDynaLoadRegion
+//=============================================================================
+// Description: Create the region. If the size of slots is zero, do
+// not preallocate the region memory.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::Create
+(
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots,
+ unsigned int numslots
+)
+{
+ rAssert( pMemRegion != NULL );
+ rAssert( !m_IsInitialized );
+ rAssert( !ArePendingSwapsRegistered( ) );
+
+ // Set the region information
+ m_SlotSize = sizeofslots;
+ m_NumSlots = numslots;
+
+ // Create the slots
+ m_ppSlot = reinterpret_cast< IRadSoundHalMemoryRegion** >
+ (
+ ::radMemoryAlloc
+ (
+ GetThisAllocator( ),
+ sizeof( IRadSoundHalMemoryRegion* ) * numslots
+ )
+ );
+ rAssert( m_ppSlot );
+
+ unsigned int i = 0;
+ for( i = 0; i < numslots; i++ )
+ {
+ // If the slot size is zero, just use the main memory
+ if( SharedMemoryRegions( ) )
+ {
+ m_ppSlot[ i ] = pMemRegion;
+ m_ppSlot[ i ]->AddRef( );
+ }
+ else
+ {
+ //
+ // ESAN TODO: Investigate the magic number 32 below...
+ //
+ m_ppSlot[ i ] = pMemRegion->CreateChildRegion( m_SlotSize, 32, "Sound Memory Region object" );
+ if( m_ppSlot[ i ] == NULL )
+ {
+ // If this occurs, there in the check for free space. This may
+ // occur if the slot size is not aligned in the same way as
+ // sound memory.
+ rDebugString( "Out of sound memory allocating region\n" );
+ rAssert( m_ppSlot[ i ] != NULL );
+ }
+ else
+ {
+ m_ppSlot[ i ]->AddRef( );
+ }
+ }
+ rAssert( m_ppSlot[ i ] != NULL );
+ rAssert( m_ppSlot[ i ]->GetSize( ) >= m_SlotSize );
+ }
+
+ // Create the slot objects and pending slot objects
+ m_ppSlotObjects = reinterpret_cast< daSoundFileInstance** >
+ (
+ ::radMemoryAlloc
+ (
+ GetThisAllocator( ),
+ sizeof( daSoundFileInstance* ) * numslots
+ )
+ );
+ m_ppPendingSwapObjects = reinterpret_cast< daSoundFileInstance** >
+ (
+ ::radMemoryAlloc
+ (
+ GetThisAllocator( ),
+ sizeof( daSoundFileInstance* ) * numslots
+ )
+ );
+ for( i = 0; i < numslots; i++ )
+ {
+ m_ppSlotObjects[ i ] = NULL;
+ m_ppPendingSwapObjects[ i ] = NULL;
+ }
+
+ m_IsInitialized = true;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::Destroy
+//=============================================================================
+// Description: Destroy the region.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::Destroy( void )
+{
+ if( m_IsInitialized )
+ {
+ //
+ // Swap out all the objects
+ //
+ unsigned int i = 0;
+ for( i = 0; i < m_NumSlots; i++ )
+ {
+ SwapInObject( i, NULL );
+ }
+
+ // Destroy the pending swap objects
+ if( m_ppPendingSwapObjects != NULL )
+ {
+ ::radMemoryFree( GetThisAllocator( ), m_ppPendingSwapObjects );
+ m_ppPendingSwapObjects = NULL;
+ }
+
+ // Destroy the memory objects
+ if( m_ppSlotObjects != NULL )
+ {
+ ::radMemoryFree( GetThisAllocator( ), m_ppSlotObjects );
+ m_ppSlotObjects = NULL;
+ }
+
+ // Destroy the memory regions
+ if( m_ppSlot != NULL )
+ {
+ for( i = 0; i < m_NumSlots; i++ )
+ {
+ rAssert( m_ppSlot[ i ] != NULL );
+ m_ppSlot[ i ]->Release( );
+ m_ppSlot[ i ] = NULL;
+ }
+ ::radMemoryFree( GetThisAllocator( ), m_ppSlot );
+ m_ppSlot = NULL;
+ }
+
+ // Make sure we are not the active swap
+ ClearActiveSwap( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::ServiceOncePerFrame
+//=============================================================================
+// Description: Service the sound system once per frame.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::ServiceOncePerFrame( void )
+{
+ // Service any active swaps
+ if( s_pActiveRegion == this )
+ {
+ if( GetSlotState( s_ActiveSlot ) != Initializing )
+ {
+ ClearActiveSwap( );
+ }
+ }
+ else
+ {
+ // Make sure that any pending swaps take place
+ if( ArePendingSwapsRegistered( ) )
+ {
+ unsigned int i = 0;
+ for( i = 0; i < GetNumSlots( ); i++ )
+ {
+ daSoundFileInstance* pObject = GetPendingSwapObject( i );
+ if( pObject != NULL )
+ {
+ daSoundDynaLoadRegion::SlotState state = GetSlotState( i );
+ if( state == Empty )
+ {
+ PerformSwap( i );
+ }
+ }
+ }
+ }
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SwapInObject
+//=============================================================================
+// Description: Swap in a sound object.
+//
+// Parameters: slot - the slot number to swap a sound into
+// pObject - a dynamic loading object
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::SwapInObject
+(
+ unsigned int slot,
+ daSoundFileInstance* pObject
+)
+{
+ // Destroy any pending swap object
+ daSoundFileInstance* pOldObject = GetPendingSwapObject( slot );
+ if( pOldObject != NULL )
+ {
+ SetPendingSwapObject( slot, NULL );
+ ClearActiveSwap( );
+ }
+
+ // Destroy the old object
+ pOldObject = GetSlotObject( slot );
+ if( pOldObject != NULL )
+ {
+ pOldObject->UnLoad( );
+ SetSlotObject( slot, NULL );
+ }
+
+ // Set the pending swap object
+ SetPendingSwapObject( slot, pObject );
+
+ // The swap will occur asynchronously in ServiceOncePerFrame( )
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetSlotState
+//=============================================================================
+// Description: Get the state of a slot
+//
+// Parameters: slot - the slot number to check
+//
+// Return: Returns the state of a slot
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadRegion::SlotState daSoundDynaLoadRegion::GetSlotState
+(
+ unsigned int slot
+)
+{
+ rAssert( m_IsInitialized );
+ rAssert( m_ppSlot != NULL );
+ rAssert( slot < m_NumSlots );
+ rAssert( GetSlotMemoryRegion( slot ) != NULL );
+
+ bool slotHasObject = true;
+ bool slotHasAllocation = true;
+
+ unsigned int numobjs = 0;
+ GetSlotMemoryRegion( slot )->GetStats( NULL, &numobjs, NULL, false );
+ slotHasAllocation = ( ( numobjs != 0 ) && ( !SharedMemoryRegions( ) ) );
+
+ daSoundFileInstance* pObject = GetSlotObject( slot );
+ // If we do not have our own memory regions, we assume that the object has already disapeared.
+ slotHasObject = ( pObject != NULL );
+
+ // Determine the state
+ daSoundDynaLoadRegion::SlotState state = Empty;
+ if( slotHasObject )
+ {
+ rAssert( pObject != NULL );
+
+ if( pObject->UpdateLoading( ) )
+ {
+ state = Ready;
+ }
+ else
+ {
+ state = Initializing;
+ }
+ }
+ else
+ {
+ if( slotHasAllocation )
+ {
+ state = Destroying;
+ }
+ else
+ {
+ state = Empty;
+ }
+ }
+
+ return state;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetNumSlots
+//=============================================================================
+// Description: Get the number of slots in this region
+//
+// Return: Returns the number of slots
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundDynaLoadRegion::GetNumSlots( void )
+{
+ rAssert( m_IsInitialized );
+ return m_NumSlots;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetSlotSize
+//=============================================================================
+// Description: Get the size of the slots in this dynaload region
+//
+// Return: Returns the size of the slots
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundDynaLoadRegion::GetSlotSize( void )
+{
+ rAssert( m_IsInitialized );
+ return m_SlotSize;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SharedMemoryRegions
+//=============================================================================
+// Description: Are the memory regions shared, or does each slot have its own?
+//
+// Return: Returns true if the memory regions are shared.
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundDynaLoadRegion::SharedMemoryRegions( void )
+{
+ return( m_SlotSize == 0 );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::PerformSwap
+//=============================================================================
+// Description: Do an actual swap into a memory slot. The slot
+// should be already verified as empty.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::PerformSwap
+(
+ unsigned int slot
+)
+{
+ bool result = SetActiveSwap( slot );
+ if( result )
+ {
+ rAssert( GetSlotState( slot ) == Empty );
+
+ // Swap in the object
+ daSoundFileInstance* pObject = GetPendingSwapObject( slot );
+ rAssert( pObject != NULL );
+ pObject->AddRef( );
+ SetSlotObject( slot, pObject );
+ SetPendingSwapObject( slot, NULL );
+
+ // Tell it to create itself
+ IRadSoundHalMemoryRegion* pRegion = GetSlotMemoryRegion( slot );
+ rAssert( pRegion != NULL );
+ pObject->Load( pRegion );
+
+ pObject->Release( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetSlotMemoryRegion
+//=============================================================================
+// Description: Get the slot memory region
+//
+// Return: Returns the size of the slots
+//
+//-----------------------------------------------------------------------------
+
+IRadSoundHalMemoryRegion* daSoundDynaLoadRegion::GetSlotMemoryRegion
+(
+ unsigned int slot
+)
+{
+ rAssert( m_IsInitialized );
+ rAssert( m_ppSlot != NULL );
+ rAssert( slot < m_NumSlots );
+
+ return( m_ppSlot[ slot ] );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SetSlotObject
+//=============================================================================
+// Description: Set a slot's object
+//
+// Parameters: slot - the slot whose object is to be set
+// pObject - the object to place in the slot
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::SetSlotObject
+(
+ unsigned int slot,
+ daSoundFileInstance* pObject
+)
+{
+ SetObject_Internal( m_ppSlotObjects, slot, pObject );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetSlotObject
+//=============================================================================
+// Description: Get a slot's object
+//
+// Return: Returns the sound object
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance* daSoundDynaLoadRegion::GetSlotObject
+(
+ unsigned int slot
+)
+{
+ return GetObject_Internal( m_ppSlotObjects, slot );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SetPendingSwapObject
+//=============================================================================
+// Description: Set a pending swap ovject for a given slot
+//
+// Parameters: slot - the slot whose object is to be set
+// pObject - the object to place in the slot
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::SetPendingSwapObject
+(
+ unsigned int slot,
+ daSoundFileInstance* pObject
+)
+{
+ if( GetPendingSwapObject( slot ) != NULL )
+ {
+ --m_PendingSwapCount;
+ --s_GlobalPendingSwapCount;
+ }
+ if( pObject != NULL )
+ {
+ ++m_PendingSwapCount;
+ ++s_GlobalPendingSwapCount;
+ }
+ SetObject_Internal( m_ppPendingSwapObjects, slot, pObject );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::ArePendingSwapsRegistered
+//=============================================================================
+// Description: Returns true if there are still pending swaps registered
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundDynaLoadRegion::ArePendingSwapsRegistered( void )
+{
+ return( m_PendingSwapCount > 0 );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::ArePendingSwapsRegistered
+//=============================================================================
+// Description: Returns true if there are still pending swaps registered
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundDynaLoadRegion::GetNumPendingSwaps( void )
+{
+ return( s_GlobalPendingSwapCount );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetPendingSwapObject
+//=============================================================================
+// Description: Get a pending swap object for a given slot
+//
+// Return: Returns the sound object
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance* daSoundDynaLoadRegion::GetPendingSwapObject
+(
+ unsigned int slot
+)
+{
+ return GetObject_Internal( m_ppPendingSwapObjects, slot );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SetObject_Internal
+//=============================================================================
+// Description: Set an object in an object array
+//
+// Parameters: ppObjects - the object array
+// slot - the slot whose object is to be set
+// pObject - the object to place in the slot
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::SetObject_Internal
+(
+ daSoundFileInstance** ppObjects,
+ unsigned int slot,
+ daSoundFileInstance* pObject
+)
+{
+ rAssert( m_IsInitialized );
+ rAssert( ppObjects != NULL );
+ rAssert( slot < m_NumSlots );
+
+ // Under the current usage of this class, we cannot set a slot object
+ // to anything but NULL if an object already exists.
+ daSoundFileInstance* pOldObject = GetObject_Internal
+ (
+ ppObjects,
+ slot
+ );
+ rAssert( (pObject == NULL ) || ( pOldObject == NULL ) );
+ if( pOldObject != pObject )
+ {
+ // Out with the old
+ if( pOldObject != NULL )
+ {
+ pOldObject->Release( );
+ pOldObject = NULL;
+ }
+
+ // In with the new
+ ppObjects[ slot ] = pObject;
+ rAssert( GetObject_Internal( ppObjects, slot ) == pObject );
+ if( ppObjects[ slot ] != NULL )
+ {
+ ppObjects[ slot ]->AddRef( );
+ }
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::GetObject_Internal
+//=============================================================================
+// Description: Get an object in an object array
+//
+// Return: Returns the sound object
+//
+//-----------------------------------------------------------------------------
+
+daSoundFileInstance* daSoundDynaLoadRegion::GetObject_Internal
+(
+ daSoundFileInstance** ppObjects,
+ unsigned int slot
+)
+{
+ rAssert( m_IsInitialized );
+ rAssert( ppObjects != NULL );
+ rAssert( slot < m_NumSlots );
+
+ return( ppObjects[ slot ] );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::ClearActiveSwap
+//=============================================================================
+// Description: Clear the active swap region
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadRegion::ClearActiveSwap( void )
+{
+ if( s_pActiveRegion == this )
+ {
+ s_pActiveRegion = NULL;
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadRegion::SetActiveSwap
+//=============================================================================
+// Description: Set the active swap to this object. This is used
+// to help serialize dynamic loading.
+//
+// Returns: Returns true if the active swap region has been set to
+// this.
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundDynaLoadRegion::SetActiveSwap( unsigned int slot )
+{
+ if( s_pActiveRegion == NULL )
+ {
+ s_pActiveRegion = this;
+ s_ActiveSlot = slot;
+
+ return true;
+ }
+ return false;
+}
+
+
+//=============================================================================
+// daSoundDynaLoadManager Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::daSoundDynaLoadManager
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadManager::daSoundDynaLoadManager( )
+ :
+ radRefCount( 0 ),
+ m_pCompletionCallback( NULL ),
+ m_pCompletionUserData( NULL )
+{
+ // Set the singleton
+ rAssert( s_pSingleton == NULL );
+ s_pSingleton = this;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager:~daSoundDynaLoadManager
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadManager::~daSoundDynaLoadManager( )
+{
+ // Remove the singleton
+ rAssert( s_pSingleton != NULL );
+ s_pSingleton = NULL;
+
+ // Assert that there is no pending completion callback
+ rAssert( m_pCompletionCallback == NULL );
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::GetInstance
+//=============================================================================
+// Description: Get the singleton instance of the load manager
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadManager* daSoundDynaLoadManager::GetInstance( void )
+{
+ return s_pSingleton;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::ServiceOncePerFrame
+//=============================================================================
+// Description: Service the load manager.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadManager::ServiceOncePerFrame( void )
+{
+ IDaSoundDynaLoadCompletionCallback* callback;
+
+ // Service each of the regions
+ daSoundDynaLoadRegion* pDynaLoadRegion =
+ daSoundDynaLoadRegion::GetLinkedClassHead( );
+ while( pDynaLoadRegion != NULL )
+ {
+ pDynaLoadRegion->ServiceOncePerFrame( );
+ pDynaLoadRegion = pDynaLoadRegion->GetLinkedClassNext( );
+ }
+
+ // Call any completion callbacks
+ if
+ (
+ ( m_pCompletionCallback != NULL ) &&
+ ( daSoundDynaLoadRegion::GetNumPendingSwaps( ) == 0 )
+ )
+ {
+ //
+ // Store the callback separately before using, since the callback
+ // may lead to another sound load
+ //
+ callback = m_pCompletionCallback;
+ m_pCompletionCallback = NULL;
+ m_pCompletionUserData = NULL;
+
+ callback->OnDynaLoadOperationsComplete
+ (
+ m_pCompletionUserData
+ );
+
+ callback->Release();
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::CreateRegion
+//=============================================================================
+// Description: Create a dynamic loading region
+//
+// Parameters: pMemRegion - the sound region to divide up so that
+// the given slots may be created.
+// sizeofslots - the size of the dynamic loading slots
+// numslots - the number of dynamic loading slots
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadRegion* daSoundDynaLoadManager::CreateRegion
+(
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots,
+ unsigned int numslots
+)
+{
+ rAssert( pMemRegion != NULL );
+#ifdef DASOUNDDYNALOAD_DEBUG
+ if( sg_ShowDynaLoadRegionCreation )
+ {
+ rReleasePrintf
+ (
+ "CreateRegion( %#x, sizeofslots=%u, numslots=%u )\n",
+ pMemRegion,
+ sizeofslots,
+ numslots,
+ 0
+ );
+ }
+#endif //DASOUNDDYNALOAD_DEBUG
+
+ // Make sure the new region fits into memory
+ unsigned int freeSpace = 0;
+ pMemRegion->GetStats( NULL, NULL, &freeSpace, false );
+ daSoundDynaLoadRegion* pDynaRegion = NULL;
+ if( freeSpace >= sizeofslots * numslots )
+ {
+ // Create the memory region
+ pDynaRegion = new( GetThisAllocator( ) ) daSoundDynaLoadRegion( );
+ rAssert( pDynaRegion != NULL );
+ pDynaRegion->Create( pMemRegion, sizeofslots, numslots );
+ }
+ else
+ {
+ // Out of memory!
+ // If this occurs during the game, your loading stratagies must be
+ // reconsidered. If it happens while setting up sounds for
+ // the game then the choices of resident sound files must
+ // be looked at, or more sound memory should be allocated.
+ rDebugString( "Out of sound memory trying to create sound region\n" );
+ rAssert( 0 );
+ }
+
+ return pDynaRegion;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::CreateRegionFromTotalSpace
+//=============================================================================
+// Description: Create a dynamic loading region when given a total amount of
+// space.
+//
+// Parameters: pMemRegion - the sound region to divide up so that
+// the given slots may be created.
+// sizeofslots - the size of the dynamic loading slots
+//
+// Note: The actual amount of space used will be aligned down by the
+// size of slots.
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadRegion* daSoundDynaLoadManager::CreateRegionFromTotalSpace
+(
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots
+)
+{
+ rAssert( pMemRegion != NULL );
+
+ // How much free space is there?
+ unsigned int freeSpace = 0;
+ pMemRegion->GetStats( NULL, NULL, &freeSpace, false );
+
+ // How many slots can we make
+ unsigned int numslots = freeSpace / sizeofslots;
+
+ // Make the slots
+ daSoundDynaLoadRegion* pDynaRegion = NULL;
+ if( numslots > 0 )
+ {
+ pDynaRegion = CreateRegion( pMemRegion, sizeofslots, numslots );
+ }
+
+ return pDynaRegion;
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::AddCompletionCallback
+//=============================================================================
+// Description: Add a completion callback
+//
+//-----------------------------------------------------------------------------
+
+void daSoundDynaLoadManager::AddCompletionCallback
+(
+ IDaSoundDynaLoadCompletionCallback* pCallback,
+ void* pUserData
+)
+{
+ if( m_pCompletionCallback != NULL )
+ {
+ rDebugString( "Cannot add a completion callback while one is\n" );
+ rDebugString( "pending using current sounddynamic loading manager.\n" );
+ rAssert( 0 );
+
+ m_pCompletionCallback->Release( );
+ m_pCompletionCallback = NULL;
+ }
+
+ m_pCompletionCallback = pCallback;
+ m_pCompletionUserData = pUserData;
+
+ if( m_pCompletionCallback != NULL )
+ {
+ m_pCompletionCallback->AddRef( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundDynaLoadManager::GetNumPendingSwaps
+//=============================================================================
+// Description: Returns the number of load regions in line to
+// be loaded with new data
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundDynaLoadManager::GetNumPendingSwaps( void )
+{
+ return daSoundDynaLoadRegion::GetNumPendingSwaps( );
+}
+
+} // Sound Namespace
diff --git a/game/code/sound/soundrenderer/sounddynaload.h b/game/code/sound/soundrenderer/sounddynaload.h
new file mode 100644
index 0000000..ef24357
--- /dev/null
+++ b/game/code/sound/soundrenderer/sounddynaload.h
@@ -0,0 +1,199 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: sounddynaload.hpp
+//
+// Subsystem: Dark Angel - Dynamic Loading System
+//
+// Description: Description of the DA Dynamic Sound Loading System
+//
+// Revisions:
+// + Created: Novemeber 22, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _SOUNDDYNALOAD_HPP
+#define _SOUNDDYNALOAD_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radlinkedclass.hpp>
+
+#include <radsound.hpp>
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundDynaLoadRegion;
+class daSoundDynaLoadManager;
+class daSoundFileInstance;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+struct IDaSoundDynaLoadCompletionCallback : public IRefCount
+{
+ virtual void OnDynaLoadOperationsComplete( void* pUserData ) = 0;
+};
+
+//
+// A dynamic load region
+//
+class daSoundDynaLoadRegion : public radLinkedClass< daSoundDynaLoadRegion >,
+ public radRefCount
+{
+public:
+
+ enum SlotState {
+ Empty,
+ Initializing,
+ Ready,
+ Destroying
+ };
+
+ IMPLEMENT_REFCOUNTED( "daSoundDynaLoadRegion" );
+ daSoundDynaLoadRegion( );
+ virtual ~daSoundDynaLoadRegion( );
+
+ // Create and destroy the region
+ void Create
+ (
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots,
+ unsigned int numslots
+ );
+ void Destroy( void );
+ void ServiceOncePerFrame( void );
+
+ // Track if there are any pending swaps registered.
+ static unsigned int GetNumPendingSwaps( void );
+
+ //
+ // daSoundDynaLoadRegion
+ //
+ void SwapInObject
+ (
+ unsigned int slot,
+ daSoundFileInstance* pObject
+ );
+ daSoundDynaLoadRegion::SlotState GetSlotState
+ (
+ unsigned int slot
+ );
+ unsigned int GetNumSlots( void );
+ unsigned int GetSlotSize( void );
+
+protected:
+ bool SharedMemoryRegions( void );
+
+ void PerformSwap( unsigned int slot );
+
+ IRadSoundHalMemoryRegion* GetSlotMemoryRegion( unsigned int slot );
+
+ void SetSlotObject( unsigned int slot, daSoundFileInstance* pObject );
+ daSoundFileInstance* GetSlotObject( unsigned int slot );
+
+ void SetPendingSwapObject( unsigned int slot, daSoundFileInstance * pObject );
+ bool ArePendingSwapsRegistered( void );
+ daSoundFileInstance* GetPendingSwapObject( unsigned int slot );
+
+ void SetObject_Internal
+ (
+ daSoundFileInstance** ppObjects,
+ unsigned int slot,
+ daSoundFileInstance* pObject
+ );
+ daSoundFileInstance* GetObject_Internal
+ (
+ daSoundFileInstance** ppObjects,
+ unsigned int slot
+ );
+
+ void ClearActiveSwap( void );
+ bool SetActiveSwap( unsigned int slot );
+
+private:
+ bool m_IsInitialized;
+
+ // The active swap
+ static daSoundDynaLoadRegion* s_pActiveRegion;
+ static unsigned int s_ActiveSlot;
+
+ // Region information
+ unsigned int m_NumSlots;
+ unsigned int m_SlotSize;
+
+ // Allocated regions
+ IRadSoundHalMemoryRegion** m_ppSlot;
+ daSoundFileInstance** m_ppSlotObjects;
+ daSoundFileInstance** m_ppPendingSwapObjects;
+
+ // Count of pending swap operations
+ unsigned int m_PendingSwapCount;
+ static unsigned int s_GlobalPendingSwapCount;
+};
+
+//
+// Dynamic loading system interface
+//
+class daSoundDynaLoadManager : public radRefCount
+{
+public:
+ IMPLEMENT_REFCOUNTED( "daSoundDynaLoadManager" );
+ daSoundDynaLoadManager( );
+ virtual ~daSoundDynaLoadManager( );
+
+ static daSoundDynaLoadManager* GetInstance( void );
+
+ //
+ // daSoundDynaLoadRegion
+ //
+ virtual void ServiceOncePerFrame( void );
+
+ daSoundDynaLoadRegion* CreateRegion
+ (
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots,
+ unsigned int numslots
+ );
+ daSoundDynaLoadRegion* CreateRegionFromTotalSpace
+ (
+ IRadSoundHalMemoryRegion* pMemRegion,
+ unsigned int sizeofslots
+ );
+ void AddCompletionCallback
+ (
+ IDaSoundDynaLoadCompletionCallback* pCallback,
+ void* pUserData
+ );
+ unsigned int GetNumPendingSwaps( void );
+
+protected:
+private:
+ //
+ // Store this class as a singleton
+ //
+ static daSoundDynaLoadManager* s_pSingleton;
+
+ //
+ // Store a completion callback
+ //
+ IDaSoundDynaLoadCompletionCallback* m_pCompletionCallback;
+ void* m_pCompletionUserData;
+};
+
+} // Sound Namespace
+#endif //_SOUNDDYNALOAD_HPP
+
diff --git a/game/code/sound/soundrenderer/soundnucleus.cpp b/game/code/sound/soundrenderer/soundnucleus.cpp
new file mode 100644
index 0000000..2c56488
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundnucleus.cpp
@@ -0,0 +1,594 @@
+#include <sound/soundrenderer/soundnucleus.hpp>
+#include <main/commandlineoptions.h>
+#include <memory/srrmemory.h>
+#include <radmusic/radmusic.hpp>
+#include <memory/srrmemory.h>
+
+namespace Sound
+{
+
+const Encoding gPcmEncoding = { IRadSoundHalAudioFormat::PCM, 1, 1 };
+const Encoding gPcmBEncoding = { IRadSoundHalAudioFormat::PCM_BIGENDIAN, 1, 1 };
+const Encoding gVagEncoding = { IRadSoundHalAudioFormat::VAG, 2, 7 };
+const Encoding gGcAdpcmEncoding = { IRadSoundHalAudioFormat::GCNADPCM, 2, 7 };
+const Encoding gRadAdpcmEncoding = { IRadSoundHalAudioFormat::RadicalAdpcm, 5, 16 };
+const Encoding gXAdpcmEncoding = { IRadSoundHalAudioFormat::XBOXADPCM, 36, 128 };
+
+const unsigned int NUM_AUX_SENDS = 1;
+
+const unsigned int MUSIC_NUM_STREAM_PLAYERS = 4;
+const unsigned int MUSIC_NUM_CLIP_PLAYERS = 2;
+const unsigned int MUSIC_NUM_CHANNELS = 2;
+const unsigned int MUSIC_SAMPLING_RATE = 24000;
+
+const unsigned int TOTAL_PS2_FREE_UNCOMPRESSED_CLIP_BYTES = ( 1624 * 1024 * 7 ) / 2;
+
+#if defined RAD_GAMECUBE
+
+ const int ARAM_SILENT_BUFFER_SIZE = 1280;
+ const int ARAM_USER_START = 0x4000;
+ const int ARAM_RESERVED_BINK_MEMORY = 0x25800;
+ const int GAMECUBE_SOUND_MEMORY_AVAILABLE =
+ ( 1024 * 1024 * 10 ) - ARAM_SILENT_BUFFER_SIZE - ARAM_USER_START - ARAM_RESERVED_BINK_MEMORY;
+
+ const int PLAYBACK_RATE = 32000;
+
+ AudioFormat gCompressedStreamAudioFormat = { 1, & gGcAdpcmEncoding, 24000 };
+ AudioFormat gUnCompressedStreamAudioFormat = { 1, & gPcmBEncoding, 24000 };
+ AudioFormat gClipFileAudioFormat = { 1, & gPcmBEncoding, 24000 };
+ AudioFormat gMusicAudioFormat = { 2, & gPcmBEncoding, 24000 };
+
+ const unsigned int STREAM_BUFFER_SIZE_MS = 6000;
+ const bool STREAM_USE_BUFFERED_DATA_SOURCES = false;
+ const unsigned int STREAM_BUFFERED_DATA_SOURCE_SIZE_MS = 0;
+ const radMemorySpace STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Local;
+
+ const unsigned int CLIP_BUFFERED_DATA_SOURCE_SIZE_MS = 0;
+ const radMemorySpace CLIP_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Local;
+
+#elif defined RAD_XBOX || defined RAD_WIN32
+
+ const int PLAYBACK_RATE = 0;
+
+#ifdef PAL
+ AudioFormat gCompressedStreamAudioFormat = { 1, & gXAdpcmEncoding, 24000 };
+#else
+ AudioFormat gCompressedStreamAudioFormat = { 1, & gPcmEncoding, 24000 };
+#endif
+ AudioFormat gUnCompressedStreamAudioFormat = { 1, & gPcmEncoding, 24000 };
+ AudioFormat gClipFileAudioFormat = { 1, & gPcmEncoding, 24000 };
+ AudioFormat gMusicAudioFormat = { 2, & gPcmEncoding, 24000 };
+
+ const unsigned int STREAM_BUFFER_SIZE_MS = 6000;
+ const bool STREAM_USE_BUFFERED_DATA_SOURCES = false;
+ const unsigned int STREAM_BUFFERED_DATA_SOURCE_SIZE_MS = 0;
+ const radMemorySpace STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Local;
+
+ const unsigned int CLIP_BUFFERED_DATA_SOURCE_SIZE_MS = 0;
+ const radMemorySpace CLIP_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Local;
+
+
+#elif defined RAD_PS2
+
+ const int PLAYBACK_RATE = 0;
+
+ AudioFormat gCompressedStreamAudioFormat = { 1, & gVagEncoding, 24000 };
+ AudioFormat gUnCompressedStreamAudioFormat = { 1, & gVagEncoding, 24000 };
+ AudioFormat gClipFileAudioFormat = { 1, & gVagEncoding, 24000 };
+ AudioFormat gMusicAudioFormat = { 2, & gVagEncoding, 24000 };
+
+ const unsigned int STREAM_BUFFER_SIZE_MS = 1000;
+ const bool STREAM_USE_BUFFERED_DATA_SOURCES = true;
+ const unsigned int STREAM_BUFFERED_DATA_SOURCE_SIZE_MS = 4100;
+ const radMemorySpace STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Iop;
+
+ const unsigned int CLIP_BUFFERED_DATA_SOURCE_SIZE_MS = 5000;
+ const radMemorySpace CLIP_BUFFERED_DATA_SOURCE_MEMORY_SPACE = radMemorySpace_Ee;
+
+#endif
+
+enum ClipLoadState
+{
+ ClipLoadState_Idle,
+ ClipLoadState_InitFile,
+ ClipLoadState_FillingBuffer,
+ ClipLoadState_LoadingClip,
+ ClipLoadState_Done
+};
+
+
+struct ClipLoadInfo
+{
+ IRadSoundRsdFileDataSource * pFds;
+ IRadSoundClip * pClip;
+ IRadSoundBufferedDataSource * pBds;
+ ClipLoadState state;
+ bool looping;
+} gClipLoadInfo;
+
+StreamerResources gStreamers[ SOUND_NUM_STREAM_PLAYERS ] =
+{
+ { NULL, NULL, NULL, & gCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+#ifdef RAD_XBOX
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 },
+#endif
+ { NULL, NULL, NULL, & gUnCompressedStreamAudioFormat, false, 0 }
+};
+
+
+void CreateAudioFormat( AudioFormat * pAf, radMemoryAllocator alloc )
+{
+ pAf->m_pAudioFormat = ::radSoundHalAudioFormatCreate( alloc );
+ pAf->m_pAudioFormat->AddRef( );
+
+ pAf->m_pAudioFormat->Initialize(
+ pAf->m_pEncoding->m_Encoding,
+ NULL,
+ pAf->m_SamplingRate,
+ pAf->m_Channels,
+ 16 );
+}
+
+void DestroyAudioFormat( AudioFormat * pAf )
+{
+ pAf->m_pAudioFormat->Release( );
+ pAf->m_pAudioFormat = NULL;
+}
+
+void CreateStreamerResources( StreamerResources * pSi, radMemoryAllocator alloc )
+{
+ pSi->m_pStreamPlayer = ::radSoundStreamPlayerCreate( alloc );
+ pSi->m_pStreamPlayer->AddRef( );
+
+ pSi->m_pStreamPlayer->Initialize(
+ pSi->m_pAudioFormat->m_pAudioFormat,
+ STREAM_BUFFER_SIZE_MS,
+ IRadSoundHalAudioFormat::Milliseconds,
+ ::radSoundHalSystemGet( )->GetRootMemoryRegion( ),
+ "Sound Stream Player" );
+
+ pSi->m_pStitchedDataSource = ::radSoundStitchedDataSourceCreate( alloc );
+ pSi->m_pStitchedDataSource->AddRef( );
+ pSi->m_pStitchedDataSource->InitializeFromAudioFormat( pSi->m_pAudioFormat->m_pAudioFormat );
+
+ if ( STREAM_USE_BUFFERED_DATA_SOURCES && ( false == CommandLineOptions::Get( CLO_FIREWIRE ) ) )
+ {
+ pSi->m_pBufferedDataSource = radSoundBufferedDataSourceCreate( alloc );
+ pSi->m_pBufferedDataSource->AddRef( );
+
+ pSi->m_pBufferedDataSource->Initialize(
+ STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE,
+ radMemorySpaceGetAllocator( STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE, RADMEMORY_ALLOC_DEFAULT ), // This is IOP Memory
+ STREAM_BUFFERED_DATA_SOURCE_SIZE_MS,
+ IRadSoundHalAudioFormat::Milliseconds,
+ pSi->m_pAudioFormat->m_pAudioFormat,
+ "DaSound Buffered DataSource" );
+
+ }
+ else
+ {
+ pSi->m_pBufferedDataSource = NULL;
+ }
+}
+
+void DestroyStreamerResources( StreamerResources* pSi )
+{
+ // Its a stream player
+ pSi->m_pStreamPlayer->Stop( );
+ pSi->m_pStreamPlayer->SetDataSource( NULL );
+
+ if( pSi->m_pBufferedDataSource )
+ {
+ pSi->m_pBufferedDataSource->Release( );
+ pSi->m_pBufferedDataSource = NULL;
+ }
+
+ // Release the player
+ pSi->m_pStreamPlayer->Release( );
+ pSi->m_pStreamPlayer = NULL;
+
+
+ pSi->m_pStitchedDataSource->Release( );
+ pSi->m_pStitchedDataSource = NULL;
+}
+
+unsigned int CalculateStreamerSize( unsigned int ms, AudioFormat * pAf )
+{
+ unsigned int sizeInFrames = pAf->m_pAudioFormat->MillisecondsToFrames( ms );
+
+ unsigned int optimalFrameMultiple =
+ pAf->m_pAudioFormat->BytesToFrames( radSoundHalDataSourceReadMultipleGet( ) );
+
+ // Our buffer must be at least as big as two optimal reads.
+
+ sizeInFrames = radMemoryRoundUp( sizeInFrames, optimalFrameMultiple * 2 );
+
+ sizeInFrames = ::radSoundHalBufferCalculateMemorySize( IRadSoundHalAudioFormat::Frames,
+ sizeInFrames, IRadSoundHalAudioFormat::Frames, pAf->m_pAudioFormat );
+
+ unsigned int sizeInBytes = pAf->m_pAudioFormat->FramesToBytes( sizeInFrames );
+
+ return sizeInBytes;
+}
+
+void SoundNucleusInitialize( radMemoryAllocator alloc )
+{
+
+#if defined( RAD_PS2 ) || defined( RAD_GAMECUBE ) || defined( RAD_WIN32 )
+ ::radSoundHalSystemInitialize( alloc );
+#else
+ ::radSoundHalSystemInitialize( GMA_XBOX_SOUND_MEMORY );
+#endif
+
+ CreateAudioFormat( & gCompressedStreamAudioFormat, alloc );
+ CreateAudioFormat( & gUnCompressedStreamAudioFormat, alloc );
+ CreateAudioFormat( & gClipFileAudioFormat, alloc );
+ CreateAudioFormat( & gMusicAudioFormat, alloc );
+
+
+
+ //
+ // ESAN TODO: Investigate the magic number 150 below...
+ //
+
+ unsigned int totalStreamSoundMemoryNeeded = 0;
+ unsigned int totalStreamBufferMemoryNeeded = 0;
+ unsigned int totalClipBufferMemoryNeeded = 0;
+
+ if ( CLIP_BUFFERED_DATA_SOURCE_SIZE_MS > 0 )
+ {
+ gClipLoadInfo.pBds = radSoundBufferedDataSourceCreate( GMA_AUDIO_PERSISTENT );
+ gClipLoadInfo.pBds->AddRef( );
+ gClipLoadInfo.pBds->Initialize(
+ CLIP_BUFFERED_DATA_SOURCE_MEMORY_SPACE,
+ radMemorySpaceGetAllocator(
+ CLIP_BUFFERED_DATA_SOURCE_MEMORY_SPACE,
+ GMA_AUDIO_PERSISTENT ),
+ CLIP_BUFFERED_DATA_SOURCE_SIZE_MS,
+ IRadSoundHalAudioFormat::Milliseconds,
+ SoundNucleusGetClipFileAudioFormat( ),
+ "Clip Bds" );
+
+ gClipLoadInfo.pBds->SetLowWaterMark( 1.0f );
+
+ totalClipBufferMemoryNeeded =
+ SoundNucleusGetClipFileAudioFormat( )->MillisecondsToBytes(
+ CLIP_BUFFERED_DATA_SOURCE_SIZE_MS );
+ }
+
+
+ for( unsigned int i = 0; i < SOUND_NUM_STREAM_PLAYERS; i ++ )
+ {
+ StreamerResources* pSi = gStreamers + i;
+
+ unsigned int streamSoundMemoryNeeded = CalculateStreamerSize(
+ STREAM_BUFFER_SIZE_MS,
+ pSi->m_pAudioFormat );
+
+ totalStreamSoundMemoryNeeded += streamSoundMemoryNeeded;
+
+ unsigned int streamBufferMemoryNeeded = CalculateStreamerSize(
+ STREAM_BUFFERED_DATA_SOURCE_SIZE_MS,
+ pSi->m_pAudioFormat );
+
+ totalStreamBufferMemoryNeeded += streamBufferMemoryNeeded;
+
+ rTunePrintf( "AUDIO: Predicting SOUND streamer will allocate: Sound: [0x%x] Buffer:[0x%x]\n",
+ streamSoundMemoryNeeded,
+ streamBufferMemoryNeeded );
+ }
+
+ for( unsigned int i = 0; i < MUSIC_NUM_STREAM_PLAYERS; i ++ )
+ {
+ unsigned int streamSoundMemoryNeeded = CalculateStreamerSize(
+ STREAM_BUFFER_SIZE_MS,
+ & gMusicAudioFormat );
+
+ totalStreamSoundMemoryNeeded += streamSoundMemoryNeeded;
+
+ unsigned int streamBufferMemoryNeeded = CalculateStreamerSize(
+ STREAM_BUFFERED_DATA_SOURCE_SIZE_MS,
+ & gMusicAudioFormat );
+
+ totalStreamBufferMemoryNeeded += streamBufferMemoryNeeded;
+
+ rTunePrintf( "AUDIO: Predicting MUSIC streamer will allocate: Sound: [0x%x] Buffer:[0x%x]\n",
+ streamSoundMemoryNeeded,
+ streamBufferMemoryNeeded );
+
+ }
+
+ unsigned int totalClipMemoryNeeded =
+ ( TOTAL_PS2_FREE_UNCOMPRESSED_CLIP_BYTES * gClipFileAudioFormat.m_pEncoding->m_CompressionNumerator ) /
+ gClipFileAudioFormat.m_pEncoding->m_CompressionDenominator;
+
+ rTunePrintf(
+ "AUDIO: Sound Memory totals: Stream: [0x%x] Clip: [0x%x], Total: [0x%x]\n",
+ totalStreamSoundMemoryNeeded,
+ totalClipMemoryNeeded,
+ totalStreamSoundMemoryNeeded + totalClipMemoryNeeded );
+
+ #ifdef RAD_GAMECUBE
+ rAssert(
+ ( totalStreamSoundMemoryNeeded + totalClipMemoryNeeded ) <=
+ GAMECUBE_SOUND_MEMORY_AVAILABLE );
+ #endif
+
+ rTunePrintf(
+ "AUDIO: Sound Buffered Stream Memory Stream: [0x%x], Clip: [0x%x] Total:\n",
+ totalStreamBufferMemoryNeeded,
+ totalClipBufferMemoryNeeded,
+ totalStreamBufferMemoryNeeded + totalClipBufferMemoryNeeded );
+
+ IRadSoundHalSystem::SystemDescription desc;
+
+ desc.m_MaxRootAllocations = 170;
+ desc.m_NumAuxSends = NUM_AUX_SENDS;
+#ifdef RAD_WIN32
+ desc.m_SamplingRate = 24000;
+#endif
+
+#ifndef RAD_PS2
+ desc.m_ReservedSoundMemory = totalStreamSoundMemoryNeeded + totalClipMemoryNeeded;
+#endif
+
+#ifdef RAD_GAMECUBE
+ desc.m_EffectsAllocator = GMA_AUDIO_PERSISTENT;
+#endif
+
+ ::radSoundHalSystemGet( )->Initialize( desc );
+ //::radSoundHalSystemGet( )->SetOutputMode( radSoundOutputMode_Surround );
+
+ for( unsigned int i = 0; i < SOUND_NUM_STREAM_PLAYERS; i ++ )
+ {
+ gStreamers[ i ].index = i;
+ CreateStreamerResources( gStreamers + i, alloc );
+ }
+
+ radmusic::stream_graph_description sgDesc[ MUSIC_NUM_STREAM_PLAYERS ];
+
+ for( unsigned int i = 0; i < MUSIC_NUM_STREAM_PLAYERS; i ++ )
+ {
+ sgDesc[ i ].buffered_data_source_size_in_ms = STREAM_BUFFERED_DATA_SOURCE_SIZE_MS;
+ sgDesc[ i ].buffered_data_source_space = STREAM_BUFFERED_DATA_SOURCE_MEMORY_SPACE;
+ sgDesc[ i ].channels = MUSIC_NUM_CHANNELS;
+ sgDesc[ i ].sampling_rate = MUSIC_SAMPLING_RATE;
+ sgDesc[ i ].stream_buffer_size_in_ms = STREAM_BUFFER_SIZE_MS;
+ sgDesc[ i ].use_buffered_data_source = CommandLineOptions::Get( CLO_FIREWIRE ) ? false : STREAM_USE_BUFFERED_DATA_SOURCES;
+ }
+
+ radmusic::initialize( sgDesc, MUSIC_NUM_STREAM_PLAYERS, MUSIC_NUM_CLIP_PLAYERS, GMA_MUSIC );
+ radmusic::register_radload_loaders( );
+
+}
+
+void SoundNucleusTerminate( void )
+{
+ rAssert( ClipLoadState_Idle == gClipLoadInfo.state );
+
+ if ( gClipLoadInfo.pBds != NULL )
+ {
+ gClipLoadInfo.pBds->Release( );
+ }
+
+ for( unsigned int i = 0; i < SOUND_NUM_STREAM_PLAYERS; i ++ )
+ {
+ DestroyStreamerResources( gStreamers + i );
+ }
+
+ DestroyAudioFormat( & gCompressedStreamAudioFormat );
+ DestroyAudioFormat( & gUnCompressedStreamAudioFormat );
+ DestroyAudioFormat( & gClipFileAudioFormat );
+ DestroyAudioFormat( & gMusicAudioFormat );
+
+ radmusic::terminate( );
+
+ // Shutdown our related systems
+ ::radSoundHalSystemTerminate( );
+
+}
+
+IRadSoundHalAudioFormat * SoundNucleusGetStreamFileAudioFormat( void )
+{
+#if defined( RAD_GAMECUBE ) || ( defined( RAD_XBOX ) && defined( PAL ) )
+ return NULL;
+ #else
+ return gUnCompressedStreamAudioFormat.m_pAudioFormat;
+ #endif
+
+}
+
+IRadSoundHalAudioFormat * SoundNucleusGetClipFileAudioFormat( void )
+{
+ return gClipFileAudioFormat.m_pAudioFormat;
+}
+
+StreamerResources* SoundNucleusCaptureStreamerResources( IRadSoundHalAudioFormat * pAf )
+{
+ for( unsigned int i = 0; i < SOUND_NUM_STREAM_PLAYERS; i ++ )
+ {
+ StreamerResources * pSi =
+ gStreamers + i;
+
+ if ( ! pSi->m_IsCaptured )
+ {
+ if ( pSi->m_pAudioFormat->m_pAudioFormat->Matches( pAf ) )
+ {
+ pSi->m_IsCaptured = true;
+ return pSi;
+ }
+ }
+ }
+
+ rTuneAssertMsg( false, "Out of streamers of desired format" );
+
+ return NULL;
+}
+
+void SoundNucleusUnCaptureStreamerResources( StreamerResources * pSi )
+{
+ rAssert( gStreamers[ pSi->index ].m_IsCaptured == true );
+ gStreamers[ pSi->index ].m_IsCaptured = false;
+}
+
+void SoundNucleusLoadClip( const char * pFileName, bool looping )
+{
+ rAssert( ClipLoadState_Idle == gClipLoadInfo.state );
+
+ gClipLoadInfo.pFds = radSoundRsdFileDataSourceCreate( GMA_AUDIO_PERSISTENT );
+ gClipLoadInfo.pFds->AddRef( );
+ gClipLoadInfo.looping = looping;
+
+
+ // Initialize the file data source iwth our file
+ //
+ gClipLoadInfo.pFds->InitializeFromFileName(
+ pFileName,
+ false,
+ 0,
+ IRadSoundHalAudioFormat::Frames,
+ SoundNucleusGetClipFileAudioFormat( ) );
+
+ gClipLoadInfo.state = ClipLoadState_InitFile;
+}
+
+bool SoundNucleusIsClipLoaded( void )
+{
+ rAssert( ClipLoadState_Idle != gClipLoadInfo.state );
+
+ return ClipLoadState_Done == gClipLoadInfo.state;
+}
+
+void SoundNucleusFinishClipLoad( IRadSoundClip ** ppClip )
+{
+ rAssert( ClipLoadState_Done == gClipLoadInfo.state );
+
+ *ppClip = gClipLoadInfo.pClip;
+ gClipLoadInfo.pClip = NULL;
+
+ gClipLoadInfo.pFds->Release( );
+ gClipLoadInfo.pFds = NULL;
+
+ if ( NULL != gClipLoadInfo.pBds )
+ {
+ gClipLoadInfo.pBds->SetInputDataSource( 0 );
+ }
+
+ gClipLoadInfo.state = ClipLoadState_Idle;
+}
+
+void SoundNucleusCancelClipLoad( void )
+{
+ rAssert( ClipLoadState_Idle != gClipLoadInfo.state );
+
+ if( NULL != gClipLoadInfo.pClip )
+ {
+ gClipLoadInfo.pClip->Release( );
+ gClipLoadInfo.pClip = NULL;
+ }
+
+ if( NULL != gClipLoadInfo.pFds )
+ {
+ gClipLoadInfo.pFds->Release( );
+ gClipLoadInfo.pFds = NULL;
+ }
+
+ if ( NULL != gClipLoadInfo.pBds )
+ {
+ gClipLoadInfo.pBds->SetInputDataSource( 0 );
+ }
+
+ gClipLoadInfo.state = ClipLoadState_Idle;
+
+}
+
+
+void SoundNucleusServiceClipLoad( void )
+{
+ ClipLoadState oldState;
+
+ do
+ {
+ oldState = gClipLoadInfo.state;
+
+ switch ( gClipLoadInfo.state )
+ {
+ case ClipLoadState_Idle:
+ {
+ break;
+ }
+ case ClipLoadState_InitFile:
+ {
+ if ( IRadSoundHalDataSource::Initialized == gClipLoadInfo.pFds->GetState( ) )
+ {
+ if ( gClipLoadInfo.pBds != NULL )
+ {
+ unsigned int ms =
+ gClipLoadInfo.pBds->GetFormat( )->FramesToMilliseconds(
+ gClipLoadInfo.pFds->GetRemainingFrames( ) );
+
+ rTuneAssert( ms < CLIP_BUFFERED_DATA_SOURCE_SIZE_MS );
+
+ gClipLoadInfo.pBds->SetInputDataSource( gClipLoadInfo.pFds );
+
+ gClipLoadInfo.state = ClipLoadState_FillingBuffer;
+ }
+ else
+ {
+ gClipLoadInfo.pClip = radSoundClipCreate( GMA_AUDIO_PERSISTENT );
+ gClipLoadInfo.pClip->AddRef( );
+ gClipLoadInfo.pClip->Initialize(
+ gClipLoadInfo.pFds,
+ radSoundHalSystemGet( )->GetRootMemoryRegion( ),
+ gClipLoadInfo.looping,
+ "Clip" );
+
+ gClipLoadInfo.state = ClipLoadState_LoadingClip;
+ }
+ }
+
+ break;
+ }
+ case ClipLoadState_FillingBuffer:
+ {
+ if ( gClipLoadInfo.pBds->IsBufferFull( ) )
+ {
+ gClipLoadInfo.pClip = radSoundClipCreate( GMA_AUDIO_PERSISTENT );
+ gClipLoadInfo.pClip->AddRef( );
+ gClipLoadInfo.pClip->Initialize(
+ gClipLoadInfo.pBds,
+ radSoundHalSystemGet( )->GetRootMemoryRegion( ),
+ gClipLoadInfo.looping,
+ "Clip" );
+
+ gClipLoadInfo.state = ClipLoadState_LoadingClip;
+ }
+
+ break;
+ }
+ case ClipLoadState_LoadingClip:
+ {
+ if ( IRadSoundClip::Initialized == gClipLoadInfo.pClip->GetState( ) )
+ {
+ gClipLoadInfo.state = ClipLoadState_Done;
+ }
+
+ break;
+ }
+ case ClipLoadState_Done:
+ {
+ break;
+ }
+ }
+ }
+ while( oldState != gClipLoadInfo.state );
+}
+
+} \ No newline at end of file
diff --git a/game/code/sound/soundrenderer/soundnucleus.hpp b/game/code/sound/soundrenderer/soundnucleus.hpp
new file mode 100644
index 0000000..dc028e3
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundnucleus.hpp
@@ -0,0 +1,70 @@
+
+#ifndef SOUNDNUCLEUS_HPP
+#define SOUNDNUCLEUS_HPP
+
+#include <radmemory.hpp>
+#include <radsound.hpp>
+
+namespace Sound
+{
+#ifdef RAD_XBOX
+ const unsigned int SOUND_NUM_STREAM_PLAYERS = 10;
+#else
+ const unsigned int SOUND_NUM_STREAM_PLAYERS = 9;
+#endif
+ const unsigned int SOUND_NUM_CLIP_PLAYERS = 64;
+
+struct Encoding
+{
+ IRadSoundHalAudioFormat::Encoding m_Encoding;
+ unsigned int m_CompressionNumerator;
+ unsigned int m_CompressionDenominator;
+};
+
+struct AudioFormat
+{
+ unsigned int m_Channels;
+ const Encoding * m_pEncoding;
+ unsigned int m_SamplingRate;
+ IRadSoundHalAudioFormat * m_pAudioFormat;
+};
+
+struct StreamerResources
+{
+ IRadSoundStreamPlayer * m_pStreamPlayer;
+ IRadSoundBufferedDataSource * m_pBufferedDataSource;
+ IRadSoundStitchedDataSource * m_pStitchedDataSource;
+ AudioFormat * m_pAudioFormat;
+ bool m_IsCaptured;
+ unsigned int index;
+};
+
+void SoundNucleusInitialize( radMemoryAllocator alloc );
+void SoundNucleusTerminate( void );
+
+IRadSoundHalAudioFormat * SoundNucleusGetStreamFileAudioFormat( void );
+IRadSoundHalAudioFormat * SoundNucleusGetClipFileAudioFormat( void );
+
+StreamerResources * SoundNucleusCaptureStreamerResources( IRadSoundHalAudioFormat * pAf );
+void SoundNucleusUnCaptureStreamerResources( StreamerResources * pSi );
+
+void SoundNucleusLoadClip( const char * pFileName, bool looping );
+bool SoundNucleusIsClipLoaded( void );
+void SoundNucleusCancelClipLoad( void );
+void SoundNucleusFinishClipLoad( IRadSoundClip ** ppClip );
+void SoundNucleusServiceClipLoad( void );
+
+}
+
+#endif
+
+
+
+
+
+
+
+
+
+
+
diff --git a/game/code/sound/soundrenderer/soundplayer.h b/game/code/sound/soundrenderer/soundplayer.h
new file mode 100644
index 0000000..78538d3
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundplayer.h
@@ -0,0 +1,468 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: dasoundplayer.hpp
+//
+// Subsystem: Dark Angel - Sound players
+//
+// Description: Defines the a Dark Angel sound player
+//
+// Revisions:
+// + Created October 16, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _DASOUNDPLAYER_HPP
+#define _DASOUNDPLAYER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radlinkedclass.hpp>
+
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/soundallocatedresource.h>
+#include <radsound.hpp>
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+struct IRadObjectBTree;
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundClipStreamPlayer;
+class daSoundTuner;
+struct IDaSoundPlayerState;
+struct StreamerResources;
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+class daSoundAllocatedResource;
+
+//=============================================================================
+// Typdefs and enumerations
+//=============================================================================
+
+const float radSoundPitchChangeThreshold = 0.1f;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+class daSoundPlayerBase :
+ public IRefCount,
+ public radLinkedClass< daSoundPlayerBase >,
+ public radRefCount
+{
+ public:
+
+ inline daSoundPlayerBase( ) : radRefCount( 0 ) { }
+ virtual ~daSoundPlayerBase( ) { }
+
+ IMPLEMENT_REFCOUNTED( "daSoundPlayerBase" );
+
+ virtual void ServiceOncePerFrame ( void ) = 0;
+ virtual bool IsCaptured ( void ) = 0;
+ virtual void Pause ( void ) = 0;
+ virtual void Continue ( void ) = 0;
+ virtual void UberContinue( void ) = 0;
+ virtual void Stop ( void ) = 0;
+ virtual void SetPitch( float pitch ) = 0;
+ virtual bool IsPaused( void ) = 0;
+
+ virtual void ChangeTrim( daSoundGroup groupName, float newTrim ) = 0;
+ virtual void ChangeFaderTrim( daSoundGroup groupName, float newTrim ) = 0;
+};
+
+//
+// This contains a Dark Angel player instance.
+//
+class daSoundClipStreamPlayer
+ :
+ public daSoundPlayerBase,
+ public IRadSoundStitchCallback
+
+{
+public:
+
+ //
+ // Constructor and destructor
+ //
+ daSoundClipStreamPlayer( void );
+ virtual ~daSoundClipStreamPlayer ( void );
+
+ // daSoundPlayerBase
+
+ virtual void ServiceOncePerFrame ( void );
+ virtual bool IsCaptured ( void );
+ virtual void Pause ( void );
+ virtual void Continue ( void );
+ virtual void UberContinue( void );
+ virtual void Stop ( void );
+ virtual void SetPitch( float pitch );
+
+ virtual void ChangeTrim( daSoundGroup groupName, float newTrim );
+ virtual void ChangeFaderTrim( daSoundGroup groupName, float newTrim );
+
+ bool IsPaused( void );
+
+ //
+ // Sound player states
+ //
+
+ enum State {
+ State_DeCued,
+ State_Cueing,
+ State_Cued,
+ State_CuedPlay,
+ State_Playing,
+ State_Stopping,
+ State_Done
+ };
+
+ //
+ // Get and state this player's state
+ //
+
+ inline State GetState ( void );
+
+ //
+ // Initialize with some form of player
+ //
+ void InitializeAsClipPlayer( void );
+ void InitializeAsStreamPlayer( void );
+
+ void Capture(
+ IDaSoundResource* pResource,
+ bool isPositional );
+
+ inline IRadSoundHalPositionalGroup* GetPositionalGroup( void );
+
+ void Play( void );
+ void UnCapture ( void );
+
+ inline void SetPositionAndVelocity(
+ const radSoundVector * pPosition,
+ const radSoundVector * pVelocity );
+
+ inline void SetMinMaxDistance( float min, float max );
+
+ inline void SetExternalTrim( float newTrim );
+ inline void SetGroupTrim( float newTrim );
+ inline void SetFaderGroupTrim( float newTrim );
+ inline void SetMasterTrim( float newTrim );
+
+ inline IDaSoundResource::Type GetPlayerType ( void );
+ daSoundGroup GetSoundGroup ( void );
+
+ void RegisterSoundPlayerStateCallback
+ (
+ IDaSoundPlayerState* pCallback,
+ void* pUserData
+ );
+ void UnregisterSoundPlayerStateCallback
+ (
+ IDaSoundPlayerState* pCallback,
+ void* pUserData
+ );
+
+ unsigned int GetPlaybackTimeInSamples ( void );
+
+ void OnStitch( IRadSoundHalDataSource **, unsigned int frameCount, void * pUserData );
+
+ const void GetFileName( char * pBuf, unsigned int max );
+
+private:
+
+ enum CueingState
+ {
+ CueingState_Null,
+ CueingState_Resource,
+ CueingState_Player,
+ CueingState_Cued
+ };
+
+ inline void CalculateCurrentTrim( void );
+ inline void CalculateCurrentPitch( void );
+ void HookUpAndCuePlayer( void );
+
+ void UpdateClip( void );
+ void UpdateStream( void );
+
+ //
+ // Get the randomized trim and pitch settings based on a
+ // min/max variance of the current resource
+ //
+ inline void CalculateNewVaryingTrim ( void );
+ inline void CalculateNewVaryingPitch ( void );
+
+ //
+ // Trim values
+ //
+ float m_Trim;
+ float m_GroupTrim;
+ float m_FaderGroupTrim;
+ float m_MasterTrim;
+ float m_StoppingTrim;
+ float m_VaryingTrim;
+ float m_CurrentTrim; // floating target
+
+ float m_VaryingPitch;
+ float m_Pitch;
+ float m_CurrentPitch; // floating target
+
+ //
+ // Sound player state
+ //
+ State m_State;
+ CueingState m_CueingState;
+
+ //
+ // Hold a capture counter
+ //
+ unsigned int m_CaptureCount;
+
+ //
+ // Hold a pause counter
+ //
+ unsigned int m_PauseCount;
+
+ //
+ // Store the allocated and normal resource
+ //
+ daSoundAllocatedResource* m_pAllocatedResource;
+ unsigned int m_AllocResInstanceID;
+ IDaSoundResource* m_pResource;
+
+ //
+ // The positional group that this player uses
+ //
+ IRadSoundHalPositionalGroup * m_pPositionalGroup;
+ bool m_IsPositional;
+
+ //
+ // Currently, only one callback is allowed at a time
+ //
+ IDaSoundPlayerState* m_pStateChangeCallback;
+ void* m_pStateChangeCallbackUserData;
+
+ //
+ // Store the various types of players based on the connected resource
+ //
+ union
+ {
+ struct
+ {
+ IRadSoundClipPlayer* m_pClipPlayer;
+ } m_ClipInfo;
+
+ struct
+ {
+ StreamerResources* m_pResources;
+ IRadSoundRsdFileDataSource* m_pRsdFileDataSource;
+ } m_StreamInfo;
+ };
+
+ IDaSoundResource::Type m_Type;
+};
+
+
+inline IDaSoundResource::Type daSoundClipStreamPlayer::GetPlayerType( void )
+{
+ return m_Type;
+}
+
+inline void daSoundClipStreamPlayer::SetExternalTrim( float newTrim )
+{
+ radSoundVerifyAnalogVolume( newTrim );
+
+ m_Trim = newTrim;
+
+}
+
+inline void daSoundClipStreamPlayer::SetGroupTrim( float newTrim )
+{
+ radSoundVerifyAnalogVolume( newTrim );
+
+ m_GroupTrim = newTrim;
+
+}
+
+inline void daSoundClipStreamPlayer::SetFaderGroupTrim( float newTrim )
+{
+ radSoundVerifyAnalogVolume( newTrim );
+
+ m_FaderGroupTrim = newTrim;
+}
+
+inline void daSoundClipStreamPlayer::SetMasterTrim( float newTrim )
+{
+ radSoundVerifyAnalogVolume( newTrim );
+
+ m_MasterTrim = newTrim;
+}
+
+inline void daSoundClipStreamPlayer::CalculateCurrentTrim( void)
+{
+ float oldTrim = m_CurrentTrim;
+
+ float newTrim =
+ m_VaryingTrim *
+ m_StoppingTrim *
+ m_Trim *
+ m_GroupTrim *
+ m_FaderGroupTrim *
+ m_MasterTrim;
+
+ if ( State_Playing == m_State || State_Stopping == m_State )
+ {
+ if ( newTrim >= oldTrim )
+ {
+ float dif = newTrim - oldTrim;
+
+ if ( dif >= radSoundVolumeChangeThreshold )
+ {
+ newTrim = oldTrim + radSoundVolumeChangeThreshold;
+ }
+ }
+ else
+ {
+ float dif = oldTrim - newTrim;
+
+ if ( dif >= radSoundVolumeChangeThreshold )
+ {
+ newTrim = oldTrim - radSoundVolumeChangeThreshold;
+ }
+ }
+ }
+
+ m_CurrentTrim = newTrim;
+
+ radSoundVerifyAnalogVolume( m_CurrentTrim );
+}
+
+inline void daSoundClipStreamPlayer::CalculateCurrentPitch( void )
+{
+ float oldPitch = m_CurrentPitch;
+
+ float newPitch = m_VaryingPitch * m_Pitch;
+
+ if ( m_State == State_Playing || m_State == State_Stopping )
+ {
+ if ( newPitch > oldPitch )
+ {
+ float dif = newPitch - oldPitch;
+
+ if( dif > radSoundPitchChangeThreshold )
+ {
+ newPitch = oldPitch + radSoundVolumeChangeThreshold;
+ }
+ }
+ else
+ {
+ float dif = oldPitch - newPitch;
+
+ if( dif > radSoundPitchChangeThreshold )
+ {
+ newPitch = oldPitch - radSoundVolumeChangeThreshold;
+ }
+ }
+ }
+
+ m_CurrentPitch = newPitch;
+
+ radSoundVerifyAnalogPitch( m_CurrentPitch );
+}
+
+inline void daSoundClipStreamPlayer::SetPitch( float pitch )
+{
+ if ( pitch <= 0.0f )
+ {
+ rDebugPrintf( "AUDIO: Error, pitch set to: [%f]\n", pitch );
+
+ pitch = 0.0f;
+ }
+
+ // radSoundVerifyAnalogPitch( pitch );
+
+ m_Pitch = pitch;
+}
+
+inline void daSoundClipStreamPlayer::CalculateNewVaryingTrim( void )
+{
+ float minTrim;
+ float maxTrim;
+
+ m_pResource->GetTrimRange( &minTrim, &maxTrim );
+
+ m_VaryingTrim = ::radSoundRandMinMax( minTrim, maxTrim );
+
+ radSoundVerifyAnalogVolume( m_VaryingTrim );
+}
+
+
+inline void daSoundClipStreamPlayer::CalculateNewVaryingPitch( void )
+{
+ float minPitch;
+ float maxPitch;
+
+ m_pResource->GetPitchRange( &minPitch, &maxPitch );
+
+ m_VaryingPitch = ::radSoundRandMinMax( minPitch, maxPitch );
+
+ radSoundVerifyAnalogPitch( m_VaryingPitch );
+}
+
+inline daSoundClipStreamPlayer::State daSoundClipStreamPlayer::GetState( void )
+{
+ return m_State;
+}
+
+inline void daSoundClipStreamPlayer::SetPositionAndVelocity(
+ const radSoundVector * pPosition,
+ const radSoundVector * pVelocity )
+{
+ m_pPositionalGroup->SetPosition( (radSoundVector*) pPosition );
+ m_pPositionalGroup->SetVelocity( (radSoundVector*) pVelocity );
+}
+
+inline void daSoundClipStreamPlayer::SetMinMaxDistance( float min, float max )
+{
+ m_pPositionalGroup->SetMinMaxDistance( min, max );
+}
+
+inline bool daSoundClipStreamPlayer::IsPaused( void )
+{
+ return m_PauseCount != 0;
+}
+
+
+inline IRadSoundHalPositionalGroup * daSoundClipStreamPlayer::GetPositionalGroup( void )
+{
+ if ( m_IsPositional )
+ {
+ return m_pPositionalGroup;
+ }
+
+ return NULL;
+}
+
+
+} // Sound Namespace
+#endif //_DASOUNDPLAYER_HPP
+
diff --git a/game/code/sound/soundrenderer/soundrenderingmanager.cpp b/game/code/sound/soundrenderer/soundrenderingmanager.cpp
new file mode 100644
index 0000000..167e871
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundrenderingmanager.cpp
@@ -0,0 +1,1545 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundrenderingmanager.cpp
+//
+// Subsystem: Dark Angel - Sound Manager System
+//
+// Description: Implementation of the sound manager
+//
+// Revisions:
+// + Created October 2, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radfile.hpp>
+
+
+#include <radmusic/radmusic.hpp>
+#include <radsound.hpp>
+
+#include <radobjectlist.hpp>
+#include <radscript.hpp>
+#include <radtypeinfo.hpp>
+#include <radtypeinfoutil.hpp>
+#include <radfactory.hpp>
+
+#include <memory/srrmemory.h>
+#include <loading/loadingmanager.h>
+#include <loading/soundfilehandler.h>
+
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/soundresource.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/playermanager.h>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/soundallocatedresource.h>
+#include <sound/soundrenderer/soundconstants.h>
+#include <sound/soundclusternameenum.h>
+#include <sound/soundmanager.h>
+#include <sound/soundrenderer/soundnucleus.hpp>
+#include <sound/dialog/dialogcoordinator.h>
+#include <radobjectbtree.hpp>
+#include <radmemorymonitor.hpp>
+
+#include <pddi/pddi.hpp>
+#include <p3d/utility.hpp>
+#include <p3d/p3dtypes.hpp>
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+//#define AUDIO_FILE_PERFORMANCE_LOG
+//#define AUDIO_FILE_PERFORMANCE_SPEW
+
+bool gDaSoundStats = false;
+bool gTuneSound = false;
+
+namespace Sound {
+
+const short MAX_BTREE_NODES = 5100;
+
+radObjectBTreeNode* gpBTreeNodePool = 0;
+
+//=============================================================================
+// Debug Information
+//=============================================================================
+
+//
+// Use this if you want to debug the sound tuner
+//
+#ifndef FINAL
+#ifndef NDEBUG
+
+// This is the type of debug information to output
+#define DASOUNDMANAGER_OUTPUTDEBUGINFO
+#ifdef DASOUNDMANAGER_OUTPUTDEBUGINFO
+//static DebugInfoType sg_DebugInfoType = DEBUG_RESOURCEINFO;
+#endif //DASOUNDMANAGER_OUTPUTDEBUGINFO
+
+#endif //NDEBUG
+#endif //FINAL
+
+
+//=============================================================================
+// Macros and Defines
+//=============================================================================
+
+//
+// THe sound memory size
+//
+
+//
+// Some directories
+//
+#define SOUND_ROOT_DIR "sound"
+#define SCRIPT_DIR SOUND_ROOT_DIR"\\scripts"
+#define TYPEINFO_DIR SOUND_ROOT_DIR"\\typ"
+
+unsigned int gTotalMicrosecondsWastedParsingScripts = 0;
+
+//=============================================================================
+// Constants
+//=============================================================================
+
+//
+// Custom memory management should not be handled by the sound system!
+//
+radMemoryAllocator DAMEMORY_ALLOC_SOUND = RADMEMORY_ALLOC_DEFAULT;
+
+//
+// The object list page size for the sound objects
+//
+static const unsigned int SoundObjectsListPageSize = 32;
+
+//
+// Flag used for file callback
+//
+static const bool LastScriptTrue = true;
+static const bool LastScriptFalse = false;
+
+//=============================================================================
+// Static Variables
+//=============================================================================
+
+//
+// The sound manager singleton class
+//
+daSoundRenderingManager* daSoundRenderingManager::s_Singleton = NULL;
+
+
+//=============================================================================
+// Local data
+//=============================================================================
+
+//
+// The name of our sound resource namespace
+//
+static const char s_SoundNamespace[ ] = "SoundGlobals";
+
+//
+// The name of our tuning object namespace
+//
+static const char s_TuningNamespace[] = "TuningGlobals";
+
+//
+// Base name for our character namespaces
+//
+static const char s_CharacterNamespace[] = "CharSounds";
+
+//
+// The name of the listener object
+//
+//static const char s_TheListenerName[ ] = "TheListener";
+
+//
+// Dialog cement file names
+//
+#if defined( RAD_XBOX )
+
+static const unsigned int s_NumDialogCementFiles = 3;
+
+static const char s_EnglishDialogue[] = "dialog0?.rcf";
+static const char s_FrenchDialogue[] = "dialogf0?.rcf";
+static const char s_GermanDialogue[] = "dialogg0?.rcf";
+static const char s_SpanishDialogue[] = "dialogs0?.rcf";
+static const char s_ItalianDialogue[] = "dialogi0?.rcf";
+
+#else
+
+static const unsigned int s_NumDialogCementFiles = 1;
+
+static const char s_EnglishDialogue[] = "dialog.rcf";
+static const char s_FrenchDialogue[] = "dialogf.rcf";
+static const char s_GermanDialogue[] = "dialogg.rcf";
+static const char s_SpanishDialogue[] = "dialogs.rcf";
+static const char s_ItalianDialogue[] = "dialogi.rcf";
+
+#endif
+
+//
+// Cement libraries associated with the Dark Angel sound system
+//
+struct DaSoundCementLibraryData
+{
+ const char* m_LibraryIDString;
+ const char* m_Filename;
+ unsigned int m_CacheSize;
+};
+
+//
+// Type info
+//
+struct DaSoundTypeinfoData
+{
+ const char* m_Filename;
+};
+static DaSoundTypeinfoData s_DaSoundTypeInfo =
+{
+ TYPEINFO_DIR"\\srrtypes.typ"
+};
+
+//
+// Radscripts associated wtih the DA sound system
+//
+struct DaSoundScriptData
+{
+ const char* m_Filename;
+};
+
+//
+// IMPORTANT CHANGE: The last script files listed will have its contents go
+// into the tuning namespace, not the sound namespace. This is to ensure
+// that everything in the sound namespace is a soundResourceData object
+// to allow me to search for dialog resources without an illegal downcast
+// (stinky downcasts, hate 'em).
+//
+static DaSoundScriptData s_DaSoundScripts[ ] =
+{
+ // Character sound scripts
+ { "\\Apu.spt" },
+ { "\\Bart.spt" },
+ { "\\Homer.spt" },
+ { "\\Lisa.spt" },
+ { "\\Marge.spt" },
+
+ // Level scripts
+ { "\\suburbs.spt" },
+ { "\\downtown.spt" },
+ { "\\seaside.spt" },
+ { "\\level1.spt" },
+ { "\\level2.spt" },
+ { "\\level3.spt" },
+ { "\\level4.spt" },
+ { "\\level5.spt" },
+ { "\\level6.spt" },
+ { "\\level7.spt" },
+ { "\\minigame.spt" },
+
+ // Sound effect resources
+ { "\\frontend.spt" },
+ { "\\collide.spt" },
+ { "\\carsound.spt" },
+ { "\\World.spt" },
+ { "\\positionalSounds.spt" },
+ { "\\interactive_props.spt" },
+
+ // Dialog
+ { "\\dialog.spt" },
+ { "\\nis.spt" },
+
+ // Cars
+ { "\\bart_v.spt" },
+ { "\\apu_v.spt" },
+ { "\\snake_v.spt" },
+ { "\\homer_v.spt" },
+ { "\\famil_v.spt" },
+ { "\\gramp_v.spt" },
+ { "\\cletu_v.spt" },
+ { "\\wiggu_v.spt" },
+ { "\\empty.spt" },
+ { "\\marge_v.spt" },
+ { "\\empty.spt" },
+ { "\\empty.spt" },
+ { "\\smith_v.spt" },
+ { "\\empty.spt" },
+ { "\\empty.spt" },
+ { "\\empty.spt" },
+ { "\\zombi_v.spt" },
+ { "\\empty.spt" },
+ { "\\empty.spt" },
+ { "\\cVan.spt" },
+ { "\\compactA.spt" },
+ { "\\comic_v.spt" },
+ { "\\skinn_v.spt" },
+ { "\\cCola.spt" },
+ { "\\cSedan.spt" },
+ { "\\cPolice.spt" },
+ { "\\cCellA.spt" },
+ { "\\cCellB.spt" },
+ { "\\cCellC.spt" },
+ { "\\cCellD.spt" },
+ { "\\minivanA_v.spt" },
+ { "\\pickupA.spt" },
+ { "\\taxiA_v.spt" },
+ { "\\sportsA.spt" },
+ { "\\sportsB.spt" },
+ { "\\SUVA.spt" },
+ { "\\wagonA.spt" },
+ { "\\hbike_v.spt" },
+ { "\\burns_v.spt" },
+ { "\\honor_v.spt" },
+ { "\\cArmor.spt" },
+ { "\\cCurator.spt" },
+ { "\\cHears.spt" },
+ { "\\cKlimo.spt" },
+ { "\\cLimo.spt" },
+ { "\\cNerd.spt" },
+ { "\\frink_v.spt" },
+ { "\\cMilk.spt" },
+ { "\\cDonut.spt" },
+ { "\\bbman_v.spt" },
+ { "\\bookb_v.spt" },
+ { "\\carhom_v.spt" },
+ { "\\elect_v.spt" },
+ { "\\fone_v.spt" },
+ { "\\gramR_v.spt" },
+ { "\\moe_v.spt" },
+ { "\\mrplo_v.spt" },
+ { "\\otto_v.spt" },
+ { "\\plowk_v.spt" },
+ { "\\scorp_v.spt" },
+ { "\\willi_v.spt" },
+ { "\\sedanA.spt" },
+ { "\\sedanB.spt" },
+ { "\\cBlbart.spt" },
+ { "\\cCube.spt" },
+ { "\\cDuff.spt" },
+ { "\\cNonup.spt" },
+ { "\\lisa_v.spt" },
+ { "\\krust_v.spt" },
+ { "\\coffin.spt" },
+ { "\\hallo.spt" },
+ { "\\ship.spt" },
+ { "\\witchcar.spt" },
+ { "\\huska.spt" },
+ { "\\atv_v.spt" },
+ { "\\dune_v.spt" },
+ { "\\hype_v.spt" },
+ { "\\knigh_v.spt" },
+ { "\\mono_v.spt" },
+ { "\\oblit_v.spt" },
+ { "\\rocke_v.spt" },
+ { "\\ambul.spt" },
+ { "\\burnsarm.spt" },
+ { "\\fishtruc.spt" },
+ { "\\garbage.spt" },
+ { "\\icecream.spt" },
+ { "\\istruck.spt" },
+ { "\\nuctruck.spt" },
+ { "\\pizza.spt" },
+ { "\\schoolbu.spt" },
+ { "\\votetruc.spt" },
+ { "\\glastruc.spt" },
+ { "\\cfire_v.spt" },
+ { "\\cBone.spt" },
+ { "\\redbrick.spt" },
+
+ // Tuning
+ { "\\car_tune.spt" },
+ { "\\positionalSettings.spt" },
+ { "\\global.spt" }
+};
+
+const unsigned int NumSoundScripts = sizeof( s_DaSoundScripts ) /
+ sizeof( DaSoundScriptData );
+
+const unsigned int NUM_TUNING_SCRIPTS = 3;
+const unsigned int NUM_CHARACTER_SCRIPTS = 5;
+const unsigned int INTERACTIVE_PROPS_SCRIPT_POSITION = 21;
+const unsigned int DIALOGUE_SCRIPT_POSITION = 22;
+const unsigned int NIS_SCRIPT_POSITION = 23;
+
+//
+// Array mapping scripts to sound clusters that their sounds should
+// be loaded/unloaded with.
+//
+// IMPORTANT: this array needs to be maintained to match the scripts
+// in s_DaSoundScripts up to the first car script. After that, we
+// do it programatically (I don't think that's actually a word).
+//
+static SoundClusterName s_ScriptClusters[] =
+{
+ SC_CHAR_APU,
+ SC_CHAR_BART,
+ SC_CHAR_HOMER,
+ SC_CHAR_LISA,
+ SC_CHAR_MARGE,
+ SC_LEVEL_SUBURBS,
+ SC_LEVEL_DOWNTOWN,
+ SC_LEVEL_SEASIDE,
+ SC_LEVEL1,
+ SC_LEVEL2,
+ SC_LEVEL3,
+ SC_LEVEL4,
+ SC_LEVEL5,
+ SC_LEVEL6,
+ SC_LEVEL7,
+ SC_MINIGAME,
+ SC_ALWAYS_LOADED,
+ SC_ALWAYS_LOADED,
+ SC_ALWAYS_LOADED,
+ SC_ALWAYS_LOADED,
+ SC_INGAME,
+ SC_INGAME,
+ SC_NEVER_LOADED,
+ SC_NEVER_LOADED,
+};
+const unsigned int NumClusterNames = sizeof( s_ScriptClusters ) /
+ sizeof( SoundClusterName );
+
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundRenderingManager Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundRenderingManager::daSoundRenderingManager
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundRenderingManager::daSoundRenderingManager( )
+ :
+ radRefCount( 0 ),
+ m_pScript( NULL ),
+ m_IsInitialized( false ),
+ m_pResourceNameSpace( NULL ),
+ m_pTuningNameSpace( NULL ),
+ m_pDynaLoadManager( NULL ),
+ m_pTuner( NULL ),
+ m_pResourceManager( NULL ),
+ m_pPlayerManager( NULL ),
+ m_scriptLoadCount( 0 ),
+ m_currentLanguage( DIALOGUE_LANGUAGE_ENGLISH ),
+ m_languageSelected( false )
+{
+ unsigned int i;
+
+ // Create the singleton
+ rAssert( s_Singleton == NULL );
+ s_Singleton = this;
+
+ for( i = 0; i < NUM_CHARACTER_NAMESPACES; i++ )
+ {
+ m_pCharacterNameSpace[i] = NULL;
+ }
+
+ for( i = 0; i < NUM_SOUND_CEMENT_FILES; i++ )
+ {
+ m_soundCementFileHandles[i] = 0;
+ }
+
+ m_LastPerformanceEventTime = radTimeGetMilliseconds( );
+ ::RadSoundSetFilePerformanceCallback( & daSoundRenderingManager::FilePerformanceEvent );
+
+ radDbgWatchAddBoolean(
+ & gDaSoundStats,
+ "DaSound Stats",
+ "Sound" );
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::~daSoundRenderingManager
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundRenderingManager::~daSoundRenderingManager( )
+{
+
+ radDbgWatchDelete( & gDaSoundStats );
+ ::RadSoundSetFilePerformanceCallback( NULL );
+
+ rAssert( !m_IsInitialized );
+
+ // Clear the singleton
+ s_Singleton = NULL;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetInstance
+//=============================================================================
+// Description: Get the singleton instance of this class
+//
+//-----------------------------------------------------------------------------
+
+daSoundRenderingManager* daSoundRenderingManager::GetInstance( void )
+{
+ return s_Singleton;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::Initialize
+//=============================================================================
+// Description: Initialize the sound manager with the stuff that we don't
+// need to do if we're muted.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManager::Initialize
+(
+ void
+)
+{
+ unsigned int i;
+ char nameBuffer[50];
+ int nameLength;
+
+ //
+ // Create namespaces
+ //
+ m_pResourceNameSpace = ::radNameSpaceCreate( GetThisAllocator( ) );
+ m_pResourceNameSpace->AddRef( );
+ m_pResourceNameSpace->SetName( s_SoundNamespace );
+
+ m_pTuningNameSpace = ::radNameSpaceCreate( GetThisAllocator( ) );
+ m_pTuningNameSpace->AddRef( );
+ m_pTuningNameSpace->SetName( s_TuningNamespace );
+
+ strcpy( nameBuffer, s_CharacterNamespace );
+ nameLength = strlen( s_CharacterNamespace );
+ for( i = 0; i < NUM_CHARACTER_NAMESPACES; i++ )
+ {
+ m_pCharacterNameSpace[i] = ::radNameSpaceCreate( GetThisAllocator() );
+ rAssert( m_pCharacterNameSpace[i] != NULL );
+
+ m_pCharacterNameSpace[i]->AddRef();
+
+ //
+ // Create a unique name
+ //
+ nameBuffer[nameLength] = static_cast<char>( '0' + i );
+ nameBuffer[nameLength+1] = '\0';
+ m_pCharacterNameSpace[i]->SetName( nameBuffer );
+ }
+
+ //
+ // Spawn other elements of the sound system (some of these depend on the namespace)
+ //
+ m_pDynaLoadManager = new ( GetThisAllocator( ) ) daSoundDynaLoadManager( );
+ m_pDynaLoadManager->AddRef( );
+ m_pResourceManager = new ( GetThisAllocator( ) ) daSoundResourceManager( );
+ m_pResourceManager->AddRef( );
+ m_pPlayerManager = new ( GetThisAllocator( ) ) daSoundPlayerManager( );
+ m_pPlayerManager->AddRef( );
+
+ Sound::daSoundTunerCreate ( &m_pTuner, GetThisAllocator( ) );
+
+ m_pPlayerManager->UglyHackPostInitialize( m_pTuner );
+
+ //
+ // Register some factories and some objects. Some of these object use
+ // the spawned systems.
+ //
+ ::radFactoryRegister(
+ "daSoundResourceData",
+ (radFactoryProc*) daSoundResourceManager::CreateResourceData );
+ rAssert( GetSoundNamespace( ) != NULL );
+ rAssert( GetTuningNamespace() != NULL );
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::IsInitialized
+//=============================================================================
+// Description: Use this to pull for the end of initialization
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundRenderingManager::IsInitialized( void )
+{
+ return m_IsInitialized;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::Terminate
+//=============================================================================
+// Description: Terminate the sound manager
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManager::Terminate( void )
+{
+ unsigned int i;
+
+ // Stop all the sounds in the game
+ GetPlayerManager( )->CancelPlayers( );
+
+ // Release the namespaces, must do this before killing resource manager
+ // some of the reference counting is not per-object.
+
+ m_pResourceNameSpace->Release( );
+ m_pTuningNameSpace->Release();
+
+ for( i = 0; i < NUM_CHARACTER_NAMESPACES; i++ )
+ {
+ m_pCharacterNameSpace[i]->Release();
+ }
+
+ // Destroy the sound systems created by the initalize
+ if( IsInitialized( ) )
+ {
+ //
+ // Detach the various systems spawned on creation
+ //
+ if( m_pPlayerManager != NULL )
+ {
+ m_pPlayerManager->Release( );
+ m_pPlayerManager = NULL;
+ }
+ if( m_pResourceManager != NULL )
+ {
+ m_pResourceManager->Release( );
+ m_pResourceManager = NULL;
+ }
+ if( m_pTuner != NULL )
+ {
+ m_pTuner->Release( );
+ m_pTuner = NULL;
+ }
+ if( m_pDynaLoadManager != NULL )
+ {
+ m_pDynaLoadManager->Release( );
+ m_pDynaLoadManager = NULL;
+ }
+
+#ifndef FINAL
+ if ( gTuneSound )
+ {
+ ::radRemoteScriptTerminate( );
+ }
+#endif
+ rAssert( m_pScript == NULL );
+ ::radScriptTerminate( );
+
+ //
+ // Release the cement file
+ //
+ for( i = 0; i < NUM_SOUND_CEMENT_FILES; i++ )
+ {
+ GetLoadingManager()->UnregisterCementLibrary( m_soundCementFileHandles[i] );
+ }
+
+ // Uninitialize
+ m_IsInitialized = false;
+ }
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::Service
+//=============================================================================
+// Description: Service the Dark Angel sound system. This call should be made
+// as often as possible.
+//
+// Parameters: none
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManager::Service( void )
+{
+ //
+ // Service the radsound system
+ //
+ ::radSoundHalSystemGet( )->Service( );
+ SoundNucleusServiceClipLoad( );
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::ServiceOncePerFrame
+//=============================================================================
+// Description: Service the Dark Angel sound system. This call should be made
+// no more than once per frame or else performance may suffer.
+//
+// Parameters: none
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManager::ServiceOncePerFrame( unsigned int elapsedTime )
+{
+ //
+ // Service the radsound system
+ //
+ ::radSoundHalSystemGet( )->ServiceOncePerFrame( );
+
+ //
+ // Do nothing else until we're fully initialized
+ //
+ if( !IsInitialized( ) )
+ {
+ return;
+ }
+
+ // Service the dynamic loading system
+ if( GetDynaLoadManager( ) != NULL )
+ {
+ GetDynaLoadManager( )->ServiceOncePerFrame( );
+ }
+
+ // Service the tuner
+ if( GetTuner( ) != NULL )
+ {
+ GetTuner( )->ServiceOncePerFrame( elapsedTime );
+ }
+
+ // Service the player manager
+ if( GetPlayerManager( ) != NULL )
+ {
+ GetPlayerManager( )->ServiceOncePerFrame( );
+ }
+}
+
+//=============================================================================
+// daSoundRenderingManager::QueueCementFileRegistration
+//=============================================================================
+// Description: Set up the cement file registration with the loading manager
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::QueueCementFileRegistration()
+{
+ HeapMgr()->PushHeap (GMA_AUDIO_PERSISTENT);
+
+ //
+ // Queue requests for sound cement file registration
+ //
+ int i = s_NumDialogCementFiles;
+
+ if( !m_languageSelected )
+ {
+ registerDialogueCementFiles( s_EnglishDialogue );
+ m_languageSelected = true;
+ }
+
+#ifdef RAD_XBOX
+ //
+ // Register the music rcfs -- no localization needed.
+ //
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "music00.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "music01.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "music02.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "music03.rcf" );
+#else
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "music.rcf" );
+#endif
+
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "carsound.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "ambience.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "nis.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "soundfx.rcf" );
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( "scripts.rcf" );
+
+ HeapMgr()->PopHeap (GMA_AUDIO_PERSISTENT);
+}
+
+//=============================================================================
+// daSoundRenderingManager::SwitchDialogueCementFile
+//=============================================================================
+// Description: Switch the current language to the given language.
+//
+// Parameters: language - new language to use
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::SetLanguage( Scrooby::XLLanguage language )
+{
+ unsigned int i;
+ const char* cementFileName = s_EnglishDialogue;
+ DialogueLanguage oldLanguage = m_currentLanguage;
+
+ switch( language )
+ {
+ case Scrooby::XL_ENGLISH:
+ cementFileName = s_EnglishDialogue;
+ m_currentLanguage = DIALOGUE_LANGUAGE_ENGLISH;
+ break;
+
+ //**************************************************************************
+ // TEMPORARY: all dialog is English until we actually get localized dialogue
+ //**************************************************************************
+ case Scrooby::XL_FRENCH:
+ cementFileName = s_FrenchDialogue;
+ m_currentLanguage = DIALOGUE_LANGUAGE_FRENCH;
+ break;
+
+ case Scrooby::XL_GERMAN:
+ cementFileName = s_GermanDialogue;
+ m_currentLanguage = DIALOGUE_LANGUAGE_GERMAN;
+ break;
+
+ case Scrooby::XL_SPANISH:
+ cementFileName = s_SpanishDialogue;
+ m_currentLanguage = DIALOGUE_LANGUAGE_SPANISH;
+ break;
+
+ default:
+ rAssertMsg( false, "Language not supported by sound system" );
+ break;
+ }
+
+ if( m_currentLanguage == oldLanguage )
+ {
+ //
+ // Nothing needs to be done
+ //
+ return;
+ }
+
+ for( i = 0; i < s_NumDialogCementFiles; i++ )
+ {
+ GetLoadingManager()->UnregisterCementLibrary( m_soundCementFileHandles[i] );
+ }
+
+ registerDialogueCementFiles( cementFileName );
+
+ m_languageSelected = true;
+}
+
+//=============================================================================
+// daSoundRenderingManager::QueueRadscriptFileLoads
+//=============================================================================
+// Description: Set up the RadScript file loads with the loading manager
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::QueueRadscriptFileLoads()
+{
+ HeapMgr()->PushHeap (GMA_AUDIO_PERSISTENT);
+
+ unsigned int i;
+ char filename[100];
+ const char* scriptName;
+
+ //
+ // Queue up the RadScript file loading requests
+ //
+ GetLoadingManager()->AddRequest( FILEHANDLER_SOUND, s_DaSoundTypeInfo.m_Filename, GMA_AUDIO_PERSISTENT );
+
+ for( i = 0; i < NumSoundScripts; i++ )
+ {
+ //
+ // Hack!
+ //
+ // Oops. Need to load the correct dialogue script depending on which language has been
+ // selected
+ //
+ if( i == DIALOGUE_SCRIPT_POSITION )
+ {
+ switch( m_currentLanguage )
+ {
+ case DIALOGUE_LANGUAGE_ENGLISH:
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+
+ case DIALOGUE_LANGUAGE_FRENCH:
+ scriptName = "\\dialogfr.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_GERMAN:
+ scriptName = "\\dialogge.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_SPANISH:
+ scriptName = "\\dialogsp.spt";
+ break;
+
+ default:
+ rAssert( false );
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+ }
+ }
+ else if( i == NIS_SCRIPT_POSITION )
+ {
+ switch( m_currentLanguage )
+ {
+ case DIALOGUE_LANGUAGE_ENGLISH:
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+
+ case DIALOGUE_LANGUAGE_FRENCH:
+ scriptName = "\\nisfr.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_GERMAN:
+ scriptName = "\\nisge.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_SPANISH:
+ scriptName = "\\nissp.spt";
+ break;
+
+ default:
+ rAssert( false );
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+ }
+ }
+ else if( i == INTERACTIVE_PROPS_SCRIPT_POSITION )
+ {
+ switch( m_currentLanguage )
+ {
+ case DIALOGUE_LANGUAGE_ENGLISH:
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+
+ case DIALOGUE_LANGUAGE_FRENCH:
+ scriptName = "\\interactive_propsfr.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_GERMAN:
+ scriptName = "\\interactive_propsge.spt";
+ break;
+
+ case DIALOGUE_LANGUAGE_SPANISH:
+ scriptName = "\\interactive_propssp.spt";
+ break;
+
+ default:
+ rAssert( false );
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ break;
+ }
+ }
+ else
+ {
+ scriptName = s_DaSoundScripts[i].m_Filename;
+ }
+ sprintf( filename, "%s%s", SCRIPT_DIR, scriptName );
+ GetLoadingManager()->AddRequest( FILEHANDLER_SOUND, filename, GMA_AUDIO_PERSISTENT );
+ }
+
+ HeapMgr()->PopHeap (GMA_AUDIO_PERSISTENT);
+}
+
+//=============================================================================
+// daSoundRenderingManager::LoadTypeInfoFile
+//=============================================================================
+// Description: Start the loading of the type info
+//
+// Parameters: filename - name of type info file
+// fileHandler - completion callback object
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::LoadTypeInfoFile( const char* filename, SoundFileHandler* fileHandler )
+{
+ m_soundFileHandler = fileHandler;
+
+ IRadTypeInfoSystem* pTypeInfoSystem = ::radTypeInfoSystemGet( );
+ rAssert( pTypeInfoSystem != NULL );
+ pTypeInfoSystem->AddRef( );
+ pTypeInfoSystem->LoadTypeInfo
+ (
+ gTuneSound ? GMA_AUDIO_PERSISTENT : GMA_TEMP,
+ filename,
+ daSoundRenderingManager::TypeInfoComplete,
+ (void*)false
+ );
+ pTypeInfoSystem->Release( );
+}
+
+//=============================================================================
+// daSoundRenderingManager::LoadScriptFile
+//=============================================================================
+// Description: Start the loading of a RadScript script file
+//
+// Parameters: filename - name of script file
+// fileHandler - completion callback object
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::LoadScriptFile( const char* filename, SoundFileHandler* fileHandler )
+{
+ const bool* lastScript;
+
+ m_soundFileHandler = fileHandler;
+
+ // Create the script object, if it hasn't been done yet
+ if( m_pScript == NULL )
+ {
+ m_pScript = ::radScriptCreateScript
+ (
+ RADMEMORY_ALLOC_TEMP
+ );
+ rAssert( m_pScript != NULL );
+ m_pScript->AddRef( );
+ }
+
+ m_pScript->SetAllocator( GetThisAllocator( ) );
+
+ //
+ // Pass a flag indicating if this is the last script as user info
+ //
+ if( m_scriptLoadCount < NUM_CHARACTER_SCRIPTS )
+ {
+ m_pScript->SetContext( GetCharacterNamespace( m_scriptLoadCount ) );
+ }
+ else if( m_scriptLoadCount >= NumSoundScripts - NUM_TUNING_SCRIPTS )
+ {
+ m_pScript->SetContext( GetTuningNamespace( ) );
+ }
+ else
+ {
+ m_pScript->SetContext( GetSoundNamespace( ) );
+ }
+
+ if( m_scriptLoadCount == NumSoundScripts - 1 )
+ {
+ lastScript = &LastScriptTrue;
+ }
+ else
+ {
+ lastScript = &LastScriptFalse;
+ }
+
+ // Load the script
+ m_pScript->Load
+ (
+ filename,
+ daSoundRenderingManager::ScriptComplete,
+ (void*)lastScript,
+ RADMEMORY_ALLOC_TEMP
+ );
+ }
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetSoundNamespace
+//=============================================================================
+// Description: Get the sound resource namespace
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the sound resource namespace
+//
+//-----------------------------------------------------------------------------
+
+IRadNameSpace* daSoundRenderingManager::GetSoundNamespace( void )
+{
+ return m_pResourceNameSpace;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetTuningNamespace
+//=============================================================================
+// Description: Get the sound tuning namespace
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the sound tuning namespace
+//
+//-----------------------------------------------------------------------------
+
+IRadNameSpace* daSoundRenderingManager::GetTuningNamespace( void )
+{
+ return m_pTuningNameSpace;
+}
+
+//=============================================================================
+// daSoundRenderingManager::GetCharacterNamespace
+//=============================================================================
+// Description: Get the specified character namespace
+//
+// Parameters: index - index into list of namespaces
+//
+// Return: Pointer to the desired namespace
+//
+//=============================================================================
+IRadNameSpace* daSoundRenderingManager::GetCharacterNamespace( unsigned int index )
+{
+ rAssert( index < NUM_CHARACTER_NAMESPACES );
+
+ return( m_pCharacterNameSpace[index] );
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetTheListener
+//=============================================================================
+// Description: Get the listener
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the listener
+//
+//-----------------------------------------------------------------------------
+
+IRadSoundHalListener* daSoundRenderingManager::GetTheListener( void )
+{
+ return ::radSoundHalListenerGet( );
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetDynaLoadManager
+//=============================================================================
+// Description: Get the dynamic loading manager
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the dynamic loading manager
+//
+//-----------------------------------------------------------------------------
+
+daSoundDynaLoadManager* daSoundRenderingManager::GetDynaLoadManager( void )
+{
+ return m_pDynaLoadManager;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetDialogManager
+//=============================================================================
+// Description: Get the dialog manager
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the dialog manager
+//
+//-----------------------------------------------------------------------------
+
+/*IDaSoundDialogManager* daSoundRenderingManager::GetDialogManager( void )
+{
+ return m_pDialogManager;
+}*/
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetTuner
+//=============================================================================
+// Description: Get the tuner
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the tuner
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundTuner* daSoundRenderingManager::GetTuner( void )
+{
+ return m_pTuner;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetObjectDataLibrary
+//=============================================================================
+// Description: Get the object data library
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the object data library
+//
+//-----------------------------------------------------------------------------
+
+/*IDaSoundObjectDataLibrary* daSoundRenderingManager::GetObjectDataLibrary( void )
+{
+ return m_pObjectDataLibrary;
+}*/
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetResourceManager
+//=============================================================================
+// Description: Get the resource manager
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the resource manager
+//
+//-----------------------------------------------------------------------------
+
+daSoundResourceManager* daSoundRenderingManager::GetResourceManager( void )
+{
+ return m_pResourceManager;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::GetPlayerManager
+//=============================================================================
+// Description: Get the player manager
+//
+// Parameters: none
+//
+// Returns: Returns a pointer to the player manager
+//
+//-----------------------------------------------------------------------------
+
+daSoundPlayerManager* daSoundRenderingManager::GetPlayerManager( void )
+{
+ return m_pPlayerManager;
+}
+
+//=============================================================================
+// Function: daSoundRenderingManager::TypeInfoComplete
+//=============================================================================
+// Description: Asynchronous file load complete callback. Redundant, but
+// RadScript requires a static function for callback
+//
+// Parameters: pUserData - some user data to pass on
+//
+// Note: This relies on the sound manager being a singleton
+//
+//-----------------------------------------------------------------------------
+void daSoundRenderingManager::TypeInfoComplete( void* pUserData )
+{
+ rAssert( s_Singleton != NULL );
+ s_Singleton->ProcessTypeInfo( pUserData );
+}
+
+//=============================================================================
+// daSoundRenderingManager::ScriptComplete
+//=============================================================================
+// Description: Asynchronous file load complete callback. Redundant, but
+// RadScript requires a static function for callback
+//
+// Parameters: pUserData - some user data to pass on
+//
+// Note: This relies on the sound manager being a singleton
+//
+//=============================================================================
+void daSoundRenderingManager::ScriptComplete( void* pUserData )
+{
+ rAssert( s_Singleton != NULL );
+ s_Singleton->ProcessScript( pUserData );
+}
+
+//=============================================================================
+// daSoundRenderingManager::SoundObjectCreated
+//=============================================================================
+// Description: RadScript callback function called when an object is created.
+// We use it to register the object for loading/unloading
+//
+// Parameters: objName - name of sound resource to load/unload
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::SoundObjectCreated( const char* objName, IRefCount* obj )
+{
+ bool added;
+ rAssert( NULL != dynamic_cast< daSoundResourceData*>( obj ) );
+ daSoundResourceData* resourceObj = static_cast<daSoundResourceData*>( obj );
+
+ //
+ // We only need to preload clips
+ //
+ if( resourceObj->GetStreaming() == false )
+ {
+ added = GetSoundManager()->GetSoundLoader()->AddResourceToCurrentCluster( objName );
+ rAssert( added );
+ }
+ else
+ {
+ volatile int x = 4;
+ }
+}
+
+//=============================================================================
+// daSoundRenderingManager::ProcessTypeInfo
+//=============================================================================
+// Description: Asynchronous file load complete callback.
+//
+// Parameters: ( void* pUserData )
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::ProcessTypeInfo( void* pUserData )
+{
+ m_soundFileHandler->LoadCompleted();
+}
+
+//=============================================================================
+// daSoundRenderingManager::ScriptComplete
+//=============================================================================
+// Description: Asynchronous script load callback
+//
+// Parameters: pUserData - some user data to pass on
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::ProcessScript( void* pUserData )
+{
+ ScriptObjCreateCallback* callbackPtr = NULL;
+ const bool* lastScript = reinterpret_cast<const bool*>( pUserData );
+
+ rAssert( m_pScript != NULL );
+
+ //
+ // Tell the sound manager which sound cluster we'll associate
+ // with the resources in this script
+ //
+ if( m_scriptLoadCount < NumSoundScripts - NUM_TUNING_SCRIPTS )
+ {
+ callbackPtr = SoundObjectCreated;
+
+ if( m_scriptLoadCount < NumClusterNames )
+ {
+ GetSoundManager()->GetSoundLoader()->SetCurrentCluster( s_ScriptClusters[m_scriptLoadCount] );
+ }
+ else
+ {
+ GetSoundManager()->GetSoundLoader()->SetCurrentCluster( static_cast<SoundClusterName>(SC_CAR_BASE + m_scriptLoadCount - NumClusterNames) );
+ }
+ }
+
+ // Execute script file
+
+ unsigned int start = radTimeGetMicroseconds( );
+ m_pScript->Run( callbackPtr );
+ unsigned int finished = radTimeGetMicroseconds( );
+ unsigned int dif = finished - start;
+
+ gTotalMicrosecondsWastedParsingScripts += dif;
+
+ if ( dif > 1000 )
+ {
+ //rTunePrintf( "\n\nAUDIO: Holy !@#$ script took [%d] ms to parse\n\n", dif / 1000 );
+ }
+
+ m_pScript->UnLoad( );
+
+ if( *lastScript )
+ {
+ rReleasePrintf( "\n\nAUDIO: Wasted [%d] ms of load time parsing scripts\n\n", gTotalMicrosecondsWastedParsingScripts / 1000);
+
+ // Free the script
+ rAssert( m_pScript != NULL );
+ m_pScript->Release( );
+ m_pScript = NULL;
+
+ //
+ // At this point the sound resources should be finalized, lets lock them down
+ // and then intialize some systems.
+ //
+
+ GetTuner( )->Initialize( );
+
+ // Initialize the dialog system
+
+ SoundManager::GetInstance( )->m_dialogCoordinator->Initialize( );
+
+ Sound::daSoundResourceManager::GetInstance( )->SetResourceLockdown( true );
+
+ m_pPlayerManager->Initialize( );
+
+ // We are now fully initialized
+ m_IsInitialized = true;
+
+ if ( ! gTuneSound )
+ {
+ radScriptUnLoadAllTypeInfo( );
+ }
+ }
+
+ ++m_scriptLoadCount;
+
+ m_soundFileHandler->LoadCompleted();
+}
+
+
+//=============================================================================
+// Public Functions
+//=============================================================================
+
+//=============================================================================
+// Function: ::daSoundRenderingManagerCreate
+//=============================================================================
+// Description: Create the sound manager
+//
+// Parameters: allocator - the memory allocator to use
+//
+// Preconditions:
+// In order to manage memory fragmentation issues, and to
+// allow a timely intialization of sound, this command should
+// be executed before any frontend or ingame structures have
+// been created.
+//
+// Postconditions:
+// This will generate any singleton classes related to the Dark
+// Angel sound system. It will register any appropriate
+// cement files to give access to sound, and it will parse
+// any sound scripts so that the sound system will be ready
+// to start recieving sound events.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManagerCreate( radMemoryAllocator allocator )
+{
+ rAssert( daSoundRenderingManager::GetInstance( ) == NULL );
+
+ // Create the sound manager
+ daSoundRenderingManager* pSoundManager = new ( allocator ) daSoundRenderingManager( );
+ rAssert( pSoundManager != NULL );
+ pSoundManager->AddRef( );
+ rAssert( pSoundManager == daSoundRenderingManager::GetInstance( ) );
+
+ rDebugChannelInitialize( GMA_MUSIC );
+ //rDebugChannelEnable( radmusic::debug_channel );
+
+ //
+ // Initialize some usefull systems
+ //
+ ::radScriptInitialize( allocator );
+#ifndef FINAL
+ if( gTuneSound )
+ {
+ ::radRemoteScriptInitialize( allocator );
+ }
+#endif
+
+ gpBTreeNodePool = (radObjectBTreeNode*) radMemoryAlloc(
+ allocator,
+ MAX_BTREE_NODES * sizeof( radObjectBTreeNode ) );
+
+ ::memset( gpBTreeNodePool, 0, MAX_BTREE_NODES * sizeof( radObjectBTreeNode ) );
+
+ radMemoryMonitorIdentifyAllocation( gpBTreeNodePool, "Global BTree Node Pool" );
+
+ radObjectBTree::Initialize( gpBTreeNodePool, MAX_BTREE_NODES );
+ // Initialize
+
+ SoundNucleusInitialize( allocator );
+}
+
+//=============================================================================
+// Function: ::daSoundRenderingManagerGet
+//=============================================================================
+// Description: Get a pointer to the sound manager singleton class
+//
+//-----------------------------------------------------------------------------
+
+daSoundRenderingManager* daSoundRenderingManagerGet( void )
+{
+ rAssert( daSoundRenderingManager::GetInstance( ) != NULL );
+ return
+ (
+ static_cast< daSoundRenderingManager* >( daSoundRenderingManager::GetInstance( ) )
+ );
+}
+
+void daSoundRenderingManager::FilePerformanceEvent(
+ bool start,
+ const char * pFile,
+ unsigned int bytes )
+{
+ daSoundRenderingManager * pThis = daSoundRenderingManager::GetInstance( );
+
+ unsigned int now = radTimeGetMilliseconds( );
+
+ if ( start )
+ {
+ pThis->m_LastPerformanceEventTime = now;
+
+ if ( CommandLineOptions::Get( CLO_AUDIO_LOADING_SPEW ) )
+ {
+ rTunePrintf( "<<START>> Async Loading: (Audio) %s Bytes: 0x%x\n", pFile, bytes );
+ }
+ }
+ else
+ {
+ unsigned int dif = now - pThis->m_LastPerformanceEventTime;
+
+ if ( CommandLineOptions::Get( CLO_AUDIO_LOADING_SPEW ) )
+ {
+ rTunePrintf( "<< END >> Async Loading: (Audio) %s (%d msecs)\n", pFile, dif );
+ }
+ }
+}
+
+void daSoundRenderingManager::Render( void )
+{
+ if ( gDaSoundStats )
+ {
+ m_pPlayerManager->Render( );
+ }
+}
+
+//=============================================================================
+// Function: ::daSoundRenderingManagerTerminate
+//=============================================================================
+// Description: Terminate the sound system
+//
+//-----------------------------------------------------------------------------
+
+void daSoundRenderingManagerTerminate( void )
+{
+ rAssert( daSoundRenderingManager::GetInstance( ) != NULL );
+ daSoundRenderingManager::GetInstance( )->Terminate( );
+ daSoundRenderingManager::GetInstance( )->Release( );
+ rAssert( daSoundRenderingManager::GetInstance( ) == NULL );
+
+ SoundNucleusTerminate( );
+}
+
+//******************************************************************************
+//
+// Private Member Functions
+//
+//******************************************************************************
+
+//=============================================================================
+// daSoundRenderingManager::registerDialogueCementFiles
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( const char* cementFilename )
+//
+// Return: void
+//
+//=============================================================================
+void daSoundRenderingManager::registerDialogueCementFiles( const char* cementFilename )
+{
+#if defined( RAD_XBOX )
+ char dialogNameBuffer[ 16 ];
+ int i = 0;
+
+ strcpy( dialogNameBuffer, cementFilename );
+ char* numberPosition = strchr( dialogNameBuffer, '?' );
+ for ( unsigned int j = 0; j < s_NumDialogCementFiles; j++ )
+ {
+ *numberPosition = j + '0';
+ m_soundCementFileHandles[i++] = GetLoadingManager()->RegisterCementLibrary( dialogNameBuffer );
+ }
+#else
+ rAssert( s_NumDialogCementFiles == 1 );
+ m_soundCementFileHandles[0] = GetLoadingManager()->RegisterCementLibrary( cementFilename );
+#endif
+}
+
+} // Sound Namespace
+
diff --git a/game/code/sound/soundrenderer/soundrenderingmanager.h b/game/code/sound/soundrenderer/soundrenderingmanager.h
new file mode 100644
index 0000000..a77ac7c
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundrenderingmanager.h
@@ -0,0 +1,187 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundrenderingmanager.hpp
+//
+// Subsystem: Dark Angel - Sound Rendering Manager System
+//
+// Description: Description of the DA sound manager
+//
+// Revisions:
+// + Created October 2, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _SOUNDRENDERINGMANAGER_HPP
+#define _SOUNDRENDERINGMANAGER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radfile.hpp>
+#include <enums.h>
+#include <radsound.hpp>
+#include <radscript.hpp>
+
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/playermanager.h>
+
+//=============================================================================
+// Global namespace forward declarations
+//=============================================================================
+
+
+class SoundFileHandler;
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundRenderingManager;
+class daSoundDynaLoadManager;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+static const unsigned int NUM_CHARACTER_NAMESPACES = 5;
+
+//
+// Language enumeration
+//
+enum DialogueLanguage
+{
+ DIALOGUE_LANGUAGE_ENGLISH,
+ DIALOGUE_LANGUAGE_FRENCH,
+ DIALOGUE_LANGUAGE_GERMAN,
+ DIALOGUE_LANGUAGE_SPANISH
+};
+
+//
+// The sound manger
+//
+class daSoundRenderingManager : public radRefCount
+{
+public:
+ IMPLEMENT_REFCOUNTED( "daSoundManager" );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundRenderingManager( );
+ virtual ~daSoundRenderingManager( );
+
+ //
+ // Get the singleton
+ //
+ static daSoundRenderingManager* GetInstance( void );
+
+ //
+ // Terminate
+ //
+ void Terminate( void );
+
+ void QueueCementFileRegistration();
+ void QueueRadscriptFileLoads();
+ void LoadTypeInfoFile( const char* filename, SoundFileHandler* fileHandler );
+ void LoadScriptFile( const char* filename, SoundFileHandler* fileHandler );
+
+ void SetLanguage( Scrooby::XLLanguage language );
+
+ void ProcessTypeInfo( void* pUserData );
+ void ProcessScript( void* pUserData );
+
+ //
+ // IDaSoundManager
+ //
+ void Initialize( void );
+ bool IsInitialized( void );
+ void Service( void );
+ void ServiceOncePerFrame( unsigned int elapsedTime );
+ void Render( void );
+
+ IRadNameSpace* GetSoundNamespace( void );
+ IRadNameSpace* GetTuningNamespace( void );
+ IRadNameSpace* GetCharacterNamespace( unsigned int index );
+ IRadSoundHalListener* GetTheListener( void );
+
+ daSoundDynaLoadManager* GetDynaLoadManager( void );
+ IDaSoundTuner* GetTuner( void );
+ daSoundResourceManager* GetResourceManager( void );
+ daSoundPlayerManager* GetPlayerManager( void );
+
+protected:
+
+ static void TypeInfoComplete( void* pUserData );
+ static void ScriptComplete( void* pUserData );
+ static void SoundObjectCreated( const char* objName, IRefCount* obj );
+
+private:
+
+ static void FilePerformanceEvent( bool start, const char * pFile, unsigned int bytes );
+
+ void registerDialogueCementFiles( const char* cementFilename );
+
+ // The singleton instance
+ static daSoundRenderingManager* s_Singleton;
+
+ IRadScript* m_pScript;
+ bool m_IsInitialized;
+
+ //
+ // Our namespaces
+ //
+ IRadNameSpace* m_pResourceNameSpace;
+ IRadNameSpace* m_pTuningNameSpace;
+
+ IRadNameSpace* m_pCharacterNameSpace[NUM_CHARACTER_NAMESPACES];
+
+ //
+ // Store the various related systems
+ //
+ daSoundDynaLoadManager* m_pDynaLoadManager;
+ IDaSoundTuner* m_pTuner;
+ daSoundResourceManager* m_pResourceManager;
+ daSoundPlayerManager* m_pPlayerManager;
+
+ //
+ // Loading system callback
+ //
+ SoundFileHandler* m_soundFileHandler;
+
+ //
+ // Cement file handles, in case we want to release them
+ //
+#ifdef RAD_XBOX
+ static const unsigned int NUM_SOUND_CEMENT_FILES = 12;
+#else
+ static const unsigned int NUM_SOUND_CEMENT_FILES = 7;
+#endif
+ unsigned int m_soundCementFileHandles[NUM_SOUND_CEMENT_FILES];
+
+ //
+ // Script loading count, so we can tell which namespace to put stuff in
+ //
+ unsigned int m_scriptLoadCount;
+
+ unsigned int m_LastPerformanceEventTime;
+
+ //
+ // Language
+ //
+ DialogueLanguage m_currentLanguage;
+ bool m_languageSelected;
+};
+
+} // Sound Namespace
+
+#endif //_SOUNDRENDERINGMANAGER_HPP
diff --git a/game/code/sound/soundrenderer/soundresource.cpp b/game/code/sound/soundrenderer/soundresource.cpp
new file mode 100644
index 0000000..ff39f81
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundresource.cpp
@@ -0,0 +1,555 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundresource.cpp
+//
+// Subsystem: Dark Angel - Sound resources
+//
+// Description: Implements sound resources
+//
+// Modification History:
+// + Created October 11, 2001 -- aking
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/soundplayer.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/playermanager.h>
+
+#include <sound/soundrenderer/soundresourcemanager.h>
+
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/soundresource.h>
+
+#include <sound/soundmanager.h>
+#include <memory/srrmemory.h>
+
+//=============================================================================
+// Static Variables
+//=============================================================================
+
+//=============================================================================
+// daSoundResourceData Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundResourceData::daSoundResourceData
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+
+inline unsigned char vol_f_to_c( float f )
+{
+ return (unsigned char) radSoundFloatToUInt( f * 255.0f );
+}
+
+inline float vol_c_to_f( unsigned char c )
+{
+ return radSoundUIntToFloat( (unsigned int) c ) / 255.0f;
+}
+
+inline unsigned short pitch_f_to_s( float f )
+{
+ return (unsigned short) radSoundFloatToUInt( f * 6553.0f );
+}
+
+inline float pitch_s_to_f( unsigned short c )
+{
+ return radSoundUIntToFloat( (unsigned short) c ) / 6553.0f;
+}
+
+const int FLAG_LOOPING = 1 << 0;
+const int FLAG_STREAMING = 1 << 1;
+
+daSoundResourceData::daSoundResourceData( )
+{
+ m_NumFiles = 0;
+
+ m_MinTrim = vol_f_to_c( 1.0f );
+ m_MaxTrim = vol_f_to_c( 1.0f );
+ m_MinPitch = pitch_f_to_s( 1.0f );
+ m_MaxPitch = pitch_f_to_s( 1.0f );
+
+ m_SoundGroup = Sound::MASTER;
+ m_CaptureCount = 0;
+
+ m_Flags = 0;
+
+ m_pFileIds = 0;
+}
+
+//=============================================================================
+// Function: daSoundResourceData::~daSoundResourceData
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundResourceData::~daSoundResourceData( )
+{
+
+}
+
+//=============================================================================
+// Function: daSoundResourceData::AddFilename
+//=============================================================================
+// Description: Add a file to this resource
+//
+// Parameters: newFileName - the new file name
+// trim - the trim for this file
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::AddFilename
+(
+ const char* newFileName,
+ float trim
+)
+{
+ rAssert( false == Sound::daSoundResourceManager::GetInstance( )->GetResourceLockdown( ) );
+
+ // very lazy indeed.
+
+ if ( m_pFileIds == 0 )
+ {
+ m_pFileIds = (FileId*) radMemoryAlloc( GMA_DEFAULT, sizeof( FileId ) * DASound_MaxNumSoundResourceFiles );
+ }
+
+ rAssert( Sound::daSoundResourceManager::GetInstance( ) != NULL );
+ rAssert( m_NumFiles < DASound_MaxNumSoundResourceFiles );
+
+ m_pFileIds[ m_NumFiles ].m_pName = (char*) radMemoryAlloc( GMA_DEFAULT, strlen( newFileName ) + 1 );
+ strcpy( m_pFileIds[ m_NumFiles ].m_pName, newFileName );
+ m_NumFiles++;
+}
+
+
+//=============================================================================
+// Function: daSoundResourceData::GetFilenameAt
+//=============================================================================
+// Description: Get the resource file at the given index
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::GetFileNameAt( unsigned int index, char* buffer, unsigned int max )
+{
+ rTuneAssert( false == Sound::daSoundResourceManager::GetInstance( )->GetResourceLockdown( ) );
+ rTuneAssert( index < m_NumFiles );
+
+ strcpy( buffer, m_pFileIds[ index ].m_pName );
+}
+
+void daSoundResourceData::GetFileKeyAt( unsigned int index, char* buffer, unsigned int max )
+{
+ rTuneAssert( index < m_NumFiles );
+ KeyToStringKey32( buffer, m_pFileIds[ index ].m_Key );
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetPitchRange
+//=============================================================================
+// Description: Set the pitch range for this resource
+//
+// Parameters: minPitch - the minimum pitch value
+// maxPitch - the maximum pitch value
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetPitchRange
+(
+ Sound::daPitchValue minPitch,
+ Sound::daPitchValue maxPitch
+)
+{
+ m_MinPitch = pitch_f_to_s( minPitch );
+ m_MaxPitch = pitch_f_to_s( maxPitch );
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetPitchRange
+//=============================================================================
+// Description: Get the pitch range for this resource
+//
+// Parameters: *MinPitch - (out )the minimum pitch value
+// *MaxPitch - (out) the maximum pitch value
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::GetPitchRange
+(
+ Sound::daPitchValue* pMinPitch,
+ Sound::daPitchValue* pMaxPitch
+)
+{
+ if( pMinPitch != NULL )
+ {
+ *pMinPitch = pitch_s_to_f( m_MinPitch );
+ }
+ if( pMaxPitch != NULL )
+ {
+ *pMaxPitch = pitch_s_to_f( m_MaxPitch );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetTrimRange
+//=============================================================================
+// Description: Set the trim range for this resource
+//
+// Parameters: minTrim - the minimum trim value
+// maxTrim - the maximum trim value
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetTrimRange
+(
+ float minTrim,
+ float maxTrim
+)
+{
+ m_MinTrim = vol_f_to_c( minTrim );
+ m_MaxTrim = vol_f_to_c( maxTrim );
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetTrim
+//=============================================================================
+// Description: Set the trim for this resource
+//
+// Parameters: trim - the trim value
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetTrim
+(
+ float trim
+)
+{
+ m_MinTrim = vol_f_to_c( trim );
+ m_MaxTrim = vol_f_to_c( trim );
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetTrimRange
+//=============================================================================
+// Description: Get the trim range for this resource
+//
+// Parameters: *MinTrim - (out )the minimum trim value
+// *MaxTrim - (out) the maximum trim value
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::GetTrimRange
+(
+ float* pMinTrim,
+ float* pMaxTrim
+)
+{
+ if( pMinTrim != NULL )
+ {
+ *pMinTrim = vol_c_to_f( m_MinTrim );
+ }
+ if( pMaxTrim != NULL )
+ {
+ *pMaxTrim = vol_c_to_f( m_MaxTrim );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetStreaming
+//=============================================================================
+// Description: Set this as a streaming resource
+//
+// Parameters: streaming - should streaming be on or off
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetStreaming( bool streaming )
+{
+ if( streaming )
+ {
+ m_Flags |= FLAG_STREAMING;
+ }
+ else
+ {
+ m_Flags &= ~FLAG_STREAMING;
+ }
+
+ if( IsCaptured( ) )
+ {
+ rReleaseString
+ (
+ "Streaming will not immediately "
+ "affect a captured resource\n"
+ );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetStreaming
+//=============================================================================
+// Description: Get whether or not this is a streaming resource
+//
+// Parameters: none
+//
+// Returns: Returns true if this resource streams, otherwise false
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundResourceData::GetStreaming( void )
+{
+ return ( m_Flags & FLAG_STREAMING ) != 0;
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetLooping
+//=============================================================================
+// Description: Set this as a looping resource
+//
+// Parameters: looping - should looping be on or off
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetLooping( bool looping )
+{
+ if( looping )
+ {
+ m_Flags |= FLAG_LOOPING;
+ }
+ else
+ {
+ m_Flags &= ~FLAG_LOOPING;
+ }
+
+ if( IsCaptured( ) )
+ {
+ rReleaseString
+ (
+ "Looping will not immediately "
+ "affect a captured resource\n"
+ );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetLooping
+//=============================================================================
+// Description: Get whether or not this is a looping resource
+//
+// Parameters: none
+//
+// Returns: Returns true if this resource loops, otherwise false
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundResourceData::GetLooping( void )
+{
+ return ( m_Flags & FLAG_LOOPING ) != 0;
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetType
+//=============================================================================
+// Description: Find out what kind of resource this is
+//
+// Parameters: none
+//
+// Returns: Returns the type of resource
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundResource::Type daSoundResourceData::GetType
+(
+ void
+)
+{
+ IDaSoundResource::Type resourceType = UNKNOWN;
+
+ if( GetStreaming( ) )
+ {
+ resourceType = STREAM;
+ }
+ else
+ {
+ resourceType = CLIP;
+ }
+
+ return resourceType;
+}
+
+//=============================================================================
+// Function: daSoundResourceData::SetSoundGroup
+//=============================================================================
+// Description: Set the sound group that this resource belongs to
+//
+// Parameters: soundGroup - the sound group to associate with this resource
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::SetSoundGroup
+(
+ Sound::daSoundGroup soundGroup
+)
+{
+ m_SoundGroup = soundGroup;
+}
+
+//=============================================================================
+// Function: daSoundResourceData::GetSoundGroup
+//=============================================================================
+// Description: Get the sound group that this resource belongs to
+//
+// Parameters: none
+//
+// Returns: Returns the sound group that this resource belongs to.
+//
+//-----------------------------------------------------------------------------
+
+Sound::daSoundGroup daSoundResourceData::GetSoundGroup( void )
+{
+ return static_cast<Sound::daSoundGroup>(m_SoundGroup);
+}
+
+//=============================================================================
+// Function: daSoundResourceData::CaptureResource
+//=============================================================================
+// Description: Capture this resource
+//
+// Parameters: none
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::CaptureResource( void )
+{
+ rAssert( Sound::daSoundResourceManager::GetInstance( ) != NULL );
+ bool wasCaptured = IsCaptured( );
+ ++m_CaptureCount;
+ if( !wasCaptured )
+ {
+ // Inform the resource manager
+ Sound::daSoundResourceManager::GetInstance( )->
+ AllocateResource( this );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::IsCaptured
+//=============================================================================
+// Description: Is this resource captured?
+//
+// Parameters: none
+//
+// Returns: Returns true if the resource is captured, otherwise false.
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundResourceData::IsCaptured( void )
+{
+ return( m_CaptureCount > 0 );
+}
+
+//=============================================================================
+// Function: daSoundResourceData::ReleaseResource
+//=============================================================================
+// Description: Release this resource
+//
+// Parameters: none
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::ReleaseResource( void )
+{
+ rAssertMsg( m_CaptureCount > 0, "Cannot release uncaptured resource" );
+ rAssert( Sound::daSoundResourceManager::GetInstance( ) != NULL );
+
+ --m_CaptureCount;
+ if( m_CaptureCount == 0 )
+ {
+ // Inform the resource manager
+ Sound::daSoundResourceManager::GetInstance( )->
+ DeallocateResource( this );
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceData::ReleaseResource
+//=============================================================================
+// Description: Plays this resource
+//
+// Notes: !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// THIS IS FOR COMPOSERS ONLY. DO NOT USE IT.
+// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceData::Play( void )
+{
+ if( Sound::daSoundRenderingManagerGet( )->GetResourceManager( )->GetResourceLockdown( ) )
+ {
+ // Play it
+ // DO NOT USE THIS COMMAND IF YOU ARE NOT IN RADTUNER / SOUNDTUNER / etc.
+ Sound::daSoundClipStreamPlayer* pPlayer = NULL;
+ Sound::daSoundRenderingManagerGet( )->GetPlayerManager( )->CaptureFreePlayer
+ (
+ &pPlayer,
+ this,
+ false );
+
+ if( pPlayer != NULL )
+ {
+ pPlayer->Play( );
+ }
+ }
+ else
+ {
+ // You shouldn't have left play commands in the composer script
+ rDebugString( "Can't play sounds before resources are locked down.\n" );
+ }
+}
+
+//=============================================================================
+// Public functions
+//=============================================================================
+
+void daSoundResourceData::AddRef( void )
+{
+ //Sound::daSoundResourceManager::GetInstance( )->AddRef( );
+}
+
+void daSoundResourceData::Release( void )
+{
+ //Sound::daSoundResourceManager::GetInstance( )->Release( );
+}
+
+
+
diff --git a/game/code/sound/soundrenderer/soundresource.h b/game/code/sound/soundrenderer/soundresource.h
new file mode 100644
index 0000000..30abb0f
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundresource.h
@@ -0,0 +1,152 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundresource.hpp
+//
+// Subsystem: Dark Angel - Sound Resources
+//
+// Description: Defines sound resource
+//
+// Modification History:
+// + Created October 11, 2001 -- aking
+//
+//=============================================================================
+
+#ifndef _SOUNDRESOURCE_HPP
+#define _SOUNDRESOURCE_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <radlinkedclass.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/idasoundresource.h>
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundResourceData;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+//
+// This contains the type of resource.
+//
+class daSoundResourceData
+ :
+ public IDaSoundResource
+{
+public:
+
+ virtual void AddRef( void );
+ virtual void Release( void );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundResourceData( );
+ virtual ~daSoundResourceData( );
+
+ //
+ // IDaSoundResourceData and IDaSoundResource
+ //
+ virtual void AddFilename
+ (
+ const char* newFileName,
+ float trim
+ );
+
+ inline virtual unsigned int GetNumFiles( void );
+
+ virtual void GetFileNameAt( unsigned int index, char* buffer, unsigned int max );
+ virtual void GetFileKeyAt( unsigned int index, char * buffer, unsigned int max );
+
+ virtual void SetPitchRange
+ (
+ float minPitch,
+ float maxPitch
+ );
+ virtual void GetPitchRange
+ (
+ float* pMinPitch,
+ float* pMaxPitch
+ );
+
+ virtual void SetTrimRange
+ (
+ float minTrim,
+ float maxTrim
+ );
+ virtual void GetTrimRange
+ (
+ float* pMinTrim,
+ float* pMaxTrim
+ );
+
+ virtual void SetTrim( float trim );
+
+ virtual void SetStreaming( bool streaming );
+ virtual bool GetStreaming( void );
+
+ virtual void SetLooping( bool looping );
+ virtual bool GetLooping( void );
+
+ virtual Type GetType( void );
+ virtual void SetSoundGroup( Sound::daSoundGroup soundGroup );
+ virtual Sound::daSoundGroup GetSoundGroup( void );
+
+ virtual void CaptureResource( void );
+ virtual bool IsCaptured( void );
+ virtual void ReleaseResource( void );
+
+ // COMPOSERS ONLY!!
+ virtual void Play( void );
+
+ //
+ // The pitch variation
+ //
+ short m_MinPitch;
+ short m_MaxPitch;
+
+ //
+ // The sound files for this resource
+ //
+
+ union FileId {
+ char * m_pName;
+ radKey32 m_Key;
+ };
+
+ FileId * m_pFileIds;
+
+
+ //
+ // The trim variation
+ //
+ unsigned char m_MinTrim;
+ unsigned char m_MaxTrim;
+
+ unsigned char m_Flags;
+
+ unsigned char m_NumFiles;
+
+ //
+ // Hold a capture counter
+ //
+ unsigned char m_CaptureCount;
+ unsigned char m_SoundGroup;
+};
+
+inline unsigned int daSoundResourceData::GetNumFiles( void )
+{
+ return m_NumFiles;
+}
+
+#endif //_SOUNDRESOURCE_HPP
+
diff --git a/game/code/sound/soundrenderer/soundresourcemanager.cpp b/game/code/sound/soundrenderer/soundresourcemanager.cpp
new file mode 100644
index 0000000..5fdc5f6
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundresourcemanager.cpp
@@ -0,0 +1,527 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundresourcemanager.cpp
+//
+// Subsystem: Dark Angel - Sound Resource Manager
+//
+// Description: Implementation of the sound resource manager
+//
+// Revisions:
+// + Created October 11, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radkey.hpp>
+#include <radobjectbtree.hpp>
+#include <radnamespace.hpp>
+#include <radsound.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/soundresource.h>
+#include <sound/soundrenderer/soundallocatedresource.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+
+#include <memory/srrmemory.h>
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Static Variables
+//=============================================================================
+
+daSoundResourceManager* daSoundResourceManager::s_pSingleton = NULL;
+
+//=============================================================================
+// Constants
+//=============================================================================
+
+//
+// The maximum number of sound resource files (not the resources, but the
+// the actual files)
+//
+const unsigned int MaxNumResourceFiles = 512;
+
+#if defined( RAD_XBOX ) || defined( RAD_WIN32 )
+ const IRadSoundHalAudioFormat::Encoding DEFAULT_ENCODING = IRadSoundHalAudioFormat::PCM;
+#elif defined RAD_PS2
+ const IRadSoundHalAudioFormat::Encoding DEFAULT_ENCODING = IRadSoundHalAudioFormat::VAG;
+#elif defined RAD_GAMECUBE
+ const IRadSoundHalAudioFormat::Encoding DEFAULT_ENCODING = IRadSoundHalAudioFormat::PCM_BIGENDIAN;
+#else
+ Uh oh.
+#endif
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundResourceManager Implementation
+//=============================================================================
+
+
+//=============================================================================
+// Function: daSoundResourceManager::daSoundResourceManager
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundResourceManager::daSoundResourceManager( )
+ :
+ radRefCount( 0 ),
+ m_pSoundNamespace( NULL ),
+ m_ResourceLockdown( false ),
+ m_secondaryNamespace( NULL )
+
+{
+ m_pFileIdMemory = 0;
+
+ m_NumResourceDatas = 0;
+
+ // Create the singleton
+ rAssert( s_pSingleton == NULL );
+ s_pSingleton = this;
+
+ // Remember the sound namespace
+ m_pSoundNamespace = Sound::daSoundRenderingManagerGet( )->GetSoundNamespace( );
+ if( m_pSoundNamespace != NULL )
+ {
+ m_pSoundNamespace->AddRef( );
+ }
+
+ m_xIOL_AllocatedResources = new ( GetThisAllocator( )) radObjectBTree( );
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::~daSoundResourceManager
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundResourceManager::~daSoundResourceManager( )
+{
+ // Release the allocated sound resources
+ m_xIOL_AllocatedResources = NULL;
+
+ // Release the sound namespace
+ if( m_pSoundNamespace != NULL )
+ {
+ m_pSoundNamespace->Release( );
+ m_pSoundNamespace = NULL;
+ }
+
+ // Remove the singleton
+ rAssert( s_pSingleton != NULL );
+ s_pSingleton = NULL;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::AllocateResource
+//=============================================================================
+// Description: Allocate a resource
+//
+// Parameters: pResource - the resource to allocate
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceManager::AllocateResource
+(
+ IDaSoundResource* pResource
+)
+{
+ rAssert( pResource != NULL );
+
+ //
+ // Allocate this resource
+ //
+ radKey32 soundKey = (radKey32) pResource;
+
+ // Find out if it already exists...
+ daSoundAllocatedResource* pAllocatedResource =
+ FindAllocatedResource( pResource );
+ if( pAllocatedResource == NULL )
+ {
+ pAllocatedResource = new ( GetThisAllocator( ) ) daSoundAllocatedResource;
+ pAllocatedResource->AddRef( );
+ pAllocatedResource->Initialize( pResource );
+
+ // Add it to our allocated resource manager
+ m_xIOL_AllocatedResources->AddObject (
+ soundKey,
+ pAllocatedResource
+ );
+
+ // Release our version
+ pAllocatedResource->Release( );
+ }
+
+ rAssert( pAllocatedResource != NULL );
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::DeallocateResource
+//=============================================================================
+// Description: Allocate a resource
+//
+// Parameters: pResource - the resource to allocate
+//
+//-----------------------------------------------------------------------------
+
+void daSoundResourceManager::DeallocateResource
+(
+ IDaSoundResource* pResource
+)
+{
+ rAssert( pResource != NULL );
+
+ //
+ // Deallocate the resource
+ //
+ radKey32 soundKey = (radKey32) pResource;
+
+ bool result = m_xIOL_AllocatedResources->RemoveObject( soundKey );
+ rAssertMsg( result, "Resource deallocated prematurely?" );
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::FindResource
+//=============================================================================
+// Description: Find a resource.
+//
+// Parameters: resourceName - the name of the resource to find
+//
+// Returns: Returns a pointer to the appropriate resource or NULL if none
+// found.
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundResource* daSoundResourceManager::FindResource
+(
+ daResourceName resourceName
+)
+{
+ IDaSoundResource* pResource;
+
+ pResource = reinterpret_cast< IDaSoundResource* >(
+ m_pSoundNamespace->GetInstance( resourceName ) );
+
+ if( ( pResource == NULL ) && ( m_secondaryNamespace != NULL ) )
+ {
+ // Search secondary namespace
+ pResource = reinterpret_cast< IDaSoundResource* >
+ (
+ m_secondaryNamespace->GetInstance( resourceName )
+ );
+ }
+
+ return pResource;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::FindResource
+//=============================================================================
+// Description: Find a resource by its key.
+//
+// Parameters: resourceKey - the key for the resource to find
+//
+// Returns: Returns a pointer to the appropriate resource or NULL if none
+// found.
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundResource* daSoundResourceManager::FindResource
+(
+ daResourceKey resourceKey
+)
+{
+ IDaSoundResource* pResource;
+
+ pResource = reinterpret_cast< IDaSoundResource* >
+ (
+ m_pSoundNamespace->GetInstance( resourceKey )
+ );
+ if( ( pResource == NULL ) && ( m_secondaryNamespace != NULL ) )
+ {
+ // Search secondary namespace
+ pResource = reinterpret_cast< IDaSoundResource* >
+ (
+ m_secondaryNamespace->GetInstance( resourceKey )
+ );
+ }
+
+ return pResource;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::FindAllocatedResource
+//=============================================================================
+// Description: Find an allocated resource
+//
+// Parameters: pResource - the resource associated with an allocated resource
+//
+// Note: Calling this command on a given resource is not guarenteed
+// to always return the same allocated resource. In fact,
+// it randomly choose which of the possible file variations
+// it should use.
+//
+//-----------------------------------------------------------------------------
+
+daSoundAllocatedResource* daSoundResourceManager::FindAllocatedResource
+(
+ IDaSoundResource* pResource
+)
+{
+ rAssert( pResource != NULL );
+
+ // Generate a key based on the resource
+ radKey32 soundKey = (radKey32) pResource;
+
+ // Find the allocated resource for the resource
+ daSoundAllocatedResource* pAllocatedResource =
+ reinterpret_cast< daSoundAllocatedResource* >
+ (
+ m_xIOL_AllocatedResources->FindObject( soundKey )
+ );
+
+ return pAllocatedResource;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::SetResourceLockdown
+//=============================================================================
+// Description: Set the lockdown state for resources
+//
+// Notes: When the resources are locked down, no new resources
+// can be created. This is so that the tuner's wiring
+// of the sound system can successively map all available
+// resources to sound groups.
+//
+//-----------------------------------------------------------------------------
+
+void FlipSlashes( char * pString )
+{
+ while (*pString != 0 )
+ {
+ if ( *pString == '/' )
+ {
+ *pString = '\\';
+ }
+ pString++;
+ }
+}
+
+void daSoundResourceManager::SetResourceLockdown( bool lockdown )
+{
+ // Currently we may only lock down the resources
+ rAssert( lockdown == true );
+ m_ResourceLockdown = lockdown;
+
+ unsigned int totalFiles = 0;
+
+ for( unsigned int r = 0; r < m_NumResourceDatas; r ++ )
+ {
+ daSoundResourceData * pRd = this->m_ResourceData + r;
+
+ totalFiles += pRd->m_NumFiles;
+ }
+
+ m_pFileIdMemory = (radKey32*) radMemoryAlloc( GMA_PERSISTENT, sizeof( radKey32 ) * totalFiles );
+
+ radKey32* pCurrent = m_pFileIdMemory;
+
+ for( unsigned int r = 0; r < MAX_SOUND_DATA_RESOURCES; r ++ )
+ {
+ daSoundResourceData * pRd = this->m_ResourceData + r;
+
+ for( unsigned int f = 0; f < pRd->m_NumFiles; f ++ )
+ {
+ FlipSlashes( pRd->m_pFileIds[ f ].m_pName );
+
+ pCurrent[ f ] = ::radMakeCaseInsensitiveKey32( pRd->m_pFileIds[ f ].m_pName );
+ radMemoryFree( pRd->m_pFileIds[ f ].m_pName );
+ }
+
+ radMemoryFree( pRd->m_pFileIds );
+ pRd->m_pFileIds = (daSoundResourceData::FileId*)pCurrent;
+ pCurrent += pRd->m_NumFiles;
+ }
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetResourceLockdown
+//=============================================================================
+// Description: Get the lockdown state for resources
+//-----------------------------------------------------------------------------
+
+bool daSoundResourceManager::GetResourceLockdown( void )
+{
+ return m_ResourceLockdown;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetLargestFileSize
+//=============================================================================
+// Description: Get the state of a resource
+//
+// Parameters: pResource - the resource to get the state of
+//
+// Returns: Returns the state of the resource
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundResourceManager::GetLargestFileSize
+(
+ IDaSoundResource* pResource
+)
+{
+ return 0;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetTotalSize
+//=============================================================================
+// Description: Get the state of a resource
+//
+// Parameters: pResource - the resource to get the state of
+//
+// Returns: Returns the state of the resource
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundResourceManager::GetTotalSize
+(
+ IDaSoundResource* pResource
+)
+{
+ return 0;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetSoundFileSize
+//=============================================================================
+// Description: Get debug information from resource manager
+//
+// Parameters: pFile - the file to find the size of
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundResourceManager::GetSoundFileSize
+(
+ const char* filename
+)
+{
+ // TODO : Don't use this unless it is not synchronous
+ rDebugString( "BAD SOUND FUNCTION BEING USED\n" );
+ unsigned int fileSize = 0;
+ IRadFile* pMyFile = NULL;
+ ::radFileOpen( &pMyFile, filename );
+ rAssert( pMyFile != NULL );
+ pMyFile->GetSizeAsync( &fileSize );
+ pMyFile->WaitForCompletion( );
+ pMyFile->Release( );
+ return fileSize;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetNumResources
+//=============================================================================
+// Description: Get the number of resources
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundResourceManager::GetNumResourceDatas( void )
+{
+ return m_NumResourceDatas;
+}
+
+//=============================================================================
+// Function: daSoundResourceManager::GetNumAllocatedResources
+//=============================================================================
+// Description: Get the number of allocated resources
+//
+//-----------------------------------------------------------------------------
+
+unsigned int daSoundResourceManager::GetNumAllocatedResources( void )
+{
+ return m_xIOL_AllocatedResources->GetSize( );
+}
+
+//=============================================================================
+// daSoundResourceManager::SetActiveResource
+//=============================================================================
+// Description: Set a secondary namespace for us to search for resources.
+// NOTE: a more robust implementation would have us storing a list
+// of these things, but I know for Simpsons that we'll only need
+// one and I want to keep the searches fast
+//
+// Parameters: activeNamespace - secondary namespace
+//
+// Return: void
+//
+//=============================================================================
+void daSoundResourceManager::SetActiveResource( IRadNameSpace* activeNamespace )
+{
+ if( activeNamespace != m_pSoundNamespace )
+ {
+ m_secondaryNamespace = activeNamespace;
+ }
+}
+
+//=============================================================================
+// daSoundResourceManager::ReleaseActiveResource
+//=============================================================================
+// Description: Lose our reference to the secondary namespace, probably because
+// the in-game resources are being released.
+//
+// Parameters: inactiveNamespace - only used to make sure we aren't releasing
+// the main sound namespace
+//
+// Return: void
+//
+//=============================================================================
+void daSoundResourceManager::ReleaseActiveResource( IRadNameSpace* inactiveNamespace )
+{
+ if( inactiveNamespace != m_pSoundNamespace )
+ {
+ m_secondaryNamespace = NULL;
+ }
+}
+
+daSoundResourceData * daSoundResourceManager::GetResourceDataAt( unsigned int i )
+{
+ rAssert( i < m_NumResourceDatas );
+
+ return m_ResourceData + i;
+}
+
+daSoundResourceData * daSoundResourceManager::CreateResourceData( void )
+{
+ daSoundResourceManager * pThis = daSoundResourceManager::GetInstance( );
+
+ rAssert( false == pThis->m_ResourceLockdown );
+
+ rAssert( pThis->m_NumResourceDatas < MAX_SOUND_DATA_RESOURCES );
+
+ daSoundResourceData * pRd = pThis->m_ResourceData + pThis->m_NumResourceDatas;
+
+ pThis->m_NumResourceDatas++;
+
+ return pRd;
+}
+
+} // Sound Namespace
+
diff --git a/game/code/sound/soundrenderer/soundresourcemanager.h b/game/code/sound/soundrenderer/soundresourcemanager.h
new file mode 100644
index 0000000..3a290c1
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundresourcemanager.h
@@ -0,0 +1,164 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundresourcemanager.hpp
+//
+// Subsystem: Dark Angel - Sound Resource Management System
+//
+// Description: Description of the DA sound resource manager
+//
+// Revisions:
+// + Created October 11, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _SOUNDRESOURCEMANAGER_HPP
+#define _SOUNDRESOURCEMANAGER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/soundresource.h>
+
+//=============================================================================
+// Global namespace forward declarations
+//=============================================================================
+
+class radObjectBTree;
+
+//=============================================================================
+// Namespace
+//=============================================================================
+
+namespace Sound {
+
+const unsigned int MAX_SOUND_DATA_RESOURCES = 5000;
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundResourceManager;
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+class daSoundAllocatedResource;
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+//
+// The sound player manager passes information into the various sound
+// players. It also keeps track of these players, gives them to people
+// who ask for them, and makes sure they do not cause to much trouble :)
+//
+class daSoundResourceManager : public IRefCount,
+ public radRefCount
+{
+public:
+ IMPLEMENT_REFCOUNTED( "daSoundResourceManager" );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundResourceManager( void );
+
+ virtual ~daSoundResourceManager( );
+
+ inline static daSoundResourceManager* GetInstance( void );
+
+ // Controlled by the resource data
+ void AllocateResource( IDaSoundResource* pResource );
+ void DeallocateResource( IDaSoundResource* pResource );
+
+ // Resource lockdown
+ void SetResourceLockdown( bool lockdown );
+
+ // Allocated resources
+ daSoundAllocatedResource* FindAllocatedResource
+ (
+ IDaSoundResource* pResource
+ );
+
+ // Get a sound file's size
+ unsigned int GetSoundFileSize
+ (
+ const char* filename
+ );
+
+ //
+ // IDaSoundResourceManager
+ //
+ IDaSoundResource* FindResource(
+ daResourceName resourceName );
+
+ IDaSoundResource* FindResource(
+ daResourceKey resourceKey );
+
+ unsigned int GetLargestFileSize( IDaSoundResource* pResource );
+ unsigned int GetTotalSize( IDaSoundResource* pResource );
+
+
+ bool GetResourceLockdown( void );
+
+ void SetActiveResource( IRadNameSpace* activeNamespace );
+ void ReleaseActiveResource( IRadNameSpace* inactiveNamespace );
+
+ unsigned int GetNumResourceDatas( void );
+ daSoundResourceData* GetResourceDataAt( unsigned int );
+ static daSoundResourceData* CreateResourceData( void );
+
+protected:
+ //
+ // Calculate some debug info
+ //
+
+ unsigned int GetNumAllocatedResources( );
+
+private:
+ // This is a singleton
+ static daSoundResourceManager* s_pSingleton;
+
+ //
+ // Store the sound namespace
+ //
+ IRadNameSpace* m_pSoundNamespace;
+
+ //
+ // Store all allocated resources (referenced by the resource's
+ // address cast to a radkey)
+ //
+ ref< radObjectBTree > m_xIOL_AllocatedResources;
+
+ //
+ // Are the resources locked down?
+ //
+ bool m_ResourceLockdown;
+
+ //
+ // Store active secondary namespace
+ //
+ IRadNameSpace* m_secondaryNamespace;
+
+ daSoundResourceData m_ResourceData[ MAX_SOUND_DATA_RESOURCES ];
+ unsigned int m_NumResourceDatas;
+
+ radKey32 * m_pFileIdMemory;
+};
+
+inline daSoundResourceManager* daSoundResourceManager::GetInstance( void )
+{
+ return s_pSingleton;
+}
+
+} // Sound Namespace
+#endif //_SOUNDRESOURCEMANAGER_HPP
+
+
diff --git a/game/code/sound/soundrenderer/soundsystem.h b/game/code/sound/soundrenderer/soundsystem.h
new file mode 100644
index 0000000..b0557ff
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundsystem.h
@@ -0,0 +1,118 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundsystem.hpp
+//
+// Subsystem: Dark Angel - Sound System
+//
+// Description: General declarations relating to the Dark Angel sound system
+//
+// Notes: This is the only file that may be loaded by non sound related
+// components of the game.
+//
+// Revisions: October 2, 2001 Creation BJR
+//
+//=============================================================================
+
+#ifndef _SOUNDSYSTEM_HPP
+#define _SOUNDSYSTEM_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radkey.hpp>
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+class daSoundRenderingManager;
+
+//=============================================================================
+// Constants, Definitions and Macros
+//=============================================================================
+
+// The sound memory allocator
+extern radMemoryAllocator DAMEMORY_ALLOC_SOUND;
+
+// One aux send channels will be used for spacial effects
+#define DA_SPACIAL_EFFECT_AUX_SEND 0
+#define DA_MISC_AUX_SEND 1
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+struct IDaSoundPlayerState;
+struct IDaSoundFadeState;
+struct IDaSoundSoundState;
+
+//=============================================================================
+// Typedefs and Enumerations
+//=============================================================================
+
+//
+// This is a sound resource name and key
+//
+typedef const char* daResourceName;
+typedef radKey32 daResourceKey;
+
+//
+// These are the sound values
+//
+typedef float daPitchValue;
+typedef float daTrimValue;
+
+//=============================================================================
+// Interfaces
+//=============================================================================
+
+//
+// Sound player state
+//
+struct IDaSoundPlayerState : public IRefCount
+{
+ virtual void OnSoundReady( void* pData ) = 0;
+ virtual void OnSoundDone( void* pData ) = 0;
+};
+
+//
+// Fade state
+//
+struct IDaSoundFadeState : public IRefCount
+{
+ virtual void OnFadeDone( void* pData ) = 0;
+};
+
+//
+// A sound object
+//
+struct IDaSoundObject : public IRefCount
+{
+ // Left intentionally blank
+};
+
+//=============================================================================
+// Public Functions
+//=============================================================================
+
+//
+// Set some global sound flags
+//
+void daSoundSetSoundOn( bool soundOn );
+
+//
+// Work indirectly with the sound manager
+//
+void daSoundRenderingManagerCreate( radMemoryAllocator allocator );
+daSoundRenderingManager* daSoundRenderingManagerGet( void );
+void daSoundRenderingManagerTerminate( void );
+
+} // Namespace
+#endif //_SOUNDSYSTEM_HPP
+
diff --git a/game/code/sound/soundrenderer/soundtuner.cpp b/game/code/sound/soundrenderer/soundtuner.cpp
new file mode 100644
index 0000000..7aaed29
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundtuner.cpp
@@ -0,0 +1,1241 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundtuner.cpp
+//
+// Subsystem: Dark Angel - Sound Tuner System
+//
+// Description: Implementation of the sound tuner
+//
+// Revisions:
+// + Created October 4, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+#include <radnamespace.hpp>
+
+#include <radsound.hpp>
+#include <radsound_hal.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/idasoundresource.h>
+#include <sound/soundrenderer/soundrenderingmanager.h>
+#include <sound/soundrenderer/soundresourcemanager.h>
+#include <sound/soundrenderer/playermanager.h>
+#include <sound/soundrenderer/soundtuner.h>
+
+#include <sound/soundmanager.h>
+
+#include <memory/srrmemory.h>
+
+//=============================================================================
+// Static Variables (outside namespace)
+//=============================================================================
+
+short Sound::daSoundTuner::s_groupWirings[NUM_SOUND_GROUPS];
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Class Implementations
+//=============================================================================
+
+//=============================================================================
+// daSoundTuner_ActiveFadeInfo Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundTuner_ActiveFadeInfo::daSoundTuner_ActiveFadeInfo
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundTuner_ActiveFadeInfo::daSoundTuner_ActiveFadeInfo
+(
+ Fader* pFader,
+ bool fadingIn,
+ IDaSoundFadeState* pDoneCallback,
+ void* pCallbackUserData,
+ DuckVolumeSet* initialVolumes,
+ DuckVolumeSet* targetVolumes
+)
+ :
+ m_pFader( pFader ),
+ m_FadingIn( fadingIn ),
+ m_pDoneCallback( pDoneCallback ),
+ m_pCallbackUserData( pCallbackUserData )
+{
+ // Reference count some items
+ rAssert( m_pFader != NULL );
+
+ m_pFader->AddRef( );
+ if( m_pDoneCallback != NULL )
+ {
+ m_pDoneCallback->AddRef( );
+ }
+
+ // Invoke the fader
+ m_pFader->Fade( m_FadingIn, initialVolumes, targetVolumes );
+}
+
+
+//=============================================================================
+// Function: daSoundTuner_ActiveFadeInfo::~daSoundTuner_ActiveFadeInfo
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundTuner_ActiveFadeInfo::~daSoundTuner_ActiveFadeInfo( )
+{
+ // Release our objects
+ rAssert( m_pFader != NULL );
+
+ m_pFader->Stop();
+ m_pFader->Release( );
+ if( m_pDoneCallback != NULL )
+ {
+ m_pDoneCallback->Release( );
+ }
+}
+
+//=============================================================================
+// Function: daSoundTuner_ActiveFadeInfo::ProcessFader
+//=============================================================================
+// Description: Process a fader's state progress
+//
+// Returns: true if we're done with the fader and are ready for destruction,
+// false otherwise
+//
+//-----------------------------------------------------------------------------
+
+bool daSoundTuner_ActiveFadeInfo::ProcessFader()
+{
+ // Is the fader done fading yet?
+ bool doneFading = false;
+ switch( m_pFader->GetState( ) )
+ {
+ case Fader::FadedIn:
+ case Fader::FadedOut:
+ {
+ // Must be done (what ever it was)
+ doneFading = true;
+ break;
+ }
+ case Fader::FadingIn:
+ {
+ // If we're supposed to be fading out, we must be done
+ if( !m_FadingIn )
+ {
+ doneFading = true;
+ }
+ break;
+ }
+ case Fader::FadingOut:
+ {
+ // If we're supposed to be fading in, we must be done
+ if( m_FadingIn )
+ {
+ doneFading = true;
+ }
+ break;
+ }
+ default:
+ rAssert( 0 );
+ break;
+ }
+
+ // If done, disconnect it, destroy it, and call its callback
+ if( doneFading )
+ {
+ // Remember the callback
+ IDaSoundFadeState* pCallback = m_pDoneCallback;
+ void* pUserData = m_pCallbackUserData;
+ if( pCallback != NULL )
+ {
+ pCallback->AddRef( );
+ }
+
+ // Call the callback
+ if( pCallback != NULL )
+ {
+ pCallback->OnFadeDone( pUserData );
+ pCallback->Release( );
+ }
+ }
+
+ return( doneFading );
+}
+
+void daSoundTuner_ActiveFadeInfo::StoreCurrentVolumes( DuckVolumeSet& volumeSet )
+{
+ unsigned int i;
+
+ rAssert( m_pFader != NULL );
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ volumeSet.duckVolume[i] = m_pFader->GetCurrentVolume( static_cast<DuckVolumes>(i) );
+ }
+}
+
+void daSoundTuner_ActiveFadeInfo::StoreTargetSettings( DuckVolumeSet& volumeSet )
+{
+ unsigned int i;
+
+ rAssert( m_pFader != NULL );
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ volumeSet.duckVolume[i] = m_pFader->GetTargetSettings( static_cast<DuckVolumes>(i) );
+ }
+}
+
+//=============================================================================
+// daSoundTuner Implementation
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundTuner::daSoundTuner
+//=============================================================================
+// Description: Constructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundTuner::daSoundTuner( )
+ :
+ radRefCount( 0 ),
+ m_pDuckFade( NULL ),
+ m_MasterVolume( 1.0f ),
+ m_activeFadeInfo( NULL ),
+ m_NISTrim( 1.0f )
+{
+ daSoundPlayerManager* playerMgr;
+ int i, j;
+
+ //
+ // The tuner makes use of several fader objects. These objects may be
+ // customized by scripts, so they must be added to the sound namespace.
+ //
+
+ // Duck fader
+ playerMgr = daSoundRenderingManagerGet()->GetPlayerManager();
+ rAssert( playerMgr != NULL );
+
+ m_pDuckFade = new( GetThisAllocator() ) Fader( NULL, DUCK_FULL_FADE, *playerMgr, *this );
+ rAssert( m_pDuckFade != NULL );
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ m_situationFaders[i] = NULL;
+ }
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ m_userVolumes.duckVolume[i] = 1.0f;
+ m_finalDuckLevels.duckVolume[i] = 1.0f;
+ }
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ for( j = 0; j < NUM_DUCK_VOLUMES; j++ )
+ {
+ m_duckLevels[i].duckVolume[j] = 1.0f;
+ }
+ }
+
+ //
+ // Initialize the sound group wirings (IMPORTANT: this assumes that
+ // daSoundTuner is a singleton, we only want to do this once)
+ //
+ for( i = 0; i < NUM_SOUND_GROUPS; i++ )
+ {
+ s_groupWirings[i] = ( 1 << i ) | ( 1 << MASTER );
+ }
+}
+
+//=============================================================================
+// Function: daSoundTuner::~daSoundTuner
+//=============================================================================
+// Description: Destructor
+//
+//-----------------------------------------------------------------------------
+
+daSoundTuner::~daSoundTuner( )
+{
+ int i;
+
+ // Release our duck faders
+ if( m_pDuckFade != NULL )
+ {
+ m_pDuckFade->Release( );
+ m_pDuckFade = NULL;
+ }
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ if( m_situationFaders[i] != NULL )
+ {
+ m_situationFaders[i]->Release( );
+ m_situationFaders[i] = NULL;
+ }
+ }
+
+ if( m_activeFadeInfo != NULL )
+ {
+ delete m_activeFadeInfo;
+ }
+}
+
+//=============================================================================
+// Function: daSoundTuner::Initialize
+//=============================================================================
+// Description: Initialize the sound tuner. This can only be done once
+// resources have been locked down.
+//
+// Parameters: outputMode - the output mode desired
+//
+// Returns: n/a
+//
+// Notes: This class does not support re-initialization
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::Initialize( void )
+{
+ // Make sure resources are locked down
+ //rAssert( Sound::daSoundRenderingManagerGet( )->GetResourceManager( )->GetResourceLockdown( ) );
+
+ // Generate each of the wiring groups
+ Sound::daSoundTunerWireSystem( this );
+}
+
+//=============================================================================
+// daSoundTuner::PostScriptLoadInitialize
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ()
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::PostScriptLoadInitialize()
+{
+ IRadNameSpace* nameSpace;
+ globalSettings* settingsObj;
+ daSoundPlayerManager* playerMgr;
+ int i;
+
+ playerMgr = daSoundRenderingManagerGet()->GetPlayerManager();
+ rAssert( playerMgr != NULL );
+
+ //
+ // Get the globalSettings object for Fader use
+ //
+ nameSpace = Sound::daSoundRenderingManagerGet()->GetTuningNamespace();
+ rAssert( nameSpace != NULL );
+
+ settingsObj = reinterpret_cast<globalSettings*>( nameSpace->GetInstance( "tuner" ) );
+ rAssert( settingsObj != NULL );
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ m_situationFaders[i] = new( GetThisAllocator() ) Fader( settingsObj,
+ static_cast<DuckSituations>(i),
+ *playerMgr,
+ *this );
+ rAssert( m_situationFaders[i] != NULL );
+ }
+
+#ifdef SOUND_DEBUG_INFO_ENABLED
+ m_debugPage.LazyInitialization( 4, GetSoundManager()->GetDebugDisplay() );
+#endif
+}
+
+//=============================================================================
+// Function: daSoundTuner::ServiceOncePerFrame
+//=============================================================================
+// Description: Service the sound tuner. This should be done once per frame.
+//
+// Parameters: none
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::ServiceOncePerFrame( unsigned int elapsedTime )
+{
+ bool faderDone;
+
+ //
+ // Process the faders
+ //
+ Fader::UpdateAllFaders( elapsedTime );
+
+ //
+ // Process the fade info stuff that monitors the faders (hmmm, this is
+ // looking like a pretty lightweight class these days. Candidate for
+ // removal?)
+ //
+ if( m_activeFadeInfo != NULL )
+ {
+ faderDone = m_activeFadeInfo->daSoundTuner_ActiveFadeInfo::ProcessFader();
+
+ if( faderDone )
+ {
+ delete m_activeFadeInfo;
+ m_activeFadeInfo = NULL;
+ }
+ }
+
+ serviceDebugInfo();
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetSoundOutputMode
+//=============================================================================
+// Description: Set the sound system output mode (stereo, mono, surround)
+//
+// Parameters: outputMode - the output mode desired
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetSoundOutputMode
+(
+ IDaSoundTuner::SoundOutputMode outputMode
+)
+{
+ radSoundOutputMode rsdOutputMode = radSoundOutputMode_Stereo;
+ if( outputMode == MONO )
+ {
+ rsdOutputMode = radSoundOutputMode_Mono;
+ }
+ else if( outputMode == STEREO )
+ {
+ rsdOutputMode = radSoundOutputMode_Stereo;
+ }
+ else if( outputMode == SURROUND )
+ {
+ rsdOutputMode = radSoundOutputMode_Surround;
+ }
+ else
+ {
+ rAssertMsg( 0, "Invalid sound output mode" );
+ }
+
+ ::radSoundHalSystemGet( )->SetOutputMode( rsdOutputMode );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetSoundOutputMode
+//=============================================================================
+// Description: Get the sound system output mode (stereo, mono, surround)
+//
+// Parameters: none
+//
+// Returns: Returns the current sound output mode
+//
+//-----------------------------------------------------------------------------
+
+IDaSoundTuner::SoundOutputMode daSoundTuner::GetSoundOutputMode
+(
+ void
+)
+{
+ IDaSoundTuner::SoundOutputMode outputMode = STEREO;
+ radSoundOutputMode rsdOutputMode =
+ ::radSoundHalSystemGet( )->GetOutputMode( );
+ if( rsdOutputMode == radSoundOutputMode_Mono )
+ {
+ outputMode = MONO;
+ }
+ else if( rsdOutputMode == radSoundOutputMode_Stereo )
+ {
+ outputMode = STEREO;
+ }
+ else if( rsdOutputMode == radSoundOutputMode_Surround )
+ {
+ outputMode = SURROUND;
+ }
+ else
+ {
+ rAssertMsg( 0, "Unrecognized sound output mode" );
+ }
+
+ return outputMode;
+}
+
+//=============================================================================
+// Function: daSoundTuner::ActivateDuck
+//=============================================================================
+// Description: Start/stop ducking of sounds
+//
+// Parameters: pObject - the object to receive fade state events
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::ActivateDuck
+(
+ IDaSoundFadeState* pObject,
+ void* pUserData,
+ bool fadeIn
+)
+{
+ activateDuckInternal( pObject, pUserData, fadeIn, m_pDuckFade );
+}
+
+//=============================================================================
+// Function: daSoundTuner::StartSituationalDuck
+//=============================================================================
+// Description: Start ducking of sounds
+//
+// Parameters: pObject - the object to receive fade state events
+//
+// Returns: n/a
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::ActivateSituationalDuck( IDaSoundFadeState* pObject,
+ DuckSituations situation,
+ void* pUserData,
+ bool fadeIn )
+{
+ activateDuckInternal( pObject, pUserData, fadeIn, m_situationFaders[situation] );
+}
+
+//=============================================================================
+// daSoundTuner::ResetDuck
+//=============================================================================
+// Description: Stop all ducking
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::ResetDuck()
+{
+ unsigned int i, j;
+
+ //
+ // Return all the duck values to max, then do a fade in
+ //
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ for( j = 0; j < NUM_DUCK_SITUATIONS; j++ )
+ {
+ m_duckLevels[j].duckVolume[i] = 1.0f;
+ }
+ }
+
+ activateDuckInternal( NULL, NULL, true, m_pDuckFade );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetMasterVolume
+//=============================================================================
+// Description: Set the master volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetMasterVolume
+(
+ daTrimValue volume
+)
+{
+ m_MasterVolume = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( MASTER, m_MasterVolume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetMasterVolume
+//=============================================================================
+// Description: Get the master volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetMasterVolume( void )
+{
+ return( m_MasterVolume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetDialogueVolume
+//=============================================================================
+// Description: Set the dialogue volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetDialogueVolume
+(
+ daTrimValue volume
+)
+{
+ m_userVolumes.duckVolume[DUCK_DIALOG] = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( DIALOGUE, volume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetDialogueVolume
+//=============================================================================
+// Description: Get the dialogue volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetDialogueVolume( void )
+{
+ return( m_userVolumes.duckVolume[DUCK_DIALOG] );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetMusicVolume
+//=============================================================================
+// Description: Set the music volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetMusicVolume
+(
+ daTrimValue volume
+)
+{
+ m_userVolumes.duckVolume[DUCK_MUSIC] = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( MUSIC, volume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetMusicVolume
+//=============================================================================
+// Description: Get the music volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetMusicVolume( void )
+{
+ return( m_userVolumes.duckVolume[DUCK_MUSIC] );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetAmbienceVolume
+//=============================================================================
+// Description: Set the music volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetAmbienceVolume
+(
+ daTrimValue volume
+)
+{
+ m_userVolumes.duckVolume[DUCK_AMBIENCE] = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( AMBIENCE, volume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetAmbienceVolume
+//=============================================================================
+// Description: Get the music volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetAmbienceVolume( void )
+{
+ return( m_userVolumes.duckVolume[DUCK_AMBIENCE] );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetSfxVolume
+//=============================================================================
+// Description: Set the sound effects volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetSfxVolume
+(
+ daTrimValue volume
+)
+{
+ m_userVolumes.duckVolume[DUCK_SFX] = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( SOUND_EFFECTS, volume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetSfxVolume
+//=============================================================================
+// Description: Get the sound effects volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetSfxVolume( void )
+{
+ return( m_userVolumes.duckVolume[DUCK_SFX] );
+}
+
+//=============================================================================
+// Function: daSoundTuner::SetCarVolume
+//=============================================================================
+// Description: Set the sound effects volume
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::SetCarVolume( daTrimValue volume )
+{
+ m_userVolumes.duckVolume[DUCK_CAR] = volume;
+
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( CARSOUND, volume );
+}
+
+//=============================================================================
+// Function: daSoundTuner::GetCarVolume
+//=============================================================================
+// Description: Get the sound effects volume
+//
+//-----------------------------------------------------------------------------
+
+daTrimValue daSoundTuner::GetCarVolume( void )
+{
+ return( m_userVolumes.duckVolume[DUCK_CAR] );
+}
+
+//=============================================================================
+// Function: daSoundTuner::FadeSounds
+//=============================================================================
+// Description: Fade a particular group of sounds
+//
+// Parameters: pKnob - the knob to fade
+// pObject - the fade state change object
+// pUserData - user data for the state change callback
+// pFader - a pointer to an actual fader to use
+// fadeIn - true if we are fading in
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::FadeSounds
+(
+ IDaSoundFadeState* pObject,
+ void* pUserData,
+ Fader* pFader,
+ bool fadeIn,
+ DuckVolumeSet* initialVolumes
+)
+{
+ unsigned int i;
+ DuckVolumeSet currentVolumes;
+ DuckVolumeSet* initVolumePtr = initialVolumes;
+ DuckVolumeSet targetVolumes;
+
+ rAssert( m_activeFadeInfo == NULL );
+ rAssert( pFader != NULL );
+ if( pFader == NULL )
+ {
+ return;
+ }
+
+ HeapMgr()->PushHeap( static_cast<GameMemoryAllocator>(GetThisAllocator()) );
+
+ //
+ // Store the intended targets for this fader.
+ //
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ if( fadeIn )
+ {
+ m_duckLevels[pFader->GetSituation()].duckVolume[i] = 1.0f;
+ }
+ else
+ {
+ m_duckLevels[pFader->GetSituation()].duckVolume[i] =
+ pFader->GetTargetSettings( static_cast<Sound::DuckVolumes>(i) );
+ }
+ }
+
+ if( initVolumePtr == NULL )
+ {
+ //
+ // Initial volumes aren't supplied, so use the current settings
+ // as we've recorded them here
+ //
+ initVolumePtr = &currentVolumes;
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ currentVolumes.duckVolume[i] = m_userVolumes.duckVolume[i];
+ }
+ }
+
+ calculateDuckedVolumes( targetVolumes );
+
+ // Create the temporary fade object. It will destroy itself when done
+ m_activeFadeInfo = new daSoundTuner_ActiveFadeInfo
+ (
+ pFader,
+ fadeIn,
+ pObject,
+ pUserData,
+ initialVolumes,
+ &targetVolumes
+ );
+
+ HeapMgr()->PopHeap( static_cast<GameMemoryAllocator>( GetThisAllocator() ) );
+}
+
+
+//=============================================================================
+// Function: daSoundTuner::WireKnobToPathHelper
+//=============================================================================
+// Description: Helper function to wire a knob to a path for a resource.
+// This function is automattically called on every
+// sound resource. If the path matches that of a file
+// in the resource, the resource's sound group is automattically
+// wired to the sound group specified by the user data.
+//
+// Notes: Trying to put a resource in more than one group will not work!
+// If a resource contains files from more than one fundamental
+// path and its wiring must reflect this, then a new
+// allocation stratagy should be used.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::WireKnobToPathHelper
+(
+ IDaSoundResource* pRes,
+ void* pUserData
+)
+{
+ char filenameBuffer[256];
+
+ // Get the wiring info
+ WirePathInfo* pInfo = (WirePathInfo*)pUserData;
+
+ unsigned int i = 0;
+ for( i = 0; i < pRes->GetNumFiles( ); i++ )
+ {
+ pRes->GetFileNameAt( i, filenameBuffer, 256 );
+ unsigned int j = 0;
+ bool match = true;
+ for( j = 0; j < pInfo->m_PathLen; j++ )
+ {
+ char a = filenameBuffer[j];
+ char b = pInfo->m_Path[j];
+
+ if( a == '/' )
+ {
+ a = '\\';
+ }
+ if( b == '/' )
+ {
+ b = '\\';
+ }
+ if( a != b )
+ {
+ // Notice that this supports the case when the length
+ // of the filename is less than the test path because,
+ // in that case, the '\0' character won't match
+ match = false;
+ break;
+ }
+ }
+ if( match )
+ {
+ pRes->SetSoundGroup( pInfo->m_SoundGroup );
+ break;
+ }
+ }
+}
+
+//=============================================================================
+// Function: daSoundTuner::WirePath
+//=============================================================================
+// Description: Wire a path to a particular sound group
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTuner::WirePath
+(
+ daSoundGroup soundGroup,
+ const char* path
+)
+{
+ // Find all resource that are in this path and relate them to this knob
+ WirePathInfo wirePathInfo;
+ wirePathInfo.m_Path = path;
+ wirePathInfo.m_PathLen = strlen( wirePathInfo.m_Path );
+ wirePathInfo.m_SoundGroup = soundGroup;
+
+ unsigned int numResources =
+ daSoundResourceManager::GetInstance( )->GetNumResourceDatas( );
+
+ for( unsigned int r = 0; r < numResources; r ++ )
+ {
+ WireKnobToPathHelper(
+ daSoundResourceManager::GetInstance( )->GetResourceDataAt( r ),
+ & wirePathInfo );
+ }
+}
+
+//=============================================================================
+// daSoundTuner::WireGroup
+//=============================================================================
+// Description: Mark a sound group as changing in sync with the master group
+//
+// Parameters: slaveGroup - slave that changes with master group
+// masterGroup - controller group
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::WireGroup( daSoundGroup slaveGroup, daSoundGroup masterGroup )
+{
+ unsigned int i;
+
+ for( i = 0; i < NUM_SOUND_GROUPS; i++ )
+ {
+ if( s_groupWirings[i] & ( 1 << slaveGroup ) )
+ {
+ s_groupWirings[i] |= 1 << masterGroup;
+ }
+ }
+}
+
+//=============================================================================
+// daSoundTuner::IsSlaveGroup
+//=============================================================================
+// Description: Indicates whether one group is slaved to another
+//
+// Parameters: slave - proposed slave sound group
+// master - proposed master sound group
+//
+// Return: True if slave is affected by master, false otherwise
+//
+//=============================================================================
+bool daSoundTuner::IsSlaveGroup( daSoundGroup slave, daSoundGroup master )
+{
+ if( s_groupWirings[slave] & ( 1 << master ) )
+ {
+ return( true );
+ }
+
+ return( false );
+}
+
+//=============================================================================
+// daSoundTuner::GetGroupTrim
+//=============================================================================
+// Description: Get the trim associated with a particular sound group.
+// Actually, our "group" is currently one of four settings,
+// even though we break it down more in daSoundGroup for
+// future expansion.
+//
+// Parameters: group - group that we want trim for
+//
+// Return: trim value for that group, or 1.0f (max) if it doesn't fit
+//
+//=============================================================================
+daTrimValue daSoundTuner::GetGroupTrim( daSoundGroup group )
+{
+ if( IsSlaveGroup( group, SOUND_EFFECTS ) )
+ {
+ return( m_userVolumes.duckVolume[DUCK_SFX] );
+ }
+ else if( IsSlaveGroup( group, MUSIC ) )
+ {
+ return( m_userVolumes.duckVolume[DUCK_MUSIC] );
+ }
+ else if( IsSlaveGroup( group, DIALOGUE ) )
+ {
+ return( m_userVolumes.duckVolume[DUCK_DIALOG] );
+ }
+ else if( IsSlaveGroup( group, AMBIENCE ) )
+ {
+ return( m_userVolumes.duckVolume[DUCK_AMBIENCE] );
+ }
+ else if( IsSlaveGroup( group, CARSOUND ) )
+ {
+ return( m_userVolumes.duckVolume[DUCK_CAR] );
+ }
+ else if( IsSlaveGroup( group, OPTIONS_MENU_STINGERS ) )
+ {
+ //
+ // Special group for options menu, not affected by ducking
+ //
+ return( 1.0f );
+ }
+ else
+ {
+ //
+ // None of the above. We shouldn't get here
+ //
+ rAssert( false );
+ return( 1.0f );
+ }
+}
+
+//=============================================================================
+// daSoundTuner::SetFaderGroupTrim
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( Sound::DuckVolumes group, daTrimValue trim )
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::SetFaderGroupTrim( Sound::DuckVolumes group, daTrimValue trim )
+{
+ m_finalDuckLevels.duckVolume[group] = trim;
+}
+
+//=============================================================================
+// daSoundTuner::GetFaderGroupTrim
+//=============================================================================
+// Description: Get the fader trim associated with a particular sound group.
+// Actually, our "group" is currently one of four settings,
+// even though we break it down more in daSoundGroup for
+// future expansion.
+//
+// Parameters: group - group that we want trim for
+//
+// Return: trim value for that group, or 1.0f (max) if it doesn't fit
+//
+//=============================================================================
+daTrimValue daSoundTuner::GetFaderGroupTrim( daSoundGroup group )
+{
+ if( IsSlaveGroup( group, SOUND_EFFECTS ) )
+ {
+ return( m_finalDuckLevels.duckVolume[DUCK_SFX] );
+ }
+ else if( IsSlaveGroup( group, MUSIC ) )
+ {
+ return( m_finalDuckLevels.duckVolume[DUCK_MUSIC] );
+ }
+ else if( IsSlaveGroup( group, DIALOGUE ) )
+ {
+ return( m_finalDuckLevels.duckVolume[DUCK_DIALOG] );
+ }
+ else if( IsSlaveGroup( group, AMBIENCE ) )
+ {
+ return( m_finalDuckLevels.duckVolume[DUCK_AMBIENCE] );
+ }
+ else if( IsSlaveGroup( group, CARSOUND ) )
+ {
+ return( m_finalDuckLevels.duckVolume[DUCK_CAR] );
+ }
+ else if( IsSlaveGroup( group, OPTIONS_MENU_STINGERS ) )
+ {
+ //
+ // Special group for options menu, not affected by ducking
+ //
+ return( 1.0f );
+ }
+ else
+ {
+ //
+ // None of the above. We shouldn't get here
+ //
+ rAssert( false );
+ return( 1.0f );
+ }
+}
+
+void daSoundTuner::MuteNIS()
+{
+ m_NISTrim = GetGroupTrim( NIS );
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( NIS, 0.0f );
+}
+
+void daSoundTuner::UnmuteNIS()
+{
+ daSoundRenderingManagerGet()->GetPlayerManager()->PlayerVolumeChange( NIS, m_NISTrim );
+}
+
+//=============================================================================
+// Private functions
+//=============================================================================
+
+void daSoundTuner::activateDuckInternal( IDaSoundFadeState* pObject,
+ void* pUserData,
+ bool fadeOut,
+ Fader* faderObj )
+{
+ DuckVolumeSet currentVolumes;
+
+#ifndef RAD_RELEASE
+ //
+ // Hack for fader tuning. The tuners usually only read the fader
+ // settings at startup, but we want them to pick up changes in radTuner
+ // on the fly. We'll make it refresh on each duck attempt in debug
+ // and tune builds.
+ //
+ refreshFaderSettings();
+#endif
+
+ if( m_activeFadeInfo != NULL )
+ {
+ //
+ // Get the current fader's settings and throw it on the stack
+ //
+ m_activeFadeInfo->StoreCurrentVolumes( currentVolumes );
+
+ //
+ // Now we can get rid of the old fader
+ //
+ delete m_activeFadeInfo;
+ m_activeFadeInfo = NULL;
+ }
+ else
+ {
+ calculateDuckedVolumes( currentVolumes );
+ }
+
+ // Use our duck fader...
+ FadeSounds( pObject,
+ pUserData,
+ faderObj,
+ fadeOut,
+ &currentVolumes );
+}
+
+//=============================================================================
+// daSoundTuner::calculateDuckedVolumes
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( DuckVolumeSet& volumes )
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::calculateDuckedVolumes( DuckVolumeSet& volumes )
+{
+ unsigned int i, j;
+
+ //
+ // Calculate target volumes
+ //
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ volumes.duckVolume[i] = 1.0f;
+ }
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ for( j = 0; j < NUM_DUCK_SITUATIONS; j++ )
+ {
+ if( m_duckLevels[j].duckVolume[i] < volumes.duckVolume[i] )
+ {
+ volumes.duckVolume[i] = m_duckLevels[j].duckVolume[i];
+ }
+ }
+ }
+}
+
+//=============================================================================
+// daSoundTuner::refreshFaderSettings
+//=============================================================================
+// Description: Reset the duck settings for each fader
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::refreshFaderSettings()
+{
+ IRadNameSpace* nameSpace;
+ globalSettings* settingsObj;
+ unsigned int i;
+
+ nameSpace = Sound::daSoundRenderingManagerGet()->GetTuningNamespace();
+ rAssert( nameSpace != NULL );
+
+ settingsObj = reinterpret_cast<globalSettings*>( nameSpace->GetInstance( "tuner" ) );
+ rAssert( settingsObj != NULL );
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ m_situationFaders[i]->ReinitializeFader( settingsObj );
+ }
+}
+
+//=============================================================================
+// daSoundTuner::serviceDebugInfo
+//=============================================================================
+// Description: Send some debug stuff to be dumped on the screen
+//
+// Parameters: None
+//
+// Return: void
+//
+//=============================================================================
+void daSoundTuner::serviceDebugInfo()
+{
+#ifdef SOUND_DEBUG_INFO_ENABLED
+ unsigned int i;
+ unsigned int j;
+
+ for( i = 0; i < NUM_DUCK_SITUATIONS; i++ )
+ {
+ for( j = 0; j < NUM_DUCK_VOLUMES; j++ )
+ {
+ m_debugPage.SetDuckLevel( static_cast<Sound::DuckSituations>(i),
+ static_cast<Sound::DuckVolumes>(j),
+ m_duckLevels[i].duckVolume[j] );
+ }
+ }
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ m_debugPage.SetFinalDuckLevel( static_cast<Sound::DuckVolumes>(i), m_finalDuckLevels.duckVolume[i] );
+ }
+
+ for( i = 0; i < NUM_DUCK_VOLUMES; i++ )
+ {
+ m_debugPage.SetUserVolume( static_cast<Sound::DuckVolumes>(i), m_userVolumes.duckVolume[i] );
+ }
+#endif
+}
+
+//=============================================================================
+// Factory functions
+//=============================================================================
+
+//=============================================================================
+// Function: daSoundTunerCreate
+//=============================================================================
+// Description: Create the tuner
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTunerCreate
+(
+ IDaSoundTuner** ppTuner,
+ radMemoryAllocator allocator
+)
+{
+ rAssert( ppTuner != NULL );
+ (*ppTuner) = new ( allocator ) daSoundTuner( );
+ (*ppTuner)->AddRef( );
+}
+
+} // Sound Namespace
diff --git a/game/code/sound/soundrenderer/soundtuner.h b/game/code/sound/soundrenderer/soundtuner.h
new file mode 100644
index 0000000..93aa9f9
--- /dev/null
+++ b/game/code/sound/soundrenderer/soundtuner.h
@@ -0,0 +1,253 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: soundtuner.hpp
+//
+// Subsystem: Dark Angel - Sound Tuner System
+//
+// Description: Description of the DA sound tuner
+//
+// Revisions:
+// + Created October 4, 2001 -- breimer
+//
+//=============================================================================
+
+#ifndef _SOUNDTUNER_HPP
+#define _SOUNDTUNER_HPP
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <raddebug.hpp>
+#include <radlinkedclass.hpp>
+
+#include <sound/soundrenderer/dasoundgroup.h>
+
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/fader.h>
+#include <sound/soundrenderer/tunerdebugpage.h>
+
+//=============================================================================
+// Global namespace forward declarations
+//=============================================================================
+
+struct IDaSoundResource;
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Prototypes
+//=============================================================================
+
+class daSoundTuner;
+
+//=============================================================================
+// Forward declarations
+//=============================================================================
+
+//=============================================================================
+// Class Declarations
+//=============================================================================
+
+//
+// A fade state information structure stores necessary information about
+// an active fade.
+//
+class daSoundTuner_ActiveFadeInfo
+{
+public:
+
+ // Constructor and destructor
+ daSoundTuner_ActiveFadeInfo
+ (
+ Fader* pFader,
+ bool pFadingIn,
+ IDaSoundFadeState* pDoneCallback,
+ void* pCallbackUserData,
+ DuckVolumeSet* initialVolumes,
+ DuckVolumeSet* targetVolumes
+ );
+ virtual ~daSoundTuner_ActiveFadeInfo( );
+
+ // Process the fader
+ bool ProcessFader();
+
+ void StoreCurrentVolumes( DuckVolumeSet& volumeSet );
+ void StoreTargetSettings( DuckVolumeSet& volumeSet );
+
+ Sound::DuckSituations GetSituation() { return( m_pFader->GetSituation() ); }
+
+private:
+ // Store the raw data
+ Fader* m_pFader;
+ bool m_FadingIn;
+ IDaSoundFadeState* m_pDoneCallback;
+ void* m_pCallbackUserData;
+};
+
+//
+// The sound tuner. All controls associated with the tuner have
+// a scripted sister componenet available for composers to modify
+// using radtuner.
+//
+class daSoundTuner : public IDaSoundTuner,
+ public radRefCount
+{
+public:
+ IMPLEMENT_REFCOUNTED( "daSoundTuner" );
+
+ //
+ // Constructor and destructor
+ //
+ daSoundTuner( );
+ virtual ~daSoundTuner( );
+
+ //
+ // IDaSoundTuner
+ //
+ void Initialize( void );
+ void PostScriptLoadInitialize();
+ void ServiceOncePerFrame( unsigned int elapsedTime );
+
+ void SetSoundOutputMode
+ (
+ SoundOutputMode outputMode
+ );
+ SoundOutputMode GetSoundOutputMode( void );
+
+ void ActivateDuck
+ (
+ IDaSoundFadeState* pObject,
+ void* pUserData,
+ bool fadeIn
+ );
+
+ void ActivateSituationalDuck( IDaSoundFadeState* pObject,
+ DuckSituations situation,
+ void* pUserData,
+ bool fadeIn );
+
+ void ResetDuck();
+
+ void SetMasterVolume( daTrimValue volume );
+ daTrimValue GetMasterVolume( void );
+
+ void SetDialogueVolume( daTrimValue volume );
+ daTrimValue GetDialogueVolume( void );
+
+ void SetMusicVolume( daTrimValue volume );
+ daTrimValue GetMusicVolume( void );
+
+ void SetAmbienceVolume( daTrimValue volume );
+ daTrimValue GetAmbienceVolume( void );
+
+ void SetSfxVolume( daTrimValue volume );
+ daTrimValue GetSfxVolume( void );
+
+ void SetCarVolume( daTrimValue volume );
+ daTrimValue GetCarVolume( void );
+
+ daTrimValue GetGroupTrim( daSoundGroup group );
+ daTrimValue GetFaderGroupTrim( daSoundGroup group );
+
+ void MuteNIS();
+ void UnmuteNIS();
+
+ void SetFaderGroupTrim( Sound::DuckVolumes group, daTrimValue trim );
+
+ void FadeSounds( IDaSoundFadeState* pObject,
+ void* pUserData,
+ Fader* pFader,
+ bool fadeIn,
+ DuckVolumeSet* initialVolumes = NULL );
+
+ //
+ // IDaSoundWiring
+ //
+ void WirePath
+ (
+ daSoundGroup soundGroup,
+ const char* path
+ );
+
+ void WireGroup( daSoundGroup slaveGroup, daSoundGroup masterGroup );
+
+ //
+ // Sound group info
+ //
+ bool IsSlaveGroup( daSoundGroup slave, daSoundGroup master );
+
+protected:
+ //
+ // Helper function for wiring knob paths
+ //
+ struct WirePathInfo
+ {
+ const char* m_Path;
+ size_t m_PathLen;
+ daSoundGroup m_SoundGroup;
+ };
+ static void WireKnobToPathHelper
+ (
+ IDaSoundResource* pRes,
+ void* pUserData
+ );
+
+private:
+
+ void activateDuckInternal( IDaSoundFadeState* pObject,
+ void* pUserData,
+ bool fadeOut,
+ Fader* faderObj );
+ void calculateDuckedVolumes( DuckVolumeSet& volumes );
+
+ void refreshFaderSettings();
+
+ void serviceDebugInfo();
+
+#ifdef SOUND_DEBUG_INFO_ENABLED
+ TunerDebugPage m_debugPage;
+#endif
+
+ //
+ // How many ducks to we have in progress?
+ //
+ DuckVolumeSet m_duckLevels[NUM_DUCK_SITUATIONS];
+
+ DuckVolumeSet m_finalDuckLevels;
+
+ //
+ // Store our duck faders
+ //
+ Fader* m_pDuckFade;
+
+ Fader* m_situationFaders[NUM_DUCK_SITUATIONS];
+
+ //
+ // Group volume settings
+ //
+ float m_MasterVolume;
+
+ DuckVolumeSet m_userVolumes;
+
+ //
+ // Our static sound group wirings
+ //
+ static short s_groupWirings[NUM_SOUND_GROUPS];
+
+ daSoundTuner_ActiveFadeInfo* m_activeFadeInfo;
+
+ //
+ // NIS hack
+ //
+ float m_NISTrim;
+};
+
+} // Sound Namespace
+#endif //_SOUNDTUNER_HPP
+
diff --git a/game/code/sound/soundrenderer/tunerdebugpage.cpp b/game/code/sound/soundrenderer/tunerdebugpage.cpp
new file mode 100644
index 0000000..a792952
--- /dev/null
+++ b/game/code/sound/soundrenderer/tunerdebugpage.cpp
@@ -0,0 +1,231 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: tunerdebugpage.cpp
+//
+// Description: Displays debug info for the sound tuner
+//
+// History: 6/11/2003 + Created -- NAME
+//
+//=============================================================================
+
+//========================================
+// System Includes
+//========================================
+
+//========================================
+// Project Includes
+//========================================
+#include <sound/soundrenderer/tunerdebugpage.h>
+
+const char* s_duckNames[Sound::NUM_DUCK_SITUATIONS] =
+{
+ "Full fade",
+ "Pause",
+ "Mission",
+ "Letterbox",
+ "Dialogue",
+ "Store",
+ "On foot",
+ "Minigame",
+ "Just Music",
+ "Credits"
+};
+
+//*****************************************************************************
+//
+// Global Data, Local Data, Local Classes
+//
+//*****************************************************************************
+
+//*****************************************************************************
+//
+// Public Member Functions
+//
+//*****************************************************************************
+
+//=============================================================================
+// TunerDebugPage::TunerDebugPage
+//=============================================================================
+// Description: Constructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//=============================================================================
+TunerDebugPage::TunerDebugPage()
+{
+ unsigned int i, j;
+
+ //
+ // Zero out the tuner values
+ //
+ for( i = 0; i < Sound::NUM_DUCK_SITUATIONS; i++ )
+ {
+ for( j = 0; j < Sound::NUM_DUCK_VOLUMES; j++ )
+ {
+ m_duckLevels[i].duckVolume[j] = 0.0f;
+ }
+ }
+
+ for( i = 0; i < Sound::NUM_DUCK_VOLUMES; i++ )
+ {
+ m_userVolumes.duckVolume[i] = 0.0f;
+ }
+}
+
+//=============================================================================
+// TunerDebugPage::~TunerDebugPage
+//=============================================================================
+// Description: Destructor.
+//
+// Parameters: None.
+//
+// Return: N/A.
+//
+//=============================================================================
+TunerDebugPage::~TunerDebugPage()
+{
+}
+
+//=============================================================================
+// TunerDebugPage::SetDuckLevel
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( DuckSituations situation, DuckVolumes volumeType, float volume )
+//
+// Return: void
+//
+//=============================================================================
+void TunerDebugPage::SetDuckLevel( Sound::DuckSituations situation,
+ Sound::DuckVolumes volumeType,
+ float volume )
+{
+ m_duckLevels[situation].duckVolume[volumeType] = volume;
+}
+
+//=============================================================================
+// TunerDebugPage::SetFinalDuckLevel
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( DuckVolumes volumeType, float volume )
+//
+// Return: void
+//
+//=============================================================================
+void TunerDebugPage::SetFinalDuckLevel( Sound::DuckVolumes volumeType, float volume )
+{
+ m_finalDuckLevel.duckVolume[volumeType] = volume;
+}
+
+//=============================================================================
+// TunerDebugPage::SetUserVolume
+//=============================================================================
+// Description: Comment
+//
+// Parameters: ( DuckVolumes volumeType, float volume )
+//
+// Return: void
+//
+//=============================================================================
+void TunerDebugPage::SetUserVolume( Sound::DuckVolumes volumeType, float volume )
+{
+ m_userVolumes.duckVolume[volumeType] = volume;
+}
+
+//*****************************************************************************
+//
+// Protected Member Functions
+//
+//*****************************************************************************
+
+//=============================================================================
+// TunerDebugPage::fillLineBuffer
+//=============================================================================
+// Description: Fill the given buffer with text to display on the screen
+// at the given line
+//
+// Parameters: lineNum - line number on screen where buffer will be displayed
+// buffer - to be filled in with text to display
+//
+// Return: void
+//
+//=============================================================================
+void TunerDebugPage::fillLineBuffer( int lineNum, char* buffer )
+{
+ switch( lineNum )
+ {
+ case 0:
+ strcpy( buffer, "Ducking volumes:" );
+ break;
+
+ case 1:
+ strcpy( buffer, " SFX Car Music Dialog Ambience" );
+ break;
+
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ case 9:
+ case 10:
+ case 11:
+ sprintf( buffer, "%s: %0.2f %0.2f %0.2f %0.2f %0.2f",
+ s_duckNames[lineNum-2],
+ m_duckLevels[lineNum-2].duckVolume[0],
+ m_duckLevels[lineNum-2].duckVolume[1],
+ m_duckLevels[lineNum-2].duckVolume[2],
+ m_duckLevels[lineNum-2].duckVolume[3],
+ m_duckLevels[lineNum-2].duckVolume[4] );
+ break;
+
+ case 13:
+ sprintf( buffer, "Final duck volumes: %0.2f %0.2f %0.2f %0.2f %0.2f",
+ m_finalDuckLevel.duckVolume[0],
+ m_finalDuckLevel.duckVolume[1],
+ m_finalDuckLevel.duckVolume[2],
+ m_finalDuckLevel.duckVolume[3],
+ m_finalDuckLevel.duckVolume[4] );
+ break;
+
+ case 15:
+ sprintf( buffer, "User volumes: %0.2f %0.2f %0.2f %0.2f %0.2f",
+ m_userVolumes.duckVolume[0],
+ m_userVolumes.duckVolume[1],
+ m_userVolumes.duckVolume[2],
+ m_userVolumes.duckVolume[3],
+ m_userVolumes.duckVolume[4] );
+ break;
+
+ default:
+ buffer[0] = '\0';
+ break;
+ }
+}
+
+//=============================================================================
+// DialogSoundDebugPage::getNumLines
+//=============================================================================
+// Description: Returns number of lines that we'll display on screen
+//
+// Parameters: None
+//
+// Return: Line count
+//
+//=============================================================================
+int TunerDebugPage::getNumLines()
+{
+ return( 16 );
+}
+
+//*****************************************************************************
+//
+// Private Member Functions
+//
+//*****************************************************************************
diff --git a/game/code/sound/soundrenderer/tunerdebugpage.h b/game/code/sound/soundrenderer/tunerdebugpage.h
new file mode 100644
index 0000000..b48797c
--- /dev/null
+++ b/game/code/sound/soundrenderer/tunerdebugpage.h
@@ -0,0 +1,68 @@
+//=============================================================================
+// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
+//
+// File: tunerdebugpage.h
+//
+// Description: Displays debug info for the sound tuner
+//
+// History: 6/11/2003 + Created -- Esan
+//
+//=============================================================================
+
+#ifndef TUNERDEBUGPAGE_H
+#define TUNERDEBUGPAGE_H
+
+//========================================
+// Nested Includes
+//========================================
+#include <sound/sounddebug/sounddebugpage.h>
+
+#include <sound/soundrenderer/dasoundgroup.h>
+
+//========================================
+// Forward References
+//========================================
+
+//=============================================================================
+//
+// Synopsis: TunerDebugPage
+//
+//=============================================================================
+
+class TunerDebugPage : public SoundDebugPage
+{
+ public:
+ TunerDebugPage();
+ virtual ~TunerDebugPage();
+
+ void SetDuckLevel( Sound::DuckSituations situation, Sound::DuckVolumes volumeType, float volume );
+ void SetFinalDuckLevel( Sound::DuckVolumes volumeType, float volume );
+ void SetUserVolume( Sound::DuckVolumes volumeType, float volume );
+
+ protected:
+ //
+ // Pure virtual functions from SoundDebugPage
+ //
+ void fillLineBuffer( int lineNum, char* buffer );
+ int getNumLines();
+
+ private:
+ //Prevent wasteful constructor creation.
+ TunerDebugPage( const TunerDebugPage& tunerdebugpage );
+ TunerDebugPage& operator=( const TunerDebugPage& tunerdebugpage );
+
+ //
+ // Ducking info
+ //
+ Sound::DuckVolumeSet m_duckLevels[Sound::NUM_DUCK_SITUATIONS];
+ Sound::DuckVolumeSet m_finalDuckLevel;
+ Sound::DuckVolumeSet m_userVolumes;
+};
+
+//*****************************************************************************
+//
+//Inline Public Member Functions
+//
+//*****************************************************************************
+
+#endif //TUNERDEBUGPAGE_H
diff --git a/game/code/sound/soundrenderer/wireplayers.cpp b/game/code/sound/soundrenderer/wireplayers.cpp
new file mode 100644
index 0000000..c63b138
--- /dev/null
+++ b/game/code/sound/soundrenderer/wireplayers.cpp
@@ -0,0 +1 @@
+// This page made intentially empty. \ No newline at end of file
diff --git a/game/code/sound/soundrenderer/wiresystem.cpp b/game/code/sound/soundrenderer/wiresystem.cpp
new file mode 100644
index 0000000..6582a16
--- /dev/null
+++ b/game/code/sound/soundrenderer/wiresystem.cpp
@@ -0,0 +1,104 @@
+//=============================================================================
+// Copyright (C) 2001 Radical Entertainment Ltd. All rights reserved.
+//
+// File: wiresystem.cpp
+//
+// Subsystem: Dark Angel - Sound Tuner System
+//
+// Description: Wire the tuner
+//
+// Revisions:
+// + Created October 24, 2001 -- breimer
+//
+//=============================================================================
+
+//=============================================================================
+// Included Files
+//=============================================================================
+
+#include <radobject.hpp>
+#include <raddebug.hpp>
+
+#include <radsound.hpp>
+#include <radsound_hal.hpp>
+
+#include <sound/soundrenderer/soundsystem.h>
+#include <sound/soundrenderer/idasoundtuner.h>
+#include <sound/soundrenderer/soundtuner.h>
+
+//=============================================================================
+// Define Owning Namespace
+//=============================================================================
+
+namespace Sound {
+
+//=============================================================================
+// Public functions
+//=============================================================================
+
+//=============================================================================
+// Function: ::daSoundTunerWireSystem
+//=============================================================================
+// Description: Wire the sound system
+//
+// NOTE: Music and ambience are ignored here, because they're controlled by
+// Radmusic and not us.
+//
+//-----------------------------------------------------------------------------
+
+void daSoundTunerWireSystem
+(
+ IDaSoundWiring* pWiring
+)
+{
+ // PATHS //////////////////////////////////////////////////////////////////
+
+ //
+ // Start by wiring up everything as dialogue by default. This is because
+ // we strip a little path info out of the dialogue files, so that we can
+ // easily switch between languages.
+ //
+ pWiring->WirePath( DIALOGUE, "" );
+
+ // Character
+ pWiring->WirePath
+ (
+ CARSOUND,
+ "sound\\carsound"
+ );
+
+ // Collision
+ pWiring->WirePath
+ (
+ NIS,
+ "sound\\nis"
+ );
+
+ pWiring->WirePath
+ (
+ SOUND_EFFECTS,
+ "sound\\soundfx"
+ );
+
+ pWiring->WirePath
+ (
+ OPTIONS_MENU_STINGERS,
+ "sound\\soundfx\\optionsmenu"
+ );
+
+ // SPECIAL GROUPS /////////////////////////////////////////////////////////
+
+ pWiring->WireGroup( NIS, DIALOGUE );
+
+ pWiring->WireGroup( DIALOGUE, DUCKABLE );
+ pWiring->WireGroup( SOUND_EFFECTS, DUCKABLE );
+ pWiring->WireGroup( CARSOUND, DUCKABLE );
+ pWiring->WireGroup( OPTIONS_MENU_STINGERS, DUCKABLE );
+
+ pWiring->WireGroup( DIALOGUE, DIALOGUE_TUNE );
+ pWiring->WireGroup( SOUND_EFFECTS, SOUND_EFFECTS_TUNE );
+ pWiring->WireGroup( MASTER, MASTER_TUNE );
+}
+
+
+} // Sound Namespace