sfxSystem.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _SFXSYSTEM_H_
  23. #define _SFXSYSTEM_H_
  24. #ifndef _SFXCOMMON_H_
  25. #include "sfx/sfxCommon.h"
  26. #endif
  27. #ifndef _TSIGNAL_H_
  28. #include "core/util/tSignal.h"
  29. #endif
  30. #ifndef _TVECTOR_H_
  31. #include "core/util/tVector.h"
  32. #endif
  33. #ifndef _THREADSAFEREFCOUNT_H_
  34. #include "platform/threads/threadSafeRefCount.h"
  35. #endif
  36. class SFXTrack;
  37. class SFXDevice;
  38. class SFXProfile;
  39. class SFXStream;
  40. class SFXAmbience;
  41. class SFXSoundscapeManager;
  42. class SFXSource;
  43. class SFXSound;
  44. class SFXBuffer;
  45. class SFXDescription;
  46. /// SFX system events that can be received notifications on.
  47. enum SFXSystemEventType
  48. {
  49. /// SFX is being updated.
  50. SFXSystemEvent_Update,
  51. /// New SFXDevice has been created.
  52. SFXSystemEvent_CreateDevice,
  53. /// SFXDevice is about to be destroyed.
  54. SFXSystemEvent_DestroyDevice,
  55. };
  56. /// SFXSystemPlugins are used to allow other subsystems hook into core functionality
  57. /// of the sound system.
  58. class SFXSystemPlugin
  59. {
  60. public:
  61. ///
  62. virtual void update() {}
  63. ///
  64. virtual SFXSource* createSource( SFXTrack* track ) { return NULL; }
  65. /// Filter the given reverb setup before it is set up on the device. This
  66. /// allows to, for example, modify the current reverb depending on listener
  67. /// location.
  68. virtual void filterReverb( SFXReverbProperties& reverb ) {}
  69. };
  70. /// This class provides access to the sound system.
  71. ///
  72. /// There are a few script preferences that are used by
  73. /// the sound providers.
  74. ///
  75. /// $pref::SFX::frequency - This is the playback frequency
  76. /// for the primary sound buffer used for mixing. Although
  77. /// most providers will reformat on the fly, for best quality
  78. /// and performance match your sound files to this setting.
  79. ///
  80. /// $pref::SFX::bitrate - This is the playback bitrate for
  81. /// the primary sound buffer used for mixing. Although most
  82. /// providers will reformat on the fly, for best quality
  83. /// and performance match your sound files to this setting.
  84. ///
  85. class SFXSystem
  86. {
  87. friend class SFXSound; // _assignVoices
  88. friend class SFXSource; // _onAddSource, _onRemoveSource.
  89. friend class SFXProfile; // _createBuffer.
  90. public:
  91. typedef Signal< void( SFXSystemEventType event ) > EventSignalType;
  92. typedef Vector< SFXSource* > SFXSourceVector;
  93. typedef Vector< SFXSound* > SFXSoundVector;
  94. protected:
  95. /// The one and only instance of the SFXSystem.
  96. static SFXSystem* smSingleton;
  97. /// The protected constructor.
  98. ///
  99. /// @see SFXSystem::init()
  100. ///
  101. SFXSystem();
  102. /// The non-virtual destructor. You shouldn't
  103. /// ever need to overload this class.
  104. ~SFXSystem();
  105. /// The current output sound device initialized
  106. /// and ready to play back.
  107. SFXDevice* mDevice;
  108. ///
  109. SFXSoundVector mSounds;
  110. /// This is used to keep track of play once sources
  111. /// that must be released when they stop playing.
  112. SFXSourceVector mPlayOnceSources;
  113. /// The last time the sources got an update.
  114. U32 mLastSourceUpdateTime;
  115. ///
  116. U32 mLastAmbientUpdateTime;
  117. ///
  118. U32 mLastParameterUpdateTime;
  119. /// The distance model used for rolloff curve computation on 3D sounds.
  120. SFXDistanceModel mDistanceModel;
  121. /// The current doppler scale factor.
  122. F32 mDopplerFactor;
  123. /// The current curve rolloff factor.
  124. F32 mRolloffFactor;
  125. /// The current position and orientation of all listeners.
  126. Vector< SFXListenerProperties > mListeners;
  127. /// Current global reverb properties.
  128. SFXReverbProperties mReverb;
  129. /// SFX system event signal.
  130. EventSignalType mEventSignal;
  131. /// Ambient soundscape manager.
  132. SFXSoundscapeManager* mSoundscapeMgr;
  133. /// List of plugins currently linked to the SFX system.
  134. Vector< SFXSystemPlugin* > mPlugins;
  135. /// @name Stats
  136. ///
  137. /// Stats reported back to the console for tracking performance.
  138. ///
  139. /// @{
  140. S32 mStatNumSources;
  141. S32 mStatNumSounds;
  142. S32 mStatNumPlaying;
  143. S32 mStatNumCulled;
  144. S32 mStatNumVoices;
  145. S32 mStatSourceUpdateTime;
  146. S32 mStatParameterUpdateTime;
  147. S32 mStatAmbientUpdateTime;
  148. /// @}
  149. /// Called to reprioritize and reassign buffers as
  150. /// sources change state, volumes are adjusted, and
  151. /// the listener moves around.
  152. ///
  153. /// @see SFXSource::_update()
  154. ///
  155. void _updateSources();
  156. /// This called to reprioritize and reassign
  157. /// voices to sources.
  158. void _assignVoices();
  159. ///
  160. void _assignVoice( SFXSound* sound );
  161. ///
  162. void _sortSounds( const SFXListenerProperties& listener );
  163. /// Called from SFXSource::onAdd to register the source.
  164. void _onAddSource( SFXSource* source );
  165. /// Called from SFXSource::onRemove to unregister the source.
  166. void _onRemoveSource( SFXSource* source );
  167. /// Called from SFXProfile to create a device specific
  168. /// sound buffer used in conjunction with a voice in playback.
  169. SFXBuffer* _createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description );
  170. /// Load file directly through SFXDevice. Depends on
  171. /// availability with selected SFXDevice.
  172. ///
  173. /// @return Return new buffer or NULL.
  174. SFXBuffer* _createBuffer( const String& filename, SFXDescription* description );
  175. ///
  176. SFXDevice* _getDevice() const { return mDevice; }
  177. public:
  178. /// Returns the one an only instance of the SFXSystem
  179. /// unless it hasn't been initialized or its been disabled
  180. /// in your build.
  181. ///
  182. /// For convienence you can use the SFX-> macro as well.
  183. ///
  184. /// @see SFXSystem::init()
  185. /// @see SFX
  186. static SFXSystem* getSingleton() { return smSingleton; }
  187. /// This is called from initialization to prepare the
  188. /// sound system singleton. This also includes registering
  189. /// common resource types and initializing available sound
  190. /// providers.
  191. static void init();
  192. /// This is called after Sim::shutdown() in shutdownLibraries()
  193. /// to free the sound system singlton. After this the SFX
  194. /// singleton is null and any call to it will crash.
  195. static void destroy();
  196. /// This is only public so that it can be called by
  197. /// the game update loop. It updates the current
  198. /// device and all sources.
  199. void _update();
  200. /// Register the given plugin with the system.
  201. void addPlugin( SFXSystemPlugin* plugin );
  202. /// Unregister the given plugin with the system.
  203. void removePlugin( SFXSystemPlugin* plugin );
  204. /// @name Device Management
  205. /// @{
  206. /// This initializes a new device.
  207. ///
  208. /// @param providerName The name of the provider.
  209. /// @param deviceName The name of the provider device.
  210. /// @param useHardware Toggles the use of hardware processing when available.
  211. /// @param maxBuffers The maximum buffers for this device to use or -1
  212. /// for the device to pick its own reasonable default.
  213. /// @param changeDevice Allows this to change the current device to a new one
  214. /// @return Returns true if the device was created.
  215. bool createDevice( const String& providerName,
  216. const String& deviceName,
  217. bool useHardware,
  218. S32 maxBuffers,
  219. bool changeDevice = false);
  220. /// Returns the current device information or NULL if no
  221. /// device is present. The information string is in the
  222. /// following format:
  223. ///
  224. /// Provider Name\tDevice Name\tUse Hardware\tMax Buffers
  225. String getDeviceInfoString();
  226. /// This destroys the current device. All sources loose their
  227. /// playback buffers, but otherwise continue to function.
  228. void deleteDevice();
  229. /// Returns true if a device is allocated.
  230. bool hasDevice() const { return mDevice != NULL; }
  231. /// @}
  232. /// @name Source Creation
  233. /// @{
  234. /// Used to create new sound sources from a sound profile. The
  235. /// returned source is in a stopped state and ready for playback.
  236. /// Use the SFX_DELETE macro to free the source when your done.
  237. ///
  238. /// @note The track must have at least the same lifetime as the
  239. /// source. If the description disappears while the source is still
  240. /// there, the source will go with it.
  241. ///
  242. /// @param profile The sound profile for the created source.
  243. /// @param transform The optional transform if creating a 3D source.
  244. /// @param velocity The optional doppler velocity if creating a 3D source.
  245. ///
  246. /// @return The sound source or NULL if an error occured.
  247. SFXSource* createSource( SFXTrack* track,
  248. const MatrixF* transform = NULL,
  249. const VectorF* velocity = NULL );
  250. /// Used to create a streaming sound source from a user supplied
  251. /// stream object.
  252. ///
  253. /// It is only intended for memory based streams. For sound file
  254. /// streaming use createSource() with a streaming SFXProfile.
  255. ///
  256. /// Use the SFX_DELETE macro to free the source when your done.
  257. ///
  258. /// @note The description must have at least the same lifetime as the
  259. /// sound. If the description disappears while the source is still
  260. /// there, the sound will go with it.
  261. ///
  262. /// @param stream The stream used to create the sound buffer. It
  263. /// must exist for the lifetime of the source and will
  264. /// have its reference count decremented when the source
  265. /// is destroyed.
  266. ///
  267. /// @param description The sound description to apply to the source.
  268. ///
  269. /// @return The sound source or NULL if an error occured.
  270. SFXSound* createSourceFromStream( const ThreadSafeRef< SFXStream >& stream,
  271. SFXDescription* description );
  272. /// Creates a source which when it finishes playing will auto delete
  273. /// itself. Be aware that the returned SFXSource pointer should only
  274. /// be used for error checking or immediate setting changes. It may
  275. /// be deleted as soon as the next system tick.
  276. ///
  277. /// @param profile The sound profile for the created source.
  278. /// @param transform The optional transform if creating a 3D source.
  279. /// @param velocity The optional doppler velocity if creating a 3D source.
  280. ///
  281. /// @return The sound source or NULL if an error occured.
  282. SFXSource* playOnce( SFXTrack* track,
  283. const MatrixF* transform = NULL,
  284. const VectorF* velocity = NULL,
  285. F32 fadeInTime = -1.f );
  286. SFXSource* playOnce( SFXProfile* profile,
  287. const MatrixF* transform = NULL,
  288. const VectorF* velocity = NULL,
  289. F32 fadeInTime = -1.f )
  290. { // Avoids having to require inclusion of sfxProfile.h
  291. return playOnce( ( SFXTrack* ) profile, transform, velocity, fadeInTime );
  292. }
  293. /// Stop the source and delete it. This method will take care of
  294. /// the fade-out time that the source may need before it will actually
  295. /// stop and may be deleted.
  296. void stopAndDeleteSource( SFXSource* source );
  297. /// Mark source for deletion when it is moving into stopped state.
  298. /// This method is useful to basically make a source a play-once source
  299. /// after the fact.
  300. void deleteWhenStopped( SFXSource* source );
  301. /// @}
  302. /// @}
  303. /// @name Listeners
  304. /// @{
  305. /// Return the number of listeners currently configured.
  306. U32 getNumListeners() const { return mListeners.size(); }
  307. /// Set the number of concurrent listeners.
  308. /// @note It depends on the selected device if more than one listener is actually supported.
  309. void setNumListeners( U32 num );
  310. /// Set the property of the given listener.
  311. const SFXListenerProperties& getListener( U32 index = 0 ) const { return mListeners[ index ]; }
  312. /// Set the 3D attributes of the given listener.
  313. void setListener( U32 index, const MatrixF& transform, const Point3F& velocity );
  314. void setListener( U32 index, const SFXListenerProperties& properties )
  315. {
  316. setListener( index, properties.getTransform(), properties.getVelocity() );
  317. }
  318. /// @}
  319. /// @name 3D Sound Configuration
  320. /// {
  321. /// Return the curve model currently used distance attenuation of positional sounds.
  322. SFXDistanceModel getDistanceModel() const { return mDistanceModel; }
  323. ///
  324. void setDistanceModel( SFXDistanceModel model );
  325. ///
  326. F32 getDopplerFactor() const { return mDopplerFactor; }
  327. ///
  328. void setDopplerFactor( F32 factor );
  329. ///
  330. F32 getRolloffFactor() const { return mRolloffFactor; }
  331. ///
  332. void setRolloffFactor( F32 factor );
  333. ///
  334. const SFXReverbProperties& getReverb() const { return mReverb; }
  335. ///
  336. void setReverb( const SFXReverbProperties& reverb );
  337. /// @}
  338. ///
  339. SFXSoundscapeManager* getSoundscapeManager() const { return mSoundscapeMgr; }
  340. /// Dump information about all current SFXSources to the console or
  341. /// to the given StringBuilder.
  342. void dumpSources( StringBuilder* toString = NULL, bool excludeGroups = true );
  343. /// Return the SFX system event signal.
  344. EventSignalType& getEventSignal() { return mEventSignal; }
  345. /// Notify the SFX system that the given description has changed.
  346. /// All sources currently using the description will be updated.
  347. void notifyDescriptionChanged( SFXDescription* description);
  348. ///
  349. void notifyTrackChanged( SFXTrack* track );
  350. };
  351. /// Less verbose macro for accessing the SFX singleton. This
  352. /// should be the prefered method for accessing the system.
  353. ///
  354. /// @see SFXSystem
  355. /// @see SFXSystem::getSingleton()
  356. ///
  357. #define SFX SFXSystem::getSingleton()
  358. #endif // _SFXSYSTEM_H_