459 lines
14 KiB
C++
459 lines
14 KiB
C++
//=============================================================================
|
|
// Copyright (C) 2002 Radical Entertainment Ltd. All rights reserved.
|
|
//
|
|
// File: trafficsoundplayer.cpp
|
|
//
|
|
// Description: Administers the playing of sound for a traffic vehicle
|
|
//
|
|
// History: 1/4/2003 + Created -- Darren
|
|
//
|
|
//=============================================================================
|
|
|
|
//========================================
|
|
// System Includes
|
|
//========================================
|
|
#include <radnamespace.hpp>
|
|
|
|
//========================================
|
|
// Project Includes
|
|
//========================================
|
|
#include <sound/movingpositional/trafficsoundplayer.h>
|
|
|
|
#include <sound/soundrenderer/soundrenderingmanager.h>
|
|
#include <sound/soundfx/positionalsoundsettings.h>
|
|
#include <sound/avatar/carsoundparameters.h>
|
|
|
|
#include <worldsim/redbrick/vehicle.h>
|
|
#include <worldsim/redbrick/trafficlocomotion.h>
|
|
#include <worldsim/traffic/trafficmanager.h>
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Global Data, Local Data, Local Classes
|
|
//
|
|
//*****************************************************************************
|
|
|
|
IRadTimerList* TrafficSoundPlayer::s_timerList = NULL;
|
|
|
|
static const unsigned int s_minHonkShortMsecs = 250;
|
|
static const unsigned int s_maxHonkShortMsecs = 500;
|
|
static const unsigned int s_minHonkLongMsecs = 500;
|
|
static const unsigned int s_maxHonkLongMsecs = 1000;
|
|
static const unsigned int s_minHonkDelay = 250;
|
|
static const unsigned int s_maxHonkDelay = 500;
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Public Member Functions
|
|
//
|
|
//*****************************************************************************
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::TrafficSoundPlayer
|
|
//=============================================================================
|
|
// Description: Constructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//=============================================================================
|
|
TrafficSoundPlayer::TrafficSoundPlayer( ) :
|
|
m_hornTimer( NULL ),
|
|
m_vehicleParameters( NULL ),
|
|
m_honkCount( 0 ),
|
|
m_pitchMultiplier( 1.0f )
|
|
{
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::~TrafficSoundPlayer
|
|
//=============================================================================
|
|
// Description: Destructor.
|
|
//
|
|
// Parameters: None.
|
|
//
|
|
// Return: N/A.
|
|
//
|
|
//=============================================================================
|
|
TrafficSoundPlayer::~TrafficSoundPlayer()
|
|
{
|
|
if( m_hornTimer != NULL )
|
|
{
|
|
m_hornTimer->UnregisterCallback( this );
|
|
m_hornTimer->Release();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::InitializeClass
|
|
//=============================================================================
|
|
// Description: Prep the timer list for tracking horn times
|
|
//
|
|
// Parameters: numVehicles - number of cars, and therefore timers we need
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::InitializeClass( unsigned int numVehicles )
|
|
{
|
|
if( s_timerList == NULL )
|
|
{
|
|
::radTimeCreateList( &s_timerList, numVehicles, GMA_AUDIO_PERSISTENT );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::Activate
|
|
//=============================================================================
|
|
// Description: Before we start playing any sound, set a random pitch adjustment
|
|
// to give this thing a little variety
|
|
//
|
|
// Parameters: soundSettings - positional stuff for traffic
|
|
// resourceName - name of engine sound
|
|
// theCar - pointer to traffic vehicle object
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::Activate( positionalSoundSettings* soundSettings,
|
|
const char* resourceName,
|
|
Vehicle* theCar )
|
|
{
|
|
unsigned int randomNumber;
|
|
|
|
//
|
|
// Pick a random pitch multiplier from 0.8 to 1.2. Arbitrary numbers.
|
|
//
|
|
randomNumber = rand() % 401;
|
|
m_pitchMultiplier = 0.8f + ( static_cast<float>(randomNumber) / 1000.0f );
|
|
|
|
VehiclePositionalSoundPlayer::Activate( soundSettings, resourceName, theCar );
|
|
|
|
m_player.SetPitch( 0.5f );
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::Deactivate
|
|
//=============================================================================
|
|
// Description: Stop playing sound.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::Deactivate()
|
|
{
|
|
VehiclePositionalSoundPlayer::Deactivate();
|
|
|
|
if( m_hornTimer != NULL )
|
|
{
|
|
m_hornTimer->UnregisterCallback( this );
|
|
m_hornTimer->Release();
|
|
m_hornTimer = NULL;
|
|
}
|
|
|
|
m_hornPlayer.Stop();
|
|
|
|
m_overlayPlayer.Stop();
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::ServiceOncePerFrame
|
|
//=============================================================================
|
|
// Description: Adjust the pitch for this vehicle
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::ServiceOncePerFrame()
|
|
{
|
|
float pitch;
|
|
|
|
VehiclePositionalSoundPlayer::ServiceOncePerFrame();
|
|
|
|
//
|
|
// Adjust pitch for vehicle speed if desired. I'll probably need to
|
|
// expose this for designer tuning later.
|
|
//
|
|
if( IsActive() && m_tiePitchToVelocity )
|
|
{
|
|
pitch = 0.5f + ( 0.5f * ( m_vehicle->mTrafficLocomotion->mActualSpeed / TrafficManager::GetInstance()->GetDesiredTrafficSpeed() ) );
|
|
pitch *= m_pitchMultiplier;
|
|
|
|
//
|
|
// Arbitrary cap, just in case. Being paranoid.
|
|
//
|
|
if( pitch > 1.5f )
|
|
{
|
|
pitch = 1.5f;
|
|
}
|
|
|
|
m_player.SetPitch( pitch );
|
|
}
|
|
|
|
m_hornPlayer.ServiceOncePerFrame();
|
|
m_overlayPlayer.ServiceOncePerFrame();
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::ServiceTimerList
|
|
//=============================================================================
|
|
// Description: Service the timer list. Static function, since we only
|
|
// need to service this static member once per frame, not once
|
|
// per object per frame.
|
|
//
|
|
// Parameters: None
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::ServiceTimerList()
|
|
{
|
|
if( s_timerList != NULL )
|
|
{
|
|
s_timerList->Service();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::OnTimerDone
|
|
//=============================================================================
|
|
// Description: Stop the traffic horn associated with this timer
|
|
//
|
|
// Parameters: elapsedTime - unused
|
|
// pUserData - unused
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::OnTimerDone( unsigned int elapsedTime, void * pUserData )
|
|
{
|
|
unsigned int timeout;
|
|
rmt::Vector position;
|
|
positionalSoundSettings* settings;
|
|
IRadNameSpace* nameSpace;
|
|
|
|
if( m_hornPlayer.IsInUse() )
|
|
{
|
|
m_hornPlayer.Stop();
|
|
|
|
if( m_honkCount == 0 )
|
|
{
|
|
//
|
|
// Last honk done
|
|
//
|
|
m_hornTimer->Release();
|
|
m_hornTimer = NULL;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Random amount of silence before next honk
|
|
//
|
|
timeout = s_minHonkDelay + ( rand() % ( s_maxHonkDelay - s_minHonkDelay ) );
|
|
m_hornTimer->SetTimeout( timeout );
|
|
m_hornTimer->Start();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Silence done, start another honk
|
|
//
|
|
rAssert( m_honkCount > 0 );
|
|
|
|
//
|
|
// Find the settings for this positional sound first
|
|
//
|
|
nameSpace = Sound::daSoundRenderingManagerGet()->GetTuningNamespace();
|
|
rAssert( nameSpace != NULL );
|
|
settings = reinterpret_cast<positionalSoundSettings*>( nameSpace->GetInstance( "traffic_horn" ) );
|
|
rAssert( settings != NULL );
|
|
|
|
m_vehicle->GetPosition( &position );
|
|
m_hornPlayer.SetPosition( position.x, position.y, position.z );
|
|
m_hornPlayer.SetPositionCarrier( *this );
|
|
m_hornPlayer.SetParameters( settings );
|
|
m_hornPlayer.PlaySound( "horn" );
|
|
|
|
--m_honkCount;
|
|
|
|
//
|
|
// Reset the timer
|
|
//
|
|
if( m_honkCount > 0 )
|
|
{
|
|
timeout = s_minHonkShortMsecs + ( rand() % ( s_maxHonkShortMsecs - s_minHonkShortMsecs ) );
|
|
}
|
|
else
|
|
{
|
|
timeout = s_minHonkLongMsecs + ( rand() % ( s_maxHonkLongMsecs - s_minHonkLongMsecs ) );
|
|
}
|
|
|
|
m_hornTimer->SetTimeout( timeout );
|
|
m_hornTimer->Start();
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::HonkHorn
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ()
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::HonkHorn()
|
|
{
|
|
unsigned int hornTime;
|
|
rmt::Vector position;
|
|
positionalSoundSettings* settings;
|
|
IRadNameSpace* nameSpace;
|
|
IRefCount* nameSpaceObj;
|
|
float diceRoll;
|
|
float probability;
|
|
|
|
rAssert( m_vehicle != NULL );
|
|
|
|
if( m_hornTimer != NULL )
|
|
{
|
|
//
|
|
// Already honking
|
|
//
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Find the settings for this positional sound first
|
|
//
|
|
nameSpace = Sound::daSoundRenderingManagerGet()->GetTuningNamespace();
|
|
rAssert( nameSpace != NULL );
|
|
nameSpaceObj = nameSpace->GetInstance( "traffic_horn" );
|
|
if( nameSpaceObj != NULL )
|
|
{
|
|
settings = reinterpret_cast<positionalSoundSettings*>( nameSpaceObj );
|
|
|
|
probability = settings->GetPlaybackProbability();
|
|
if( probability < 1.0f )
|
|
{
|
|
//
|
|
// Random play
|
|
//
|
|
diceRoll = (static_cast<float>( rand() % 100 )) / 100.0f;
|
|
if( diceRoll >= probability )
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Pick a random number of honks from 1 to 3. Pick a random time for
|
|
// the honk, giving the last one a better chance of being longer.
|
|
//
|
|
m_honkCount = rand() % 3;
|
|
if( m_honkCount > 0 )
|
|
{
|
|
hornTime = s_minHonkShortMsecs + ( rand() % ( s_maxHonkShortMsecs - s_minHonkShortMsecs ) );
|
|
}
|
|
else
|
|
{
|
|
hornTime = s_minHonkLongMsecs + ( rand() % ( s_maxHonkLongMsecs - s_minHonkLongMsecs ) );
|
|
}
|
|
|
|
s_timerList->CreateTimer( &m_hornTimer, hornTime, this, NULL, true,
|
|
IRadTimer::ResetModeOneShot );
|
|
|
|
//
|
|
// Start honking
|
|
//
|
|
m_vehicle->GetPosition( &position );
|
|
m_hornPlayer.SetPosition( position.x, position.y, position.z );
|
|
m_hornPlayer.SetPositionCarrier( *this );
|
|
m_hornPlayer.SetParameters( settings );
|
|
m_hornPlayer.PlaySound( "horn" );
|
|
}
|
|
else
|
|
{
|
|
rDebugString( "Couldn't find settings for traffic horn\n" );
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::AddOverlayClip
|
|
//=============================================================================
|
|
// Description: Play a positional clip along with the engine
|
|
//
|
|
// Parameters: parameters - car sound description for traffic vehicle
|
|
// posnSettingsName - name of object with positional settings
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::AddOverlayClip( carSoundParameters* parameters, const char* posnSettingsName )
|
|
{
|
|
const char* clipName;
|
|
positionalSoundSettings* settings;
|
|
IRadNameSpace* nameSpace;
|
|
IRefCount* nameSpaceObj;
|
|
rmt::Vector position;
|
|
|
|
rAssert( parameters != NULL );
|
|
|
|
m_vehicleParameters = parameters;
|
|
clipName = parameters->GetOverlayClipName();
|
|
if( clipName != NULL )
|
|
{
|
|
nameSpace = Sound::daSoundRenderingManagerGet()->GetTuningNamespace();
|
|
rAssert( nameSpace != NULL );
|
|
nameSpaceObj = nameSpace->GetInstance( posnSettingsName );
|
|
if( nameSpaceObj != NULL )
|
|
{
|
|
settings = reinterpret_cast<positionalSoundSettings*>( nameSpaceObj );
|
|
|
|
m_vehicle->GetPosition( &position );
|
|
m_overlayPlayer.SetPosition( position.x, position.y, position.z );
|
|
m_overlayPlayer.SetPositionCarrier( *this );
|
|
m_overlayPlayer.SetParameters( settings );
|
|
m_overlayPlayer.PlaySound( clipName );
|
|
}
|
|
else
|
|
{
|
|
rTuneAssertMsg( false, "Huh? Positional settings for overlay clip disappeared" );
|
|
}
|
|
}
|
|
}
|
|
|
|
//=============================================================================
|
|
// TrafficSoundPlayer::ToggleOverlayClip
|
|
//=============================================================================
|
|
// Description: Comment
|
|
//
|
|
// Parameters: ( carSoundParameters* parameters, const char* posnSettingsName )
|
|
//
|
|
// Return: void
|
|
//
|
|
//=============================================================================
|
|
void TrafficSoundPlayer::ToggleOverlayClip( carSoundParameters* parameters, const char* posnSettingsName )
|
|
{
|
|
if( m_overlayPlayer.IsInUse() )
|
|
{
|
|
m_overlayPlayer.Stop();
|
|
}
|
|
else
|
|
{
|
|
AddOverlayClip( parameters, posnSettingsName );
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
// Private Member Functions
|
|
//
|
|
//*****************************************************************************
|