sfxPlayList.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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 _SFXPLAYLIST_H_
  23. #define _SFXPLAYLIST_H_
  24. #ifndef _SFXCOMMON_H_
  25. #include "sfx/sfxCommon.h"
  26. #endif
  27. #ifndef _SFXTRACK_H_
  28. #include "sfx/sfxTrack.h"
  29. #endif
  30. #ifndef SOUND_ASSET_H
  31. #include "T3D/assets/SoundAsset.h"
  32. #endif
  33. class SFXState;
  34. /// A playback list of SFXTracks.
  35. ///
  36. /// Note that since SFXPlayLists are SFXTracks, play lists can be cascaded.
  37. ///
  38. /// Play lists are comprised of a sequence of slots. Each slot can be assigned
  39. /// a track (SFXProfile or another SFXPlayList) as well as a number of options
  40. /// that determine how the particular slot should behave.
  41. ///
  42. /// In addition to playing a track, each slot can do an arbitrary combination
  43. /// of the following operations:
  44. ///
  45. /// - Wait: wait for the previous or all sources to stop playing
  46. /// - Stop: stop the previous or all sources from playing
  47. /// - Delay: wait some (optionally randomized) amount of time
  48. /// - Shift Pitch: scale pitch when playing by optionally randomized amount
  49. /// - Shift Volume: scale volume when playing by optionally randomized amount
  50. /// - Fade: perform volume fade-in/out
  51. /// - Distance: only start playing track when listener is within a certain range
  52. /// - Loop: loop a set number of times
  53. /// - State: play only when the given SFXState is active; transitions out of
  54. /// slot when state is deactivated
  55. ///
  56. /// The order in which slots are played is either sequential (NotRandom),
  57. /// or a random selection (StrictRandom), or a random ordering (OrderedRandom).
  58. ///
  59. /// Additionally, the list may be looped over in entirety (All) or looped
  60. /// on single slots (useful for either manual playback control or lists that
  61. /// exclusively use states).
  62. ///
  63. /// Be aware that playlists are affected by SFXDescriptions the same way that an
  64. /// SFXProfile is, i.e. fades, looping, 3D sound, etc. all take effect.
  65. ///
  66. /// @note Playlists offer a lot of control but unfortunately they also make it
  67. /// pretty easy at the moment to shoot yourself in the foot.
  68. ///
  69. class SFXPlayList : public SFXTrack
  70. {
  71. public:
  72. typedef SFXTrack Parent;
  73. enum
  74. {
  75. /// Number of slots in a playlist.
  76. ///
  77. /// @note To have longer playlists, simply cascade playlists and use
  78. /// wait behaviors.
  79. NUM_SLOTS = 12, // AFX (was 16)
  80. NUM_TRANSITION_MODE_BITS = 3,
  81. NUM_LOOP_MODE_BITS = 1,
  82. NUM_RANDOM_MODE_BITS = 2,
  83. NUM_SLOTS_TO_PLAY_BITS = 5,
  84. NUM_REPLAY_MODE_BITS = 3,
  85. NUM_STATE_MODE_BITS = 2,
  86. };
  87. /// Behavior when description is set to loop.
  88. enum ELoopMode
  89. {
  90. /// Start over after completing a cycle.
  91. LOOP_All,
  92. /// Loop a single slot over and over.
  93. ///
  94. /// @note This behavior is only useful in combination with states or manual
  95. /// playback control. To just loop over a slot for some time, set its loop
  96. /// count instead.
  97. LOOP_Single,
  98. };
  99. /// Random playback mode.
  100. enum ERandomMode
  101. {
  102. /// No randomization of playback order.
  103. RANDOM_NotRandom,
  104. /// Playback order that jumps to a random slot after completing
  105. /// a given slot. The slot being jumped to, however, may be any
  106. /// slot in the list including the slot that has just played.
  107. ///
  108. /// @note In order to ensure cycles are always finite, this mode will
  109. /// also just do NUM_SLOTS number of transitions and then stop the
  110. /// current cycle whether all slots have played or not. Otherwise,
  111. /// it would be dependent on the random number sequence generated when
  112. /// and whether at all a given cycle finishes.
  113. RANDOM_StrictRandom,
  114. /// Before a cycle over the playlist starts, a random total ordering of
  115. /// the slots is established and then played. No slot will be played
  116. /// twice in a single cycle.
  117. RANDOM_OrderedRandom,
  118. };
  119. /// Transitioning behavior when moving in and out of slots.
  120. enum ETransitionMode
  121. {
  122. /// No specific behavior for transitioning between slots.
  123. TRANSITION_None,
  124. /// Wait for single slot to stop playing. If transitioning into slot,
  125. /// this is the slot being transitioned from. If transitioning out of slot,
  126. /// this is the current slot.
  127. TRANSITION_Wait,
  128. /// Wait for all slots to stop playing.
  129. TRANSITION_WaitAll,
  130. /// Stop single slot before proceeding. If transitioning into slot, this
  131. /// is the slot being transitioned from. If transitioning out of slot,
  132. /// this is the current slot.
  133. TRANSITION_Stop,
  134. /// Stop all playing slots before proceeding.
  135. TRANSITION_StopAll,
  136. };
  137. /// Behavior when hitting play() on a slot that is still playing from
  138. /// a previous cycle.
  139. enum EReplayMode
  140. {
  141. /// Do not check if a source is already playing on the slot.
  142. REPLAY_IgnorePlaying,
  143. /// Stop the currently playing source and start playing it from the
  144. /// beginning.
  145. REPLAY_RestartPlaying,
  146. /// Move the currently playing source to the top of the stack and pretend
  147. /// it was started by this cycle.
  148. ///
  149. /// When using STATE_PauseInactive, it is usally best to also use REPLAY_KeepPlaying
  150. /// as otherwise a new source will be spawned when the state becomes active again.
  151. ///
  152. /// @note When the currently playing source is paused, KeepPlaying will
  153. /// resume playback.
  154. REPLAY_KeepPlaying,
  155. /// Let the old source play and start a new one on the same slot.
  156. REPLAY_StartNew,
  157. /// If there is a source currently playing on this slot, skip the play() stage.
  158. REPLAY_SkipIfPlaying,
  159. };
  160. /// State-reaction behavior of slot once a source has started playing.
  161. enum EStateMode
  162. {
  163. /// Stop and remove source when state becomes inactive.
  164. STATE_StopInactive,
  165. /// Pause source when state becomes inactive and resume playback
  166. /// when state becomes active again.
  167. STATE_PauseInactive,
  168. /// Once a source has started to play, it will not be stopped due to
  169. /// state changes. A source will, however, still be prevented from starting
  170. /// to play when its assigned state is not active.
  171. STATE_IgnoreInactive,
  172. };
  173. // All structures here are laid out as structures of arrays instead of arrays of structures
  174. // to allow them to be used as fixed-size TorqueScript arrays.
  175. struct VariantFloat : SFXVariantFloat< NUM_SLOTS >
  176. {
  177. VariantFloat()
  178. {
  179. dMemset( mValue, 0, sizeof( mValue ) );
  180. dMemset( mVariance, 0, sizeof( mVariance ) );
  181. }
  182. };
  183. /// Settings for the playback slots.
  184. struct SlotData
  185. {
  186. /// Behavior when a sound is already playing on a slot from a previous cycle.
  187. EReplayMode mReplayMode[ NUM_SLOTS ];
  188. /// Behavior when transitioning into the slot.
  189. ETransitionMode mTransitionIn[ NUM_SLOTS ];
  190. /// Behavior when transitioning out of the slot.
  191. ETransitionMode mTransitionOut[ NUM_SLOTS ];
  192. /// Seconds to fade sound in. -1 to leave at default.
  193. VariantFloat mFadeTimeIn;
  194. /// Seconds to fade sound out. -1 to leave at default.
  195. VariantFloat mFadeTimeOut;
  196. /// Time to delay before mTransitionIn.
  197. VariantFloat mDelayTimeIn;
  198. /// Time to delay before mTransitionOut.
  199. VariantFloat mDelayTimeOut;
  200. /// Volume scale factor.
  201. VariantFloat mVolumeScale;
  202. /// Pitch scale factor.
  203. VariantFloat mPitchScale;
  204. /// Min distance for 3D sounds.
  205. VariantFloat mMinDistance;
  206. /// Max distance for 3D sounds.
  207. VariantFloat mMaxDistance;
  208. /// Number of times to loop over this slot.
  209. /// @note Each iteration will do a full transition as if proceeding
  210. /// to a different slot.
  211. U32 mRepeatCount[ NUM_SLOTS ];
  212. /// State restriction for this slot. Slot will only play when the given
  213. /// state is active and will be automatically transitioned from
  214. /// if the state becomes inactive.
  215. SFXState* mState[ NUM_SLOTS ];
  216. /// Bahavior when state of this slot is deactivated and the slot's track
  217. /// is playing.
  218. EStateMode mStateMode[ NUM_SLOTS ];
  219. SlotData()
  220. {
  221. dMemset( mReplayMode, 0, sizeof( mReplayMode ) );
  222. dMemset( mTransitionIn, 0, sizeof( mTransitionIn ) );
  223. dMemset( mTransitionOut, 0, sizeof( mTransitionOut ) );
  224. dMemset( mRepeatCount, 0, sizeof( mRepeatCount ) );
  225. dMemset( mState, 0, sizeof( mState ) );
  226. dMemset( mStateMode, 0, sizeof( mStateMode ) );
  227. for( U32 i = 0; i < NUM_SLOTS; ++ i )
  228. {
  229. mTransitionOut[ i ] = TRANSITION_Wait;
  230. mVolumeScale.mValue[ i ] = 1.f;
  231. mPitchScale.mValue[ i ] = 1.f;
  232. mFadeTimeIn.mValue[ i ] = -1.f; // Don't touch by default.
  233. mFadeTimeOut.mValue[ i ] = -1.f; // Don't touch by default.
  234. mMinDistance.mValue[ i ] = -1.f; // Don't touch by default.
  235. mMaxDistance.mValue[ i ] = -1.f; // Don't touch by default.
  236. }
  237. }
  238. };
  239. DECLARE_SOUNDASSET_ARRAY(SFXPlayList, Track, NUM_SLOTS);
  240. DECLARE_ASSET_ARRAY_SETGET(SFXPlayList, Track);
  241. protected:
  242. /// Trace interpreter execution. This field is not networked.
  243. bool mTrace;
  244. /// Select slots at random.
  245. ERandomMode mRandomMode;
  246. /// Loop over slots in this list.
  247. ELoopMode mLoopMode;
  248. /// Number of slots to play from list. This can be used, for example,
  249. /// to create a list of tracks where only a single track is selected and
  250. /// played for each cycle.
  251. U32 mNumSlotsToPlay;
  252. /// Data for each of the playlist slots.
  253. SlotData mSlots;
  254. public:
  255. SFXPlayList();
  256. /// Make all settings conform to constraints.
  257. void validate();
  258. /// Return true if execution tracing is enabled on this list.
  259. bool trace() const { return mTrace; }
  260. /// Return the number of slots to play from this list in a single cycle.
  261. U32 getNumSlotsToPlay() const { return mNumSlotsToPlay; }
  262. /// Return the slot order randomization behavior.
  263. ERandomMode getRandomMode() const { return mRandomMode; }
  264. /// Return the loop mode (only relevant if this is a looped playlist).
  265. ELoopMode getLoopMode() const { return mLoopMode; }
  266. /// Return the total number of slots in the list.
  267. U32 getNumSlots() const { return NUM_SLOTS; }
  268. /// Return the slot data for this list.
  269. const SlotData& getSlots() const { return mSlots; }
  270. DECLARE_CONOBJECT( SFXPlayList );
  271. DECLARE_CATEGORY( "SFX" );
  272. DECLARE_DESCRIPTION( "A playback list of SFXProfiles or nested SFXPlayLists." );
  273. // SimDataBlock.
  274. virtual bool preload( bool server, String& errorStr );
  275. virtual void packData( BitStream* stream );
  276. virtual void unpackData( BitStream* stream );
  277. virtual void inspectPostApply();
  278. static void initPersistFields();
  279. };
  280. typedef SFXPlayList::ELoopMode SFXPlayListLoopMode;
  281. typedef SFXPlayList::ETransitionMode SFXPlayListTransitionMode;
  282. typedef SFXPlayList::EStateMode SFXPlayListStateMode;
  283. typedef SFXPlayList::ERandomMode SFXPlayListRandomMode;
  284. typedef SFXPlayList::EReplayMode SFXPlayListReplayMode;
  285. DefineEnumType( SFXPlayListLoopMode );
  286. DefineEnumType( SFXPlayListTransitionMode );
  287. DefineEnumType( SFXPlayListStateMode );
  288. DefineEnumType( SFXPlayListRandomMode );
  289. DefineEnumType( SFXPlayListReplayMode );
  290. #endif // _SFXPLAYLIST_H_