/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
//////////////////////////////////////////////////////////////////////////////
// //
// plSound.h - Base sound class header //
// //
//// History /////////////////////////////////////////////////////////////////
// //
// 10.12.01 mcn - Added preliminary soft region (volume) support. //
// 7.12.02 mcn - Added EAX support //
// 7.15.02 mcn - Added support for animated volumes //
// //
//////////////////////////////////////////////////////////////////////////////
#ifndef plSound_h
#define plSound_h
#include "hsTemplates.h"
#include "hsGeometry3.h"
#include "plEAXEffects.h"
#include "pnNetCommon/plSynchedObject.h"
#include "plAvatar/plAGChannel.h"
#include "plAvatar/plAGApplicator.h"
#include "plAudioCore/plSoundBuffer.h"
class hsResMgr;
class hsStream;
class plSoundProxy;
class plDrawableSpans;
class hsGMaterial;
class plSoundMsg;
class plSoftVolume;
class plGraphPlate;
struct hsMatrix44;
class plSoundBuffer;
class plSceneObject;
class plSoundVolumeApplicator;
// Set this to 1 to do our own distance attenuation (model doesn't work yet tho)
#define MCN_HACK_OUR_ATTEN 0
#define MAX_INCIDENTALS 4
class plSound : public plSynchedObject
{
friend class plSoundSDLModifier;
friend class plSoundVolumeApplicator;
public:
plSound();
virtual ~plSound();
CLASSNAME_REGISTER( plSound );
GETINTERFACE_ANY( plSound, plSynchedObject );
enum Property
{
kPropIs3DSound = 0x00000001,
kPropDisableLOD = 0x00000002,
kPropLooping = 0x00000004,
kPropAutoStart = 0x00000008,
kPropLocalOnly = 0x00000010, // Disables network synching and triggering
kPropLoadOnlyOnCall = 0x00000020, // Only load and unload when we're told to
kPropFullyDisabled = 0x00000040, // This sound should never play while this is set
// Only plWin32LinkSound uses it. Placed here as a TODO though...
kPropDontFade = 0x00000080,
kPropIncidental = 0x00000100 // Incidental sound, will be played thru the incidental manager
};
enum Type
{
kStartType,
kSoundFX = kStartType, // For now, 3D sounds are always marked as this
kAmbience,
kBackgroundMusic,
kGUISound,
kNPCVoices,
kNumTypes
};
enum Refs
{
kRefSoftVolume = 0,
kRefDataBuffer, // plugins only
kRefParentSceneObject,
kRefSoftOcclusionRegion
};
enum
{
kSoftRegion = 0
};
enum StreamType
{
kNoStream,
kStreamFromRAM,
kStreamFromDisk,
kStreamCompressed
};
class plFadeParams
{
friend class plSound;
public:
enum Type
{
kLinear,
kLogarithmic,
kExponential
};
hsScalar fLengthInSecs; // Time to take to fade
hsScalar fVolStart; // Set one of these two for fade in/out,
hsScalar fVolEnd; // the other becomes the current volume
UInt8 fType;
hsBool fStopWhenDone; // Actually stop the sound once the fade is complete
hsBool fFadeSoftVol; // Fade the soft volume instead of fCurrVolume
plFadeParams() { fLengthInSecs = 0.f; fCurrTime = -1.f; fStopWhenDone = false; fFadeSoftVol = false; fVolStart = fVolEnd = 0.f; fType = kLinear; }
plFadeParams( Type type, hsScalar len, hsScalar start, hsScalar end )
{
fLengthInSecs = len; fVolStart = start; fVolEnd = end; fType = type;
fStopWhenDone = false;
fFadeSoftVol = false;
}
void Read( hsStream *s );
void Write( hsStream *s );
hsScalar InterpValue( void );
protected:
hsScalar fCurrTime; // -1 if we aren't active, else it's how far we're into the animation
};
virtual hsBool LoadSound( hsBool is3D ) = 0;
hsScalar GetVirtualStartTime( void ) const { return (hsScalar)fVirtualStartTime; }
virtual void Play();
void SynchedPlay( unsigned bytes );
void SynchedPlay( hsScalar virtualStartTime );
virtual void Stop();
virtual void FastForwardPlay();
virtual void FastForwardToggle();
virtual void SetMin(const int m); // sets minimum falloff distance
virtual void SetMax(const int m); // sets maximum falloff distance
virtual int GetMin() const;
virtual int GetMax() const;
virtual void SetVolume(const float volume);
virtual float GetVolume(void) const { return fCurrVolume; }
hsScalar GetMaxVolume() { return fMaxVolume; }
virtual hsBool IsPlaying() { return fPlaying; }
void SetTime(double t);
virtual double GetTime( void ) { return 0.f; }
virtual void Activate(hsBool forcePlay = false);
virtual void DeActivate();
virtual void SetLength(double l) { fLength = l; }
virtual void SetMuted( hsBool muted );
virtual hsBool IsMuted( void ) { return fMuted; }
void Disable() { fDistAttenuation = 0; }
virtual plSoundMsg* GetStatus(plSoundMsg* pMsg){return NULL;}
virtual void SetConeOrientation(hsScalar x, hsScalar y, hsScalar z);
virtual void SetOuterVolume( const int v ); // volume for the outer cone (if applicable)
virtual void SetConeAngles( int inner, int outer );
virtual void SetPosition(const hsPoint3 pos);
virtual void SetVelocity(const hsVector3 vel);
virtual hsPoint3 GetPosition() const;
virtual hsVector3 GetVelocity() const;
virtual void Update();
plSoundBuffer * GetDataBuffer( void ) const { return (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); }
hsScalar QueryCurrVolume( void ) const; // Returns the current volume, attenuated
const char * GetFileName( void ) const;
virtual double GetLength();
void SetProperty( Property prop, hsBool on ) { if( on ) fProperties |= prop; else fProperties &= ~prop; }
hsBool IsPropertySet( Property prop ) const { return ( fProperties & prop ) ? true : false; }
virtual void RefreshVolume( void );
virtual void SetStartPos(unsigned bytes) = 0;
virtual unsigned GetByteOffset(){return 0;}
virtual float GetActualTimeSec() = 0;
virtual void AddCallbacks(plSoundMsg* pMsg) = 0;
virtual void RemoveCallbacks(plSoundMsg* pMsg) = 0;
virtual UInt8 GetChannelSelect( void ) const { return 0; } // Only defined on Win32Sound right now, should be here tho
virtual void Read(hsStream* s, hsResMgr* mgr);
virtual void Write(hsStream* s, hsResMgr* mgr);
virtual void SetFadeInEffect( plFadeParams::Type type, hsScalar length );
virtual void SetFadeOutEffect( plFadeParams::Type type, hsScalar length );
virtual hsScalar CalcSoftVolume( hsBool enable, hsScalar distToListenerSquared );
virtual void UpdateSoftVolume( hsBool enable, hsBool firstTime = false );
virtual hsBool MsgReceive( plMessage* pMsg );
virtual hsBool DirtySynchState( const char *sdlName = nil, UInt32 sendFlags = 0 ); // call when state has changed
// Tests whether this sound is within range of the given position, not counting soft regions
hsBool IsWithinRange( const hsPoint3 &listenerPos, hsScalar *distSquared );
// Type setting and getting, from the Types enum
void SetType( UInt8 type ) { fType = type; }
UInt8 GetType( void ) const { return fType; }
// Priority stuff
void SetPriority( UInt8 pri ) { fPriority = pri; }
UInt8 GetPriority( void ) const { return fPriority; }
// Visualization
virtual plDrawableSpans* CreateProxy(const hsMatrix44& l2w, hsGMaterial* mat, hsTArray& idx, plDrawableSpans* addTo);
// Forced loading/unloading (for when the audio system's LOD just doesn't cut it)
virtual void ForceLoad( );
virtual void ForceUnload( void );
// Note: ONLY THE AUDIOSYS SHOULD CALL THIS. If you're not the audioSys, get lost.
static void SetCurrDebugPlate( const plKey soundKey );
void RegisterOnAudioSys( void );
void UnregisterOnAudioSys( void );
// Also only for the audio system
hsScalar GetVolumeRank( void );
void ForceUnregisterFromAudioSys( void );
static void SetLoadOnDemand( hsBool activate ) { fLoadOnDemandFlag = activate; }
static void SetLoadFromDiskOnDemand( hsBool activate ) { fLoadFromDiskOnDemand = activate; }
const plEAXSourceSettings &GetEAXSettings( void ) const { return fEAXSettings; }
plEAXSourceSettings &GetEAXSettings( void ) { return fEAXSettings; }
virtual StreamType GetStreamType() const { return kNoStream; }
virtual void FreeSoundData();
protected:
hsBool fPlaying;
hsBool fActive;
double fTime;
int fMaxFalloff;
int fMinFalloff;
hsScalar fCurrVolume;
hsScalar fDesiredVol; // Equal to fCurrVolume except when we're fading or muted
hsScalar fFadedVolume;
hsScalar fMaxVolume;
int fOuterVol;
int fInnerCone;
int fOuterCone;
double fLength;
int fProperties;
UInt8 fType;
UInt8 fPriority;
hsBool fMuted, fFading, fRegisteredForTime, fPlayOnReactivate, fFreeData;
hsBool fNotHighEnoughPriority; // Set whenever the audioSys calls UpdateSoftVolume() with enable=false,
// thus indicating that we slipped off the top 16 most wanted list.
// Do these need to be synched values? They weren't before...
hsVector3 fConeOrientation;
hsPoint3 f3DPosition;
hsVector3 f3DVelocity;
hsBool fPlayWhenLoaded;
double fSynchedStartTimeSec;
// Just around for reference and sending messages upward (synched state)
plSceneObject *fOwningSceneObject;
// EAX Settings storage here
plEAXSourceSettings fEAXSettings;
hsBool fQueued;
plFadeParams fFadeInParams, fFadeOutParams;
plFadeParams fCoolSoftVolumeTrickParams;
plFadeParams *fCurrFadeParams;
plSoftVolume *fSoftRegion;
hsScalar fSoftVolume;
hsScalar fDistAttenuation, fDistToListenerSquared;
double fVirtualStartTime;
hsBool fRegistered;
static unsigned fIncidentalsPlaying;
plSoftVolume *fSoftOcclusionRegion;
plSoundBuffer *fDataBuffer; // Not always around
hsBool fDataBufferLoaded;
plKey fDataBufferKey; // Always around
static plGraphPlate *fDebugPlate;
static plSound *fCurrDebugPlateSound;
static hsBool fLoadOnDemandFlag, fLoadFromDiskOnDemand;
hsBool fLoading;
void IUpdateDebugPlate( void );
void IPrintDbgMessage( const char *msg, hsBool isErr = false );
virtual void ISetActualVolume(const float v) = 0;
virtual void IActuallyStop( void );
virtual hsBool IActuallyPlaying( void ) = 0;
virtual void IActuallyPlay( void ) = 0;
virtual void IFreeBuffers( void ) = 0;
//NOTE: if isIncidental is true the entire sound will be loaded.
virtual plSoundBuffer::ELoadReturnVal IPreLoadBuffer( hsBool playWhenLoaded, hsBool isIncidental = false );
virtual void ISetActualTime( double t ) = 0;
virtual hsBool IActuallyLoaded( void ) = 0;
virtual void IRefreshEAXSettings( hsBool force = false ) = 0;
virtual hsScalar IGetChannelVolume( void ) const;
void ISynchToStartTime( void );
void ISynchedPlay( double virtualStartTime );
void IStartFade( plFadeParams *params, hsScalar offsetIntoFade = 0.f );
void IStopFade( hsBool shuttingDown = false, hsBool SetVolEnd = true);
hsBool IWillBeAbleToPlay( void );
void ISetSoftRegion( plSoftVolume *region );
hsScalar IAttenuateActualVolume( hsScalar volume ) const;
void ISetSoftOcclusionRegion( plSoftVolume *region );
// Override to make sure the buffer is available before the base class is called
virtual void IRefreshParams( void );
virtual bool ILoadDataBuffer( void );
virtual void IUnloadDataBuffer( void );
//virtual void ISetMinDistance( const int m ) = 0;
//virtual void ISetMaxDistance( const int m ) = 0;
//virtual void ISetOuterVolume( const int v ) = 0;
//virtual void ISetConeAngles( int inner, int outer ) = 0;
//virtual void ISetActualConeOrient( hsVector3 &vector ) = 0;
//virtual void ISetVelocity( const hsVector3 vel ) = 0;
//virtual void ISetPosition( const hsPoint3 pos ) = 0;
virtual void IRead( hsStream *s, hsResMgr *mgr );
virtual void IWrite( hsStream *s, hsResMgr *mgr );
};
//// plSoundVolumeApplicator /////////////////////////////////////////////////
// Tiny helper for handling animated volumes
class plSoundVolumeApplicator : public plAGApplicator
{
public:
plSoundVolumeApplicator() { }
plSoundVolumeApplicator( UInt32 index ) { fIndex = index; }
CLASSNAME_REGISTER( plSoundVolumeApplicator );
GETINTERFACE_ANY( plSoundVolumeApplicator, plAGApplicator );
virtual plAGApplicator *CloneWithChannel( plAGChannel *channel );
virtual void Write( hsStream *stream, hsResMgr *mgr );
virtual void Read( hsStream *s, hsResMgr *mgr );
protected:
UInt32 fIndex;
virtual void IApply( const plAGModifier *mod, double time );
};
#endif //plWin32Sound_h