sfxPlayList.h 13 KB

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