sfxPlayList.h 14 KB

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