/*==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 .
Additional permissions under GNU GPL version 3 section 7
If you modify this Program, or any covered work, by linking or
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK,
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK
(or a modified version of those libraries),
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA,
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the
licensors of this Program grant you additional
permission to convey the resulting work. Corresponding Source for a
non-source form of such a combination shall include the source code for
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered
work.
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