diff options
Diffstat (limited to 'game/code/sound/soundloader.cpp')
-rw-r--r-- | game/code/sound/soundloader.cpp | 601 |
1 files changed, 601 insertions, 0 deletions
diff --git a/game/code/sound/soundloader.cpp b/game/code/sound/soundloader.cpp new file mode 100644 index 0000000..f0a2c64 --- /dev/null +++ b/game/code/sound/soundloader.cpp @@ -0,0 +1,601 @@ +//============================================================================= +// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved. +// +// File: soundloader.cpp +// +// Description: Implement SoundLoader class, which makes sure that sounds +// required in the game are allocated and resident in sound memory +// +// History: 26/06/2002 + Created -- Darren +// +//============================================================================= + +//======================================== +// System Includes +//======================================== + +//======================================== +// Project Includes +//======================================== +#include <stdio.h> + +#include <sound/soundloader.h> +#include <sound/soundrenderer/soundrenderingmanager.h> +#include <sound/soundrenderer/soundresourcemanager.h> + +#include <memory/srrmemory.h> +#include <loading/loadingmanager.h> +#include <worldsim/redbrick/vehicle.h> +#include <constants/vehicleenum.h> +#include <mission/gameplaymanager.h> +#include <events/eventmanager.h> +#include <worldsim/character/character.h> + +#include <radscript.hpp> + + +//****************************************************************************** +// +// Global Data, Local Data, Local Classes +// +//****************************************************************************** + +// +// Names of sound clusters. Used so that the loading manager can tell us +// when it's our turn to loading something. Should correspond to SoundClusterName +// enumeration +// +static const char* s_clusterNames[] = +{ + "permanent", + "frontend", + "ingame", + "suburbs", + "downtown", + "seaside", + "level1", + "level2", + "level3", + "level4", + "level5", + "level6", + "level7", + "minigame", + "huh?", + "apu", + "bart", + "homer", + "lisa", + "marge", + "bart_v", + "apu_v", + "snake_v", + "homer_v", + "famil_v", + "gramp_v", + "cletu_v", + "wiggu_v", + "empty1", + "marge_v", + "empty2", + "empty3", + "smith_v", + "empty4", + "empty5", + "empty6", + "zombi_v", + "empty7", + "empty8", + "cVan", + "compactA", + "comic_v", + "skinn_v", + "cCola", + "cSedan", + "cPolice", + "cCellA", + "cCellB", + "cCellC", + "cCellD", + "minivanA_v", + "pickupA", + "taxiA_v", + "sportsA", + "sportsB", + "SUVA", + "wagonA", + "hbike_v", + "burns_v", + "honor_v", + "cArmor", + "cCurator", + "cHears", + "cKlimo", + "cLimo", + "cNerd", + "frink_v", + "cMilk", + "cDonut", + "bbman_v", + "bookb_v", + "carhom_v", + "elect_v", + "fone_v", + "gramR_v", + "moe_v", + "mrplo_v", + "otto_v", + "plowk_v", + "scorp_v", + "willi_v", + "sedanA", + "sedanB", + "cBlbart", + "cCube", + "cDuff", + "cNonup", + "lisa_v", + "krust_v", + "coffin", + "hallo", + "ship", + "witchcar", + "huska", + "atv_v", + "dune_v", + "hype_v", + "knigh_v", + "mono_v", + "oblit_v", + "rocke_v", + "ambul", + "burnsarm", + "fishtruc", + "garbage", + "icecream", + "istruck", + "nuctruck", + "pizza", + "schoolbu", + "votetruc", + "glastruc", + "cfire_v", + "cBone", + "redbrick" +}; + +static const int NumScriptNames = sizeof( s_clusterNames ) / sizeof( const char* ); + +// +// Indices of character namespaces for each level. +// +// TODO: I don't like these tables, there must be a more data-driven way to do +// this. +// 0 == Apu +// 1 == Bart +// 2 == Homer +// 3 == Lisa +// 4 == Marge +// +static unsigned int s_charNamespaceIndices[] = { 2, 1, 3, 4, 0, 1, 2, 0 }; + +static VehicleEnum::VehicleID s_carIndices[] = { VehicleEnum::FAMIL_V, + VehicleEnum::HONOR_V, + VehicleEnum::LISA_V, + VehicleEnum::MARGE_V, + VehicleEnum::APU_V, + VehicleEnum::BART_V, + VehicleEnum::HOMER_V, + VehicleEnum::FAMIL_V, +}; + +static unsigned int s_levelIndices[] = { 0, 1, 2, 0, 1, 2, 0, 0 }; + +//****************************************************************************** +// +// Public Member Functions +// +//****************************************************************************** + +//============================================================================== +// SoundLoader::SoundLoader +//============================================================================== +// Description: Constructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +SoundLoader::SoundLoader() : + m_currentCluster( SC_ALWAYS_LOADED ) +{ + unsigned int i; + SoundClusterName clusterIndex; + Sound::daSoundRenderingManager* renderingMgr = Sound::daSoundRenderingManagerGet(); + + for( i = 0; i < SC_MAX_CLUSTERS; i++ ) + { + m_clusterList[i] = NULL; + } + + for( clusterIndex = SC_ALWAYS_LOADED; + clusterIndex < SC_CHAR_APU; + clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) ) + { + m_clusterList[clusterIndex] = + new(GMA_PERSISTENT) SoundCluster( clusterIndex, + renderingMgr->GetSoundNamespace() ); + } + + for( clusterIndex = SC_CHAR_APU; + clusterIndex < SC_CAR_BASE; + clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) ) + { + m_clusterList[clusterIndex] = + new(GMA_PERSISTENT) SoundCluster( clusterIndex, + renderingMgr->GetCharacterNamespace( clusterIndex - SC_CHAR_APU ) ); + } + + for( clusterIndex = SC_CAR_BASE; + clusterIndex < SC_MAX_CLUSTERS; + clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) ) + { + m_clusterList[clusterIndex] = + new(GMA_PERSISTENT) SoundCluster( clusterIndex, + renderingMgr->GetSoundNamespace() ); + } + + // + // Register event listeners + // + GetEventManager()->AddListener( this, EVENT_GETINTOVEHICLE_START ); +} + +//============================================================================== +// SoundLoader::~SoundLoader +//============================================================================== +// Description: Destructor. +// +// Parameters: None. +// +// Return: N/A. +// +//============================================================================== +SoundLoader::~SoundLoader() +{ + unsigned int i; + + for( i = 0; i < SC_MAX_CLUSTERS; i++ ) + { + if( m_clusterList[i] != NULL ) + { + m_clusterList[i]->Release(); + } + } + + GetEventManager()->RemoveAll( this ); +} + +//============================================================================= +// SoundLoader::LevelLoad +//============================================================================= +// Description: Loads the sound cluster for a particular level +// +// Parameters: RenderEnums::LevelEnum level - +// enumeration indicating the level whose sound cluster +// is to be loaded +// +// Return: void +// +//============================================================================= +void SoundLoader::LevelLoad( RenderEnums::LevelEnum level ) +{ + IRadNameSpace* charNamespace; + unsigned int levelNum; + + clusterUnload( SC_FRONTEND ); + + queueLoad( SC_INGAME ); + + if( GetGameplayManager()->IsSuperSprint() ) + { + queueLoad( SC_MINIGAME ); + } + else + { + rAssert( level <= RenderEnums::numLevels ); + levelNum = static_cast<unsigned int>(level); + + queueLoad( static_cast<SoundClusterName>( SC_LEVEL_SUBURBS + s_levelIndices[levelNum] ) ); + queueLoad( static_cast<SoundClusterName>( SC_CHAR_APU + s_charNamespaceIndices[levelNum] ) ); + queueLoad( static_cast<SoundClusterName>( SC_CAR_BASE + s_carIndices[levelNum] ) ); + queueLoad( static_cast<SoundClusterName>( SC_LEVEL1 + levelNum ) ); + + charNamespace = m_clusterList[SC_CHAR_APU + s_charNamespaceIndices[level]]->GetMyNamespace(); + rAssert( charNamespace != NULL ); + + // + // We need to do this for RadTuner, since we've got duplicate names and + // it won't necessarily find the correct character otherwise + // + charNamespace->MoveToFront(); + } +} + +//============================================================================= +// SoundLoader::LevelUnload +//============================================================================= +// Description: Unloads the sound cluster for a particular level +// +// Parameters: RenderEnums::LevelEnum level - +// enumeration indicating the level whose sound cluster +// is to be unloaded +// +// Return: void +// +//============================================================================= +void SoundLoader::LevelUnload( bool goingToFe ) +{ + SoundClusterName clusterIndex; + + // + // Unload everything that's not permanent + // + for( clusterIndex = SC_INGAME; + clusterIndex < SC_MAX_CLUSTERS; + clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) ) + { + if( m_clusterList[clusterIndex]->IsLoaded() ) + { + clusterUnload( clusterIndex ); + } + } + + if( goingToFe ) + { + queueLoad( SC_FRONTEND ); + } +} + +//============================================================================= +// SoundLoader::MissionLoad +//============================================================================= +// Description: Loads the sound cluster for a particular mission +// +// Parameters: RenderEnums::MissionEnum mission - +// enumeration indicating the mission whose sound cluster +// is to be loaded +// +// Return: void +// +//============================================================================= +void SoundLoader::MissionLoad( RenderEnums::MissionEnum mission ) +{ +} + +//============================================================================= +// SoundLoader::MissionUnload +//============================================================================= +// Description: Unloads the sound cluster for a particular mission +// +// Parameters: RenderEnums::MissionEnum mission - +// enumeration indicating the mission whose sound cluster +// is to be unloaded +// +// Return: void +// +//============================================================================= +void SoundLoader::MissionUnload( RenderEnums::MissionEnum mission ) +{ +} + +void SoundLoader::LoadCarSound( Vehicle* theCar, bool unloadOtherCars ) +{ + rAssert( theCar ); + + SoundClusterName clusterIndex; + SoundClusterName newCarCluster = static_cast<SoundClusterName>(SC_CAR_BASE + theCar->mVehicleID); + bool validCar = ( SC_CAR_BASE + theCar->mVehicleID ) < NumScriptNames; + + rAssertMsg( validCar, "A new vehicle has been added that the sound system does not have a script for. Tell Esan.\n" ); + + // + // Have we loaded this car already? + // + if( !validCar || m_clusterList[newCarCluster]->IsLoaded() ) + { + return; + } + + // + // Unload the existing car sound + // + if( unloadOtherCars ) + { + for( clusterIndex = SC_CAR_BASE; + clusterIndex < SC_MAX_CLUSTERS; + clusterIndex = static_cast<SoundClusterName>( clusterIndex + 1 ) ) + { + if( m_clusterList[clusterIndex]->IsLoaded() ) + { + clusterUnload( clusterIndex ); + } + } + } + + // + // Load the new car + // + queueLoad( newCarCluster ); +} + +//============================================================================= +// SoundLoader::IsSoundLoaded +//============================================================================= +// Description: Indicate whether a particular sound resource has been loaded +// +// Parameters: soundKey - hashed name of the sound resource to look for +// +// Return: true if loaded, falsed otherwise +// +//============================================================================= +bool SoundLoader::IsSoundLoaded( Sound::daResourceKey soundKey ) +{ + unsigned int i; + + for( i = 0; i < SC_MAX_CLUSTERS; i++ ) + { + if( ( m_clusterList[i] != NULL ) && ( m_clusterList[i]->ContainsResource( soundKey ) ) ) + { + return( m_clusterList[i]->IsLoaded() ); + } + } + + return( false ); +} + +//============================================================================= +// SoundLoader::LoadClusterByName +//============================================================================= +// Description: Given a cluster name from the loading manager, load the +// desired cluster +// +// Parameters: clusterName - text name for the cluster +// callbackObj - loading file handler to notify on completion +// +// Return: true if cluster already loaded, false otherwise +// +//============================================================================= +bool SoundLoader::LoadClusterByName( const char* clusterName, SoundFileHandler* callbackObj ) +{ + const char* shortName; + unsigned int i; + + // Strip out the "sound:" prefix + rAssert( strlen( clusterName ) > 6 ); + shortName = &(clusterName[6]); + + // + // Find the matching cluster name + // + for( i = 0; i < SC_MAX_CLUSTERS; i++ ) + { + if( strcmp( shortName, s_clusterNames[i] ) == 0 ) + { + return( clusterLoad( static_cast<SoundClusterName>( i ), callbackObj ) ); + } + } + + // + // If we get here, cluster not found + // + rAssert( false ); + return( false ); +} + +//============================================================================= +// SoundLoader::HandleEvent +//============================================================================= +// Description: Comment +// +// Parameters: ( EventEnum id, void* pEventData ) +// +// Return: void +// +//============================================================================= +void SoundLoader::HandleEvent( EventEnum id, void* pEventData ) +{ + Character* theCharacter; + Vehicle* theCar; + + switch( id ) + { + case EVENT_GETINTOVEHICLE_START: + // + // Make sure we've got the correct car sound for this vehicle + // + theCharacter = static_cast<Character*>(pEventData); + rAssert( theCharacter != NULL ); + theCar = theCharacter->GetTargetVehicle(); + rAssert( theCar != NULL ); + + LoadCarSound( theCar, true ); + break; + + default: + rAssert( false ); + break; + } +} + +//****************************************************************************** +// +// Private Member Functions +// +//****************************************************************************** + +//============================================================================= +// SoundLoader::queueLoad +//============================================================================= +// Description: Queue a cluster load with the loading manager +// +// Parameters: cluster - name of cluster to queue +// +// Return: void +// +//============================================================================= +void SoundLoader::queueLoad( SoundClusterName cluster ) +{ + char fakeFilename[50]; + + // + // Create a pseudo filename that we'll give to the loading manager. + // Content doesn't really matter, we'll just throw it out when the + // loading manager passes it back + // + if( cluster >= NumScriptNames ) + { + // + // Just load Bart for now + // + cluster = SC_CAR_BASE; + } + + sprintf( fakeFilename, "sound:%s", s_clusterNames[cluster] ); + GetLoadingManager()->AddRequest( FILEHANDLER_SOUND, fakeFilename, GMA_LEVEL_AUDIO ); +} + +//============================================================================= +// SoundLoader::clusterLoad +//============================================================================= +// Description: Find the specified sound cluster and direct it to load sounds +// +// Parameters: SoundClusterName name - specifies which cluster to load +// +// Return: false if cluster not yet loaded, true otherwise +// +//============================================================================= +bool SoundLoader::clusterLoad( SoundClusterName name, SoundFileHandler* callbackObj ) +{ + bool loaded; + + rAssert( name < SC_MAX_CLUSTERS ); + + loaded = m_clusterList[name]->IsLoaded(); + if( !loaded ) + { + m_clusterList[name]->LoadSounds( callbackObj ); + } + + return( loaded ); +} + +void SoundLoader::clusterUnload( SoundClusterName name ) +{ + rAssert( name < SC_MAX_CLUSTERS ); + if( m_clusterList[name]->IsLoaded() ) + { + m_clusterList[name]->UnloadSounds(); + } +}
\ No newline at end of file |