// // dummysound.cpp // // a bunch of dummy implementations of the sound interfaces, for use without a // sound card. // #include "pch.h" #include "soundbase.h" #include "soundutil.h" namespace SoundEngine { // // A stubbed version of the ISoundInstance interface // class DummySoundInstance : public ISoundInstance, public ISoundTweakable3D { bool m_bLooping; bool m_bPlaying; TRef m_psource; TRef m_peventsourceFinished; public: DummySoundInstance(bool bLooping, ISoundPositionSource* psource) : m_bLooping(bLooping), m_bPlaying(true), m_psource(psource) { m_peventsourceFinished = new EventSourceImpl(); }; // Stops the sound. If bForceNow is true the sound will stop ASAP, // possibly popping. If it is false some sounds may play a trail-off // sound or fade away. HRESULT Stop(bool bForceNow = false) { m_bLooping = false; return S_OK; }; // returns S_OK if the sound is currently playing HRESULT IsPlaying() { return m_bPlaying ? S_OK : S_FALSE; }; // Gets an event which fires when the sound finishes playing (for any // reason) IEventSource* GetFinishEventSource() { return m_peventsourceFinished; }; // Gets an interface for tweaking the sound, if supported, NULL otherwise. virtual TRef GetISoundTweakable() { return this; }; // Gets an interface for tweaking the sound, if supported, NULL otherwise. virtual TRef GetISoundTweakable3D() { return this; }; // update the sound, return true if we should keep it around. bool Update() { if (m_bPlaying) { m_bPlaying = m_bLooping && (!m_psource || m_psource->IsPlaying()); if (!m_bPlaying) m_peventsourceFinished->Trigger(); } return m_bPlaying; }; // // ISoundTweakable // // Sets the gain, from 0 to -100 dB HRESULT SetGain(float fGain) { return S_OK; } // Sets the pitch shift, where 1.0 is normal, 0.5 is half of normal speed, // and 2.0 is twice normal speed. HRESULT SetPitch(float fPitch) { return S_OK; } // sets the priority - used as a addition to volume when choosing which // sounds are most important to play. virtual HRESULT SetPriority(float fPriority) { return S_OK; } // // ISoundTweakable3D // // toggles 3D Positioning on and off for the given sound. HRESULT Set3D(bool b3D) { return S_OK; } // Sets the distance at which the sound will be at max volume. This // effects how quickly the sound drops off with distance. HRESULT SetMinimumDistance(float fMinimumDistance) { return S_OK; } // Sets a sound cone of size fInnerAngle (in degrees) where the volume is at // normal levels, outside of which it fades down by fOutsideGain // (range of 0 to -100 db) at fOuterAngle (degrees) and beyond. HRESULT SetCone(float fInnerAngle, float fOuterAngle, float fOutsideGain) { return S_OK; } }; // // A stubbed version of the ISoundEngine interface // class DummySoundEngineImpl : public ISoundEngine, public ISoundBufferSource { TList > m_listPlayingSounds; TRef m_peventsourceUpdate; DWORD m_dwLastUpdateTime; TRef m_pBufferSourceDelegate; public: // constructor DummySoundEngineImpl() { m_peventsourceUpdate = new IntegerEventSourceImpl(); m_dwLastUpdateTime = timeGetTime(); m_pBufferSourceDelegate = new SoundBufferSourceDelegate(this); } // destructor ~DummySoundEngineImpl() { } // Rebuild the sound stage to reflect any recent changes in sound virtual HRESULT Update() { DWORD dwUpdateTime = timeGetTime(); DWORD dwUpdatePeriod = dwUpdateTime - m_dwLastUpdateTime; m_peventsourceUpdate->Trigger(dwUpdatePeriod); // loop through the sounds, deleting those that are no longer playing TList >::Iterator iterSound(m_listPlayingSounds); while (!iterSound.End()) { if (iterSound.Value()->Update()) { iterSound.Next(); } else { iterSound.Remove(); } } m_dwLastUpdateTime = dwUpdateTime; return S_OK; }; // Gets a buffer source for this object (not guarenteed to keep the sound // engine alive due to circular reference problems) virtual ISoundBufferSource* GetBufferSource() { return m_pBufferSourceDelegate; }; // 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) { nBuffers = m_listPlayingSounds.GetCount(); return S_OK; }; // // General environment functions // // Sets the listener to use for the current sounds HRESULT SetListener(ISoundListener* plistener) { TRef plistenerRef = plistener; // cycle the ref count return S_OK; }; // Sets a general quality of playback (CPU time vs. fidelity) HRESULT SetQuality(Quality quality) { return S_OK; }; // Allows/disallows hardware acceleration. HRESULT EnableHardware(bool bEnable) { return S_OK; } // Sets the conversion from game units to meters HRESULT SetDistanceFactor(float fMetersPerUnit) { return S_OK; } // 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.. HRESULT SetRolloffFactor(float fRolloffFactor) { return S_OK; } // Sets the doppler factor, where 1.0 is real-world doppler HRESULT SetDopplerFactor(float fDopplerFactor) { return S_OK; } // // 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& psoundNew, ISoundPCMData* pcmdata, bool bLooping, ISoundPositionSource* psource = NULL) { DummySoundInstance* dummySound = new DummySoundInstance(bLooping, psource); psoundNew = (ISoundInstance*)dummySound; m_listPlayingSounds.PushEnd(dummySound); return S_OK; }; // 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& psoundNew, ISoundPCMData* pcmdata, unsigned uLoopStart, unsigned uLoopLength, ISoundPositionSource* psource = NULL) { DummySoundInstance* dummySound = new DummySoundInstance(true, psource); psoundNew = (ISoundInstance*)dummySound; m_listPlayingSounds.PushEnd(dummySound); return S_OK; }; // 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() { return m_peventsourceUpdate; }; }; // create a dummy sound engine HRESULT CreateDummySoundEngine(TRef& psoundengine) { psoundengine = new DummySoundEngineImpl(); return S_OK; } }