123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383 |
- //
- // ds3dbuffer.h: low-level classes representing actual DirectSound3D buffers
- //
- namespace SoundEngine {
- // the minimum audible sound we care about (in dB)
- const float c_fMinAudible = -60.0f;
- // The conversion ratio from min distance to max distance.
- const float c_fMinToMaxDistanceRatio = 4000.0f;
- //
- // A single DirectSound3D sound buffer. This wrapper handles the painful tasks
- // of dealing with buffer loss, etc..
- //
- class DS3DSoundBuffer : public ISoundObject SoundDebugImpl
- {
- private:
- // the default sample rate for this sound (when pitch is set to 1)
- DWORD m_dwSampleRate;
- //
- // cached settings
- //
- // The current gain of the sound
- float m_fGain;
- // the current pitch of the sound
- float m_fPitch;
- // is 3D on at the moment?
- bool m_b3D;
- // are the positions and velocity listener-relative?
- bool m_bListenerRelative;
- // the current maximum distance of the sound
- float m_fMinimumDistance;
- // the current sound cone
- float m_fInnerAngle, m_fOuterAngle, m_fOutsideGain;
- // the current position of the sound
- Vector m_vectPosition;
- // the current velocity of the sound
- Vector m_vectVelocity;
- // the current orientation of the sound
- Vector m_vectOrientation;
-
- // convert a gain in the range -100 to 0 dB to a direct sound volume
- inline static LONG DSoundVolume(float fGain);
- protected:
- // The current sound buffer
- TRef<IDirectSoundBuffer> m_pdirectsoundbuffer;
- TRef<IDirectSound3DBuffer> m_pdirectsound3Dbuffer;
- // initializes the object, creating the DSoundBuffer itself and
- // initializing local variables.
- virtual HRESULT CreateBuffer(IDirectSound* pDirectSound, ISoundPCMData* pdata,
- DWORD dwBufferSize, bool bStatic, bool bSupport3D, ISoundEngine::Quality quality,
- bool bAllowHardware);
- // Use an exisiting to initialize this buffer. Note that the buffers will
- // share memory, so this only really works for static buffers.
- virtual HRESULT DuplicateBuffer(IDirectSound* pDirectSound, DS3DSoundBuffer* pBuffer);
- // Start the buffer, starting as a looping buffer if requested.
- HRESULT StartImpl(bool bLooping);
- // restore the contents of the buffer after a buffer loss
- virtual HRESULT RestoreBuffer() = 0;
- public:
- DS3DSoundBuffer();
- ~DS3DSoundBuffer();
- // Sets the volume and pitch iff the new values differ from the old.
- HRESULT UpdateState(float fGain, float fPitch, bool bCanDefer = true);
- // Sets the 3D info iff the new values differ from the old.
- HRESULT UpdateState3D(
- const Vector& vectPosition,
- const Vector& vectVelocity,
- const Vector& vectOrientation,
- float fMinimumDistance,
- float fInnerAngle,
- float fOuterAngle,
- float fOutsideGain,
- bool b3D,
- bool bListenerRelative,
- bool bCanDefer = true
- );
- // Starts the given buffer playing at the given position.
- virtual HRESULT Start(DWORD dwPosition, bool bIsStopping = false) = 0;
- // stops the given buffer.
- virtual HRESULT Stop(bool bForceNow = false) = 0;
- // gets the current status of the buffer
- HRESULT GetStatus(bool& bPlaying, bool& bBufferLost);
- // Gets the current position of the sound
- virtual HRESULT GetPosition(DWORD& dwPosition) = 0;
- //
- // 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
- };
- //
- // A specialization of DS3DSoundBuffer for static buffers
- //
- class DS3DStaticSoundBuffer : public DS3DSoundBuffer
- {
- // true if the buffer has been played at least once
- bool m_bHasBeenPlayed;
- // true iff this sound is a looping sound.
- bool m_bLooping;
- // The data source used to create this sound
- TRef<ISoundPCMData> m_pdata;
- // restore the contents of the buffer after a buffer loss
- virtual HRESULT RestoreBuffer();
- // fills the buffer with data from the data source
- virtual HRESULT LoadData();
- // a cache of currently playing static sound buffers
- class CacheKey
- {
- bool m_bSupport3D;
- ISoundEngine::Quality m_quality;
- bool m_bAllowHardware;
- ISoundPCMData* m_pdata;
- public:
- CacheKey(ISoundPCMData* pdata, bool bSupport3D, ISoundEngine::Quality quality, bool bAllowHardware)
- : m_pdata(pdata), m_bSupport3D(bSupport3D), m_quality(quality), m_bAllowHardware(bAllowHardware) {};
- bool operator < (const CacheKey& key) const
- {
- return (m_pdata < key.m_pdata) || (m_pdata == key.m_pdata)
- && ((!m_bSupport3D && key.m_bSupport3D) || (m_bSupport3D == key.m_bSupport3D)
- && ((m_quality < key.m_quality) || (m_quality == key.m_quality)
- && (!m_bAllowHardware && key.m_bAllowHardware)));
- }
- };
- typedef std::multimap<CacheKey, DS3DStaticSoundBuffer*> BufferCache;
- static BufferCache bufferCache;
- BufferCache::iterator m_iterSelf;
- public:
- // Constructor
- DS3DStaticSoundBuffer();
- // Destructor
- ~DS3DStaticSoundBuffer();
- // Initializes this object with the given wave data, 3D support, and sound
- // quality.
- HRESULT Init(IDirectSound* pDirectSound, ISoundPCMData* pdata,
- bool bLooping, bool bSupport3D, ISoundEngine::Quality quality,
- bool bAllowHardware
- );
- // starts the given buffer playing at the given position.
- virtual HRESULT Start(DWORD dwPosition, bool bIsStopping = false);
- // stops the given buffer.
- virtual HRESULT Stop(bool bForceNow = false);
- // Gets the current position of the sound
- virtual HRESULT GetPosition(DWORD& dwPosition);
- };
- //
- // A specialization of DS3DSoundBuffer for streaming buffers
- //
- class DS3DStreamingSoundBuffer : public DS3DSoundBuffer, protected TaskListThread::Task
- {
- protected:
- // true if the buffer has been played at least once
- bool m_bHasBeenPlayed;
- // true iff this sound is a looping sound.
- bool m_bLooping;
- // The data source used to create this sound
- TRef<ISoundPCMData> m_pdata;
- // the next source offset to write
- DWORD m_dwSourceOffset;
- // the next buffer offset at which to write
- DWORD m_dwWriteOffset;
- // the last buffer offset at which we saw the read pointer
- DWORD m_dwLastReadOffset;
- // the size of the streaming buffer.
- DWORD m_dwBufferSize;
- // an offset which, if the read pointer crosses, we know that we have
- // finished playing the sound and are now playing silence.
- DWORD m_dwStopOffset;
- // true iff we are playing silence at this point.
- bool m_bPlayingSilence;
- // The update thread which handles filling the buffers as they play
- static TaskListThread m_threadUpdate;
- // determines if a buffer cursor starting at dwStart and ending at dwEnd
- // would have crossed event dwTrigger.
- inline bool CrossedBoundary(DWORD dwTrigger, DWORD dwStart, DWORD dwEnd);
- // updates anything waiting for the play/read pointer to cross a certain
- // point in the buffer.
- virtual void ReadPointerUpdate(DWORD dwReadOffset);
- // gets the last played source offset from the last played buffer offset.
- virtual DWORD GetPlayedSourceOffset(DWORD dwLastPlayedPosition);
- // restore the contents of the buffer after a buffer loss
- virtual HRESULT RestoreBuffer();
- // Fills the buffer with as much data as it can handle.
- //
- // bTrustWritePtr is a bit of a hack for ASR sounds. Basically, the
- // problem is that when stop is called, an ASR sound needs to call
- // GetCurrentPosition to figure out the first safe place it can start
- // writing the sound's release. When UpdateBufferContents calls
- // GetCurrentPosition a moment later, however, it may return a slightly
- // larger offset for the minimum write position. We want to use the result
- // of the first call to GetCurrentPosition in this case, and not assert
- // that the write pointer is after the result returned by the second call
- // to GetCurrentPosition.
- virtual HRESULT UpdateBufferContents(bool bTrustWritePtr = false);
- // streams the given length of data out to the buffer pointed to by pvBuffer
- virtual HRESULT StreamData(void *pvBuffer, DWORD dwLength);
- // Initializes this object with the given wave data, 3D support, sound
- // quality, and buffer length (in seconds)
- HRESULT Init(IDirectSound* pDirectSound, ISoundPCMData* pdata,
- bool bLooping, bool bSupport3D, ISoundEngine::Quality quality,
- bool bAllowHardware, float fBufferLength
- );
- //
- // TaskListThread::Execute interface
- //
- // Updates the contents of the streaming buffer.
- virtual bool Execute();
- public:
- // Constructor
- DS3DStreamingSoundBuffer();
- // Destructor
- ~DS3DStreamingSoundBuffer();
- // Initializes this object with the given wave data, 3D support, and sound
- // quality.
- HRESULT Init(IDirectSound* pDirectSound, ISoundPCMData* pdata,
- bool bLooping, bool bSupport3D, ISoundEngine::Quality quality,
- bool bAllowHardware
- );
- // starts the given buffer playing at the given position.
- virtual HRESULT Start(DWORD dwPosition, bool bIsStopping = false);
- // stops the given buffer.
- virtual HRESULT Stop(bool bForceNow = false);
- // Gets the current position of the sound
- virtual HRESULT GetPosition(DWORD& dwPosition);
- // gets the current status of the buffer
- HRESULT GetStatus(bool& bPlaying, bool& bBufferLost);
- };
- //
- // A specialization of DS3DSoundBuffer for ASR buffers
- //
- class DS3DASRSoundBuffer : public DS3DStreamingSoundBuffer
- {
- private:
- // the start of the sustain loop in the data source
- DWORD m_dwLoopOffset;
- // the length of the sustain loop in the data source
- DWORD m_dwLoopLength;
- // an offset which, if the read pointer crosses, we know that we have
- // finished playing the attack part of the sound.
- DWORD m_dwSustainBufferOffset;
- // true if we are playing/have played the sustain portion of the sound
- bool m_bPlayingSustain;
- // an offset which, if the read pointer crosses, we know that we have
- // finished playing the sustain part of the sound and are now playing
- // the release part of the sound.
- DWORD m_dwReleaseBufferOffset;
- // true if we are playing/have played the release portion of the sound
- bool m_bPlayingRelease;
- // true if we are trying to transition to the release portion
- bool m_bEnding;
- // updates anything waiting for the play/read pointer to cross a certain
- // point in the buffer.
- virtual void ReadPointerUpdate(DWORD dwReadOffset);
- // gets the last played source offset from the last played buffer offset.
- virtual DWORD GetPlayedSourceOffset(DWORD dwLastPlayedPosition);
- // streams the given length of data out to the buffer pointed to by pvBuffer
- virtual HRESULT StreamData(void *pvBuffer, DWORD dwLength);
- public:
- // Destructor
- ~DS3DASRSoundBuffer();
- // Initializes this object with the given wave data, 3D support, and sound
- // quality.
- HRESULT Init(IDirectSound* pDirectSound, ISoundPCMData* pdata,
- DWORD dwLoopOffset, DWORD dwLoopLength, bool bSupport3D,
- ISoundEngine::Quality quality , bool bAllowHardware
- );
- // starts the given buffer playing at the given position.
- virtual HRESULT Start(DWORD dwPosition, bool bIsStopping = false);
- // stops the given buffer.
- virtual HRESULT Stop(bool bForceNow = false);
- };
- };
|