ds3dvirtualbuffer.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. //
  2. // ds3dvirtualbuffer.h
  3. //
  4. // Classes representing virtual DirectSound3D buffers that may or may not have
  5. // a real DirectSoundBuffer associated with them at any given moment.
  6. //
  7. namespace SoundEngine {
  8. //
  9. // Tracks a buffer position over the lifetime of a virtual sound. This is
  10. // designed to lighter-weight than an actual sound buffer, because the sound
  11. // it represents may never be played. It's designed to be accurate, however,
  12. // so that a buffer created using this information can start at the appropriate
  13. // point.
  14. //
  15. class BufferPositionTracker
  16. {
  17. // the current position in the sound
  18. DWORD m_dwPosition;
  19. // the length of the buffer
  20. DWORD m_dwLength;
  21. // the sample rate of the sound, in bytes per second.
  22. DWORD m_dwBytesPerSec;
  23. // a mask of valid position bits (since a position must start on a sample
  24. // boundary)
  25. DWORD m_dwPositionMask;
  26. // true iff end has been called on this
  27. bool m_bEnding;
  28. //
  29. // Non-ASR data
  30. //
  31. // true if this is looping
  32. bool m_bLooping;
  33. //
  34. // ASR data
  35. //
  36. // true iff this is an ASR sound.
  37. bool m_bASR;
  38. // the starting position of the sustain loop.
  39. DWORD m_dwLoopStart;
  40. // the length of the sustain loop
  41. DWORD m_dwLoopLength;
  42. public:
  43. // Create a position tracker for a sound which plays until it reaches the
  44. // end (for non-looping sounds) or has stop called upon it.
  45. BufferPositionTracker(ISoundPCMData* pdata, bool bLooping = false);
  46. // Creates a position tracker for an ASR buffer.
  47. BufferPositionTracker(ISoundPCMData* pdata,
  48. DWORD dwLoopStart, DWORD dwLoopLength);
  49. //
  50. // Events that the buffer tracker needs to know about
  51. //
  52. // the sound has been given a stop.
  53. void Stop(bool bForceNow = false);
  54. // the given number of miliseconds have elapsed
  55. void AddTime(DWORD dwElapsedTime);
  56. // Resets the position to the given one, presumably retrieved from a
  57. // playing buffer.
  58. void SetPosition(DWORD dwPosition);
  59. //
  60. // Info a SoundInstance may need.
  61. //
  62. // true iff this has stopped playing.
  63. bool IsStopped()
  64. {
  65. return m_dwPosition >= m_dwLength;
  66. };
  67. // is the sound in the process of stopping?
  68. bool IsStopping()
  69. {
  70. return m_bASR && m_bEnding;
  71. }
  72. // what is the current offset in the source buffer?
  73. DWORD GetPosition()
  74. {
  75. return m_dwPosition & m_dwPositionMask;
  76. }
  77. //
  78. // ASR info
  79. //
  80. // is this tracking an ASR sound?
  81. bool IsASR()
  82. {
  83. return m_bASR;
  84. }
  85. // get the loop offset in the ASR sound
  86. DWORD GetLoopOffset()
  87. {
  88. ZAssert(m_bASR);
  89. return m_dwLoopStart;
  90. }
  91. // get the loop length in an ASR sound
  92. DWORD GetLoopLength()
  93. {
  94. ZAssert(m_bASR);
  95. return m_dwLoopLength;
  96. }
  97. //
  98. // non-ASR info
  99. //
  100. // true if this is a looping sound
  101. bool IsLooping()
  102. {
  103. ZAssert(!m_bASR);
  104. return m_bLooping;
  105. }
  106. };
  107. //
  108. // A sound instance implementation representing a single virtual DirectSound3D
  109. // sound buffer. This may or may not have an actual direct sound buffer
  110. // associated with it at any time - the sound engine controls that aspect of
  111. // things.
  112. //
  113. class DSVirtualSoundBuffer : public ISoundInstance, public ISoundTweakable SoundDebugImpl
  114. {
  115. protected:
  116. // An event source which is triggered when a sound is finished (often NULL)
  117. TRef<EventSourceImpl> m_peventsourceFinished;
  118. // the current buffer position of the sound
  119. BufferPositionTracker m_bufferPositionTracker;
  120. // The data source used to create this sound
  121. TRef<ISoundPCMData> m_pdata;
  122. // The current sound buffer (possibly NULL)
  123. TRef<DS3DSoundBuffer> m_pds3dbuffer;
  124. // the aproximate age of this sound in seconds, used for priority purposes
  125. float m_fAge;
  126. // has this sound started?
  127. bool m_bStarted;
  128. // has this sound stopped?
  129. bool m_bStopped;
  130. // are we trying to stop this sound?
  131. bool m_bRetryStop;
  132. // is the buffer currently playing?
  133. bool m_bBufferPlaying;
  134. // is the buffer currently audible?
  135. bool m_bAudible;
  136. // what is the quality of the sound currently?
  137. ISoundEngine::Quality m_quality;
  138. // can the current buffer play in hardware, if available?
  139. bool m_bAllowHardware;
  140. // the dynamic priority of the sound. The only meaning this number has is
  141. // in relation to other priorities, where the higher number is the higher
  142. // priority.
  143. float m_fDynamicPriority;
  144. //
  145. // cached settings
  146. //
  147. // The current priority of the sound
  148. float m_fPriority;
  149. // The current gain of the sound
  150. float m_fGain;
  151. // the current pitch of the sound
  152. float m_fPitch;
  153. // prepare a sound buffer with the given quality and 3D support using the
  154. // direct sound object pointed to by pDirectSound.
  155. virtual HRESULT PrepareBuffer(IDirectSound* pDirectSound,
  156. ISoundEngine::Quality quality, bool bAllowHardware, bool bSupport3D);
  157. public:
  158. // Creates a virtual sound buffer for a normal sound, possibly looping
  159. DSVirtualSoundBuffer(ISoundPCMData* pdata, bool bLooping);
  160. // Creates a virtual sound buffer for an ASR sound
  161. DSVirtualSoundBuffer(ISoundPCMData* pdata, DWORD dwLoopOffset, DWORD dwLoopLength);
  162. //
  163. // Accessors
  164. //
  165. // returns true iff the buffer is no longer playing (and can be discarded)
  166. bool IsStopped()
  167. {
  168. return m_bStopped;
  169. };
  170. // Returns true if this has a playing physical buffer
  171. bool HasPlayingBuffer()
  172. {
  173. return m_bBufferPlaying;
  174. };
  175. // Returns true if this is audible at the moment
  176. bool IsAudible()
  177. {
  178. return m_bAudible;
  179. };
  180. // Gets the dynamic priority of the sound. The only meaning this number
  181. // has is in relation to other priorities, where the higher number is the
  182. // higher priority.
  183. float GetDynamicPriority()
  184. {
  185. return m_fDynamicPriority;
  186. };
  187. // Recalculates the sounds position, loudness, whether it's playing, etc..
  188. virtual HRESULT Update(DWORD dwTimeElapsed,
  189. const Vector& vectListenerPosition, float fRolloffFactor);
  190. // Creates and starts a real dsound buffer for this sound
  191. virtual HRESULT StartBuffer(IDirectSound* pDirectSound,
  192. ISoundEngine::Quality quality, bool bAllowHardware);
  193. // forcibly stops the given buffer.
  194. HRESULT StopBuffer();
  195. //
  196. // ISoundTweakable interface
  197. //
  198. // Sets the gain, from 0 to -100 dB
  199. virtual HRESULT SetGain(float fGain);
  200. // Sets the pitch shift, where 1.0 is normal, 0.5 is half of normal speed,
  201. // and 2.0 is twice normal speed.
  202. virtual HRESULT SetPitch(float fPitch);
  203. // sets the priority - used as a addition to volume when choosing which
  204. // sounds are most important to play.
  205. virtual HRESULT SetPriority(float fPriority);
  206. //
  207. // ISoundInstance interface
  208. //
  209. // Stops the sound. If bForceNow is true the sound will stop ASAP,
  210. // possibly popping. If it is false some sounds may play a trail-off
  211. // sound or fade away.
  212. virtual HRESULT Stop(bool bForceNow = false);
  213. // returns S_OK if the sound is currently playing, S_FALSE otherwise.
  214. virtual HRESULT IsPlaying();
  215. // Gets an event which fires when the sound finishes playing (for any
  216. // reason)
  217. virtual IEventSource* GetFinishEventSource();
  218. // Gets an interface for tweaking the sound, if supported, NULL otherwise.
  219. virtual TRef<ISoundTweakable> GetISoundTweakable();
  220. // Gets an interface for tweaking the sound, if supported, NULL otherwise.
  221. virtual TRef<ISoundTweakable3D> GetISoundTweakable3D();
  222. //
  223. // ISoundDebugDump
  224. //
  225. #ifdef _DEBUG
  226. // return a human-readable description of the object, prepending
  227. // strIndent to the beginning of each line.
  228. ZString DebugDump(const ZString& strIndent = "");
  229. #endif
  230. };
  231. class DS3DVirtualSoundBuffer : public DSVirtualSoundBuffer, public ISoundTweakable3D
  232. {
  233. private:
  234. //
  235. // cached settings
  236. //
  237. // The source of this sound, position-wise
  238. TRef<ISoundPositionSource> m_pposSource;
  239. // is 3D on at the moment?
  240. bool m_b3D;
  241. // have we decided to play in 3D at the moment?
  242. bool m_bPlayingIn3D;
  243. // the current maximum distance of the sound
  244. float m_fMinimumDistance;
  245. // the current sound cone
  246. float m_fInnerAngle, m_fOuterAngle, m_fOutsideGain;
  247. // the last known position of the sound
  248. Vector m_vectPosition;
  249. // the last known velocity of the sound
  250. Vector m_vectVelocity;
  251. // the last known orientation of the sound
  252. Vector m_vectOrientation;
  253. // whether or not the last known info is relative to the listener
  254. bool m_bListenerRelative;
  255. public:
  256. // constructs a simple 3D capable sound
  257. DS3DVirtualSoundBuffer(ISoundPCMData* pdata, bool bLooping,
  258. TRef<ISoundPositionSource> psource);
  259. // constructs an ASR 3D capable sound
  260. DS3DVirtualSoundBuffer(ISoundPCMData* pdata, DWORD dwLoopOffset,
  261. DWORD dwLoopLength, TRef<ISoundPositionSource> psource);
  262. //
  263. // DSVirtualSoundBuffer overides
  264. //
  265. protected:
  266. // prepare a sound buffer with the given quality and 3D support using the
  267. // direct sound object pointed to by pDirectSound.
  268. virtual HRESULT PrepareBuffer(IDirectSound* pDirectSound,
  269. ISoundEngine::Quality quality, bool bAllowHardware, bool bSupport3D);
  270. public:
  271. // Recalculates the sounds position, loudness, whether it's playing, etc..
  272. virtual HRESULT Update(DWORD dwTimeElapsed,
  273. const Vector& vectListenerPosition, float fRolloffFactor);
  274. //
  275. // ISoundTweakable3D interface
  276. //
  277. // toggles 3D Positioning on and off for the given sound.
  278. virtual HRESULT Set3D(bool b3D);
  279. // Sets the distance at which the sound will be at max volume. This
  280. // effects how quickly the sound drops off with distance.
  281. virtual HRESULT SetMinimumDistance(float fMinimumDistance);
  282. // Sets a sound cone of size fInnerAngle (in degrees) where the volume is at
  283. // normal levels, outside of which it fades down by fOutsideGain
  284. // (range of 0 to -100 db) at fOuterAngle (degrees) and beyond.
  285. virtual HRESULT SetCone(float fInnerAngle, float fOuterAngle, float fOutsideGain);
  286. //
  287. // ISoundTweakable interface
  288. //
  289. // Sets the gain, from 0 to -100 dB
  290. virtual HRESULT SetGain(float fGain);
  291. // Sets the pitch shift, where 1.0 is normal, 0.5 is half of normal speed,
  292. // and 2.0 is twice normal speed.
  293. virtual HRESULT SetPitch(float fPitch);
  294. // sets the priority - used as a addition to volume when choosing which
  295. // sounds are most important to play.
  296. virtual HRESULT SetPriority(float fPriority);
  297. // Gets an interface for tweaking the sound, if supported, NULL otherwise.
  298. virtual TRef<ISoundTweakable> GetISoundTweakable();
  299. // Gets an interface for tweaking the sound, if supported, NULL otherwise.
  300. virtual TRef<ISoundTweakable3D> GetISoundTweakable3D();
  301. };
  302. };