//
// ds3dengine.h
//
// Classes representing a DirectSound3D implementation of a sound engine
//
namespace SoundEngine {
//
// A sound engine implementation using direct sound 3D that handles basic
// resource management.
//
class DS3DSoundEngine : public ISoundEngine, public ISoundBufferSource SoundDebugImpl
{
// the currently chosen DirectSound implementation
// mdvalley: Now uses DirectSound8 interface.
TRef<IDirectSound8> m_pDirectSound8;
TRef<IDirectSound> m_pDirectSound;
// the primary buffer of this DirectSound instance
// mdvalley: The DX SDK says to keep the old interface for the primary
// buffer. I'm not arguing.
TRef<IDirectSoundBuffer> m_pPrimaryBuffer;
// the capabilities of the chosen DirectSound implementation
DSCAPS m_dscaps;
// the listener used to render sound
TRef<ISoundListener> m_plistener;
// the coresponding DirectSound3D listener for this instance.
TRef<IDirectSound3DListener> m_pDSListener;
// the rolloff factor, where 1.0f is the real-world rolloff
float m_fRolloffFactor;
// the doppler factor, where 1.0f is the real-world doppler
float m_fDopplerFactor;
// the distance factor, where 1.0f is the real-world distance factor
float m_fDistanceFactor;
// the update event source, triggered on each call to update.
TRef<IntegerEventSourceImpl> m_peventsourceUpdate;
// a delegate buffer source for this (needed to avoid circular refs)
TRef<ISoundBufferSource> m_pBufferSourceDelegate;
// a list of currently playing virtual sounds
typedef std::list<ZAdapt<TRef<DSVirtualSoundBuffer> > > VirtualSoundList;
VirtualSoundList m_listActiveSounds;
// the time of the last call to update
DWORD m_dwLastUpdateTime;
// the sound quality to use
Quality m_quality;
// whether to allow hardware acceleration
bool m_bAllowHardware;
// the desired number of sounds to play at once. This number may reserve
// a few voices for fading sounds out.
int m_nNumBuffersDesired;
// the maximum number of sounds we can play at once, including sounds that
// are fading in or out.
int m_nNumBuffersMax;
// dumps the capablilites of this DirectSound implementation to the
// debug output.
void DumpCaps();
// Sets the format of the primary buffer to the given sample rate, number
// of bits, and number of channels
HRESULT SetPrimaryBufferFormat(int nSampleRate, int nNumberOfBits, int nChannels);
// updates the listener position, orientation, etc. for direct sound 3D.
HRESULT UpdateListener();
// Is this an error worth killing a virtual sound for, or just something
// transitory? For example, we may lose a sound buffer when being swapped
// to the background, but we want the sound to continue playing when we
// are swapped back in.
static bool IsSeriousError(HRESULT hr);
// provides a complete ordering of virtual sound buffers by priority.
struct SoundPriorityCompare
{
typedef DSVirtualSoundBuffer* first_argument_type;
typedef DSVirtualSoundBuffer* second_argument_type;
typedef bool result_type;
bool operator () (DSVirtualSoundBuffer* psound1, DSVirtualSoundBuffer* psound2) const
{
return psound1->GetDynamicPriority() > psound2->GetDynamicPriority()
|| (psound1->GetDynamicPriority() == psound2->GetDynamicPriority()
&& psound1 > psound2);
}
};
template <class T>
struct RefToPtr
{
T* operator () (TRef<T>& rt)
{
return rt;
}
};
public:
// Constructor - the real initialization is done in init.
DS3DSoundEngine();
~DS3DSoundEngine();
// Basic initialization. This was pulled out of the constructor so that we
// can return error values.
HRESULT Init(HWND hwnd, bool bUseDSound8);
//
// ISoundEngine Interface
//
// Rebuild the sound stage to reflect any recent changes in sound
virtual HRESULT Update();
// Gets a buffer source for this object (not guarenteed to keep the sound
// engine alive due to circular reference problems)
virtual ISoundBufferSource* GetBufferSource();
// Gets the number of virtual sound buffers that are playing at a given
// moment. (no guarantees on how this number changes - it's just a perf.
// number to use.)
virtual HRESULT GetNumPlayingVirtualBuffers(int& nBuffers);
// Sets a general quality of playback (CPU time vs. fidelity)
HRESULT SetQuality(Quality quality);
// Allows/disallows hardware acceleration.
HRESULT EnableHardware(bool bEnable);
// Sets the listener to use for the current sounds
virtual HRESULT SetListener(ISoundListener* plistener);
// Sets the conversion from game units to meters
virtual HRESULT SetDistanceFactor(float fMetersPerUnit);
// Sets the rolloff factor, where 1.0 is the real world attenuation with
// distance, 2.0 is twice the attenuation of the real world, etc..
virtual HRESULT SetRolloffFactor(float fRolloffFactor);
// Sets the doppler factor, where 1.0 is real-world doppler
virtual HRESULT SetDopplerFactor(float fDopplerFactor);
//
// ISoundBufferSource
//
// Creates a static sound buffer of the given wave file. If bLooping is
// true, the sound will loop until stopped.
virtual HRESULT CreateStaticBuffer(TRef<ISoundInstance>& psoundNew,
ISoundPCMData* pcmdata, bool bLooping, ISoundPositionSource* psource = NULL);
// Creates a sound buffer with a loop in the middle. The sound will play
// the start sound, play the loop sound until it gets a soft stop, then
// play the rest of the sound.
virtual HRESULT CreateASRBuffer(TRef<ISoundInstance>& psoundNew,
ISoundPCMData* pcmdata, unsigned uLoopStart, unsigned uLoopLength,
ISoundPositionSource* psource = NULL);
// Gets an event which fires each time update is called. This can be used
// for some of the trickier sounds that change with time.
virtual IIntegerEventSource* GetUpdateEventSource();
//
// ISoundDebugDump
//
#ifdef _DEBUG
// return a human-readable description of the object, prepending
// strIndent to the beginning of each line.
ZString DebugDump(const ZString& strIndent = "");
#endif
};
};