You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
414 lines
14 KiB
414 lines
14 KiB
4 years ago
|
/*==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 <http://www.gnu.org/licenses/>.
|
||
|
|
||
|
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;
|
||
|
fCurrTime = -1.f;
|
||
|
}
|
||
|
|
||
|
void Read( hsStream *s );
|
||
|
void Write( hsStream *s );
|
||
|
|
||
|
hsScalar InterpValue();
|
||
|
|
||
|
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() 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() const { return fCurrVolume; }
|
||
|
hsScalar GetMaxVolume() { return fMaxVolume; }
|
||
|
virtual hsBool IsPlaying() { return fPlaying; }
|
||
|
void SetTime(double t);
|
||
|
virtual double GetTime() { 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() { 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() const { return (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded(); }
|
||
|
hsScalar QueryCurrVolume() const; // Returns the current volume, attenuated
|
||
|
|
||
|
const char * GetFileName() 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();
|
||
|
|
||
|
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() 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() const { return fType; }
|
||
|
|
||
|
// Priority stuff
|
||
|
void SetPriority( UInt8 pri ) { fPriority = pri; }
|
||
|
UInt8 GetPriority() const { return fPriority; }
|
||
|
|
||
|
// Visualization
|
||
|
virtual plDrawableSpans* CreateProxy(const hsMatrix44& l2w, hsGMaterial* mat, hsTArray<UInt32>& idx, plDrawableSpans* addTo);
|
||
|
|
||
|
// Forced loading/unloading (for when the audio system's LOD just doesn't cut it)
|
||
|
virtual void ForceLoad( );
|
||
|
virtual void ForceUnload();
|
||
|
|
||
|
// Note: ONLY THE AUDIOSYS SHOULD CALL THIS. If you're not the audioSys, get lost.
|
||
|
static void SetCurrDebugPlate( const plKey soundKey );
|
||
|
|
||
|
void RegisterOnAudioSys();
|
||
|
void UnregisterOnAudioSys();
|
||
|
|
||
|
// Also only for the audio system
|
||
|
hsScalar GetVolumeRank();
|
||
|
void ForceUnregisterFromAudioSys();
|
||
|
|
||
|
static void SetLoadOnDemand( hsBool activate ) { fLoadOnDemandFlag = activate; }
|
||
|
static void SetLoadFromDiskOnDemand( hsBool activate ) { fLoadFromDiskOnDemand = activate; }
|
||
|
|
||
|
const plEAXSourceSettings &GetEAXSettings() const { return fEAXSettings; }
|
||
|
plEAXSourceSettings &GetEAXSettings() { 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 IPrintDbgMessage( const char *msg, hsBool isErr = false );
|
||
|
|
||
|
virtual void ISetActualVolume(float v) = 0;
|
||
|
virtual void IActuallyStop();
|
||
|
virtual hsBool IActuallyPlaying() = 0;
|
||
|
virtual void IActuallyPlay() = 0;
|
||
|
virtual void IFreeBuffers() = 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() = 0;
|
||
|
virtual void IRefreshEAXSettings( hsBool force = false ) = 0;
|
||
|
|
||
|
virtual hsScalar IGetChannelVolume() const;
|
||
|
|
||
|
void ISynchToStartTime();
|
||
|
void ISynchedPlay( double virtualStartTime );
|
||
|
void IStartFade( plFadeParams *params, hsScalar offsetIntoFade = 0.f );
|
||
|
void IStopFade( hsBool shuttingDown = false, hsBool SetVolEnd = true);
|
||
|
|
||
|
hsBool IWillBeAbleToPlay();
|
||
|
|
||
|
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();
|
||
|
|
||
|
virtual bool ILoadDataBuffer();
|
||
|
virtual void IUnloadDataBuffer();
|
||
|
|
||
|
//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
|