sfxSource.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671
  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 _SFXSOURCE_H_
  23. #define _SFXSOURCE_H_
  24. #ifndef _SIMSET_H_
  25. #include "console/simSet.h"
  26. #endif
  27. #ifndef _SFXCOMMON_H_
  28. #include "sfx/sfxCommon.h"
  29. #endif
  30. #ifndef _SFXDESCRIPTION_H_
  31. #include "sfx/sfxDescription.h"
  32. #endif
  33. #ifndef _SFXPARAMETER_H_
  34. #include "sfx/sfxParameter.h"
  35. #endif
  36. #ifndef _TVECTOR_H_
  37. #include "core/util/tVector.h"
  38. #endif
  39. #ifndef _TIMESOURCE_H_
  40. #include "core/util/timeSource.h"
  41. #endif
  42. #ifndef _BITSET_H_
  43. #include "core/bitSet.h"
  44. #endif
  45. #ifndef _TORQUE_LIST_
  46. #include "core/util/tList.h"
  47. #endif
  48. class SFXTrack;
  49. class SFXDescription;
  50. class SFXSourceGroup;
  51. class SFXModifier;
  52. class EaseF;
  53. /// Baseclass for sources and controllers.
  54. class SFXSource : public SimGroup
  55. {
  56. public:
  57. typedef SimGroup Parent;
  58. friend class SFXSystem; // _init
  59. protected:
  60. typedef Torque::List< SFXModifier* > ModifierList;
  61. typedef GenericTimeSource< RealMSTimer > TimeSource;
  62. enum Flags
  63. {
  64. CustomVolumeFlag = BIT( 0 ),
  65. CustomPitchFlag = BIT( 1 ),
  66. CustomPriorityFlag = BIT( 2 ),
  67. CustomRadiusFlag = BIT( 3 ),
  68. CustomConeFlag = BIT( 4 ),
  69. CustomFadeFlag = BIT( 5 ),
  70. CustomGroupFlag = BIT( 6 ),
  71. };
  72. ///
  73. BitSet32 mFlags;
  74. /// @name Status
  75. /// @{
  76. /// Current playback status.
  77. SFXStatus mStatus;
  78. /// The playback status that the source actually wants to be in.
  79. SFXStatus mSavedStatus;
  80. /// Console functions to call when the source status changes.
  81. /// If not set, "onStatusChange" will be called on the source object.
  82. StringTableEntry mStatusCallback;
  83. /// Used internally for setting the sound status.
  84. virtual void _setStatus( SFXStatus newStatus );
  85. /// Update the playback status of the source. Meant for subclasses
  86. /// that need to poll a connected resource.
  87. virtual void _updateStatus() {}
  88. /// @}
  89. /// @name Datablocks
  90. ///
  91. /// The track datablock is optional but the description datablock is required.
  92. /// If either of the two goes away, the source will auto-delete itself.
  93. ///
  94. /// These members are SimObjectPtr so that temporary track and description
  95. /// objects that are set to auto-delete will work.
  96. ///
  97. /// @{
  98. /// The track being played by this source.
  99. /// @note Will be null for sources that have been created from SFXStreams.
  100. SimObjectPtr< SFXTrack > mTrack;
  101. /// The description holding the SFX sound configuration.
  102. SimObjectPtr< SFXDescription > mDescription;
  103. /// @}
  104. /// @name Volume
  105. ///
  106. /// Volume processing goes through a series of stages. The last stage, distance attenuation,
  107. /// happens only for 3D sounds and is done on the device (though the attenuated volume is also
  108. /// computed within SFX).
  109. ///
  110. /// The succession of stages is:
  111. ///
  112. /// 1. Fade (Apply fade-in/out if currently active)
  113. /// 2. Modulate (Apply scale factor set on source)
  114. /// 3. Modulate (Apply attenuated volume of source group as scale factor)
  115. /// 4. Attenuate (Apply 3D distance attenuation based on current listener position)
  116. ///
  117. /// @{
  118. /// The desired sound volume.
  119. F32 mVolume;
  120. /// Volume before fade stage. Used as input to volume computation. Usually this
  121. /// corresponds to mVolume but when fading out from an already faded start volume,
  122. /// this contains the starting mFadedVolume.
  123. F32 mPreFadeVolume;
  124. /// "mVolume" after fade stage. Same as "mPreFadeVolume" if no fade
  125. /// is active.
  126. F32 mFadedVolume;
  127. /// Volume scale factor imposed on this source by controller.
  128. F32 mModulativeVolume;
  129. /// Effective volume after fade and modulation but before distance attenuation.
  130. /// For non-3D sounds, this is the final effective volume.
  131. F32 mPreAttenuatedVolume;
  132. /// Effective volume after distance attenuation. Continuously updated
  133. /// to match listener position. For non-3D sounds, this is the same
  134. /// as mPreAttenuatedVolume.
  135. ///
  136. /// @note The distance attenuation that is computed here does not take
  137. /// sound cones into account so the computed attenuated volume may be
  138. /// higher than the actual effective volume on the device (never
  139. /// lower though).
  140. F32 mAttenuatedVolume;
  141. /// Set volume without affecting CustomVolumeFlag.
  142. void _setVolume( F32 volume );
  143. /// Update the effective volume of the source.
  144. virtual void _updateVolume( const MatrixF& listener );
  145. /// @}
  146. /// @name Virtualization
  147. /// @{
  148. /// The desired sound priority.
  149. F32 mPriority;
  150. /// The priority scale factor imposed by controllers.
  151. F32 mModulativePriority;
  152. /// The final priority level.
  153. F32 mEffectivePriority;
  154. /// Set priority without affecting CustomPriorityFlag.
  155. void _setPriority( F32 priority );
  156. /// Update the effective priority of the source.
  157. virtual void _updatePriority();
  158. /// @}
  159. /// @name Pitch
  160. /// @{
  161. /// The desired sound pitch.
  162. F32 mPitch;
  163. /// The pitch scale factor imposed by controllers.
  164. F32 mModulativePitch;
  165. /// The final effective pitch.
  166. F32 mEffectivePitch;
  167. /// Set pitch without affecting CustomPitchFlag.
  168. void _setPitch( F32 pitch );
  169. /// Update the effective pitch of the source.
  170. virtual void _updatePitch();
  171. ///
  172. /// @}
  173. /// @name 3D Sound
  174. /// @{
  175. /// The transform if this is a 3d source.
  176. MatrixF mTransform;
  177. /// The last set velocity.
  178. VectorF mVelocity;
  179. /// Distance at which to begin distanced-based volume attenuation.
  180. F32 mMinDistance;
  181. /// Distance at which to stop distance-based volume attenuation.
  182. F32 mMaxDistance;
  183. /// Inside cone angle in degrees.
  184. F32 mConeInsideAngle;
  185. /// Outside cone angle in degrees.
  186. F32 mConeOutsideAngle;
  187. /// Outside cone volume.
  188. F32 mConeOutsideVolume;
  189. /// The distance of this source to the last
  190. /// listener position.
  191. F32 mDistToListener;
  192. /// If true, the transform position has been randomized.
  193. bool mTransformScattered;
  194. /// Randomize transform based on scatter settings.
  195. void _scatterTransform();
  196. /// Set 3D min/max distance without affecting CustomRadiusFlag.
  197. virtual void _setMinMaxDistance( F32 min, F32 max );
  198. /// Set 3D cone without affecting CustomConeFlag.
  199. virtual void _setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume );
  200. /// @}
  201. /// @name Fading
  202. ///
  203. /// The fade system consists of "persistent" fades placed at the beginning
  204. /// and end of the playback range and of "temporary" fade segments placed in the
  205. /// playback range when stopping/pausing/resuming a source in midst of playback.
  206. ///
  207. /// @{
  208. /// The current "persistent" fade-in time in seconds. Taken initially from the
  209. /// SFXDescription and as long as not being manually set on the source, will
  210. /// stay with the description's "fadeInTime" property.
  211. F32 mFadeInTime;
  212. /// The current "persistent" fade-out time in seconds. Taken initially from the
  213. /// SFXDescription and as long as not being manually set on the source, will
  214. /// stay with the description's "fadeOutTime" property.
  215. F32 mFadeOutTime;
  216. /// Type for temporary fade segments.
  217. enum FadeSegmentType
  218. {
  219. FadeSegmentNone, ///< No temporary fade segment set.
  220. FadeSegmentPlay, ///< Temporary fade-in segment.
  221. FadeSegmentStop, ///< Temporary fade-out segment ending in stop().
  222. FadeSegmentPause ///< Temporary fade-out segment ending in pause().
  223. };
  224. /// Playtime at which persistent fade-in ends. -1 if no fade-in.
  225. F32 mFadeInPoint;
  226. /// Playtime at which persistent fade-out starts. -1 if no fade-out.
  227. F32 mFadeOutPoint;
  228. /// Type of the current temporary fade segment. No temporary fade segment
  229. /// is in place when this is FadeSegmentNone.
  230. FadeSegmentType mFadeSegmentType;
  231. /// Easing curve for the current fade segment.
  232. EaseF* mFadeSegmentEase;
  233. /// Playback position where the current temporary fade segment starts.
  234. F32 mFadeSegmentStartPoint;
  235. /// Playback position where the current temporary fade segment ends.
  236. F32 mFadeSegmentEndPoint;
  237. /// Fade time to apply when transitioning to mSavedStatus.
  238. F32 mSavedFadeTime;
  239. ///
  240. virtual void _setFadeTimes( F32 fadeInTime, F32 fadeOutTime );
  241. /// Set up a temporary fade-out segment.
  242. void _setupFadeOutSegment( FadeSegmentType type, F32 fadeOutTime );
  243. /// @}
  244. /// @name Parameters
  245. /// @{
  246. ///
  247. Vector< SFXParameter* > mParameters;
  248. ///
  249. void _addParameter( StringTableEntry name );
  250. ///
  251. virtual void _onParameterEvent( SFXParameter* parameter, SFXParameterEvent event );
  252. /// @}
  253. /// @name Playback
  254. /// @{
  255. /// The simulation tick count that playback was started at for this source.
  256. U32 mPlayStartTick;
  257. /// Time object used to keep track of playback.
  258. TimeSource mPlayTimer;
  259. /// Start playback. For implementation by concrete subclasses.
  260. /// @note This method should not take fading into account.
  261. virtual void _play();
  262. /// Pause playback. For implementation by concrete subclasses.
  263. /// @note This method should not take fading into account.
  264. virtual void _pause();
  265. /// Stop playback. For implementation by concrete subclasses.
  266. /// @note This method should not take fading into account.
  267. virtual void _stop();
  268. /// @}
  269. /// @name Modifiers
  270. /// @{
  271. /// List of modifiers that are active on this source.
  272. ModifierList mModifiers;
  273. /// Delete all modifiers of the given type.
  274. template< class T > void _clearModifiers();
  275. /// @}
  276. /// @name Callbacks
  277. /// @{
  278. DECLARE_CALLBACK( void, onStatusChange, ( SFXStatus newStatus ) );
  279. DECLARE_CALLBACK( void, onParameterValueChange, ( SFXParameter* parameter ) );
  280. /// @}
  281. ///
  282. SFXSource( SFXTrack* track, SFXDescription* description = NULL );
  283. ///
  284. virtual void _update();
  285. /// We overload this to disable creation of
  286. /// a source via script 'new'.
  287. virtual bool processArguments( S32 argc, ConsoleValue *argv );
  288. // Console getters/setters.
  289. static bool _setDescription( void *obj, const char *index, const char *data );
  290. static const char* _getDescription( void* obj, const char* data );
  291. public:
  292. ///
  293. SFXSource();
  294. ~SFXSource();
  295. ///
  296. void update();
  297. /// Returns the track played by this source; NULL for sources playing directly
  298. /// from streams.
  299. SFXTrack* getTrack() const;
  300. /// Return the SFX description associated with this source. Never NULL.
  301. SFXDescription* getDescription() const { return mDescription; }
  302. /// Return the source group that this source has been assigned to.
  303. SFXSource* getSourceGroup() const;
  304. /// @name Playback Status
  305. /// @{
  306. /// Returns the last known status without doing an update.
  307. SFXStatus getLastStatus() const { return mStatus; }
  308. /// Return the status that the source wants to be in. Used for playback
  309. /// control in combination with source groups.
  310. SFXStatus getSavedStatus() const { return mSavedStatus; }
  311. /// Returns the sound status.
  312. SFXStatus getStatus() const { const_cast< SFXSource* >( this )->_updateStatus(); return mStatus; }
  313. /// Returns true if the source is playing.
  314. bool isPlaying() const { return getStatus() == SFXStatusPlaying; }
  315. /// Returns true if the source is stopped.
  316. bool isStopped() const { return getStatus() == SFXStatusStopped; }
  317. /// Returns true if the source has been paused.
  318. bool isPaused() const { return getStatus() == SFXStatusPaused; }
  319. /// Returns true if the source is currently being virtualized.
  320. virtual bool isVirtualized() const { return false; }
  321. /// Returns true if this is a looping source.
  322. bool isLooping() const { return mDescription.isValid() && mDescription->mIsLooping; }
  323. /// @}
  324. /// @name Playback Control
  325. /// @{
  326. /// Starts the sound from the current playback position.
  327. ///
  328. /// @param fadeInTime Seconds for sound to fade in. If -1, fadeInTime from
  329. /// SFXDescription is used. Note that certain SFXSource classes may not
  330. /// support values other than 0 and -1.
  331. virtual void play( F32 fadeInTime = -1.f );
  332. /// Stops playback and resets the playback position.
  333. ///
  334. /// @note This method is also required to release all playback-related
  335. /// resources on the device.
  336. ///
  337. /// @param fadeOutTime Seconds for sound to fade out. If -1, fadeOutTime from
  338. /// SFXDescription is used. Note that certain SFXSource classes may not support
  339. /// values other than 0 and -1.
  340. virtual void stop( F32 fadeOutTime = -1.f );
  341. /// Pauses the sound playback.
  342. ///
  343. /// @param fadeOutTime Seconds for sound to fade out. If -1, fadeOutTime from
  344. /// SFXDescription is used. Note that certain SFXSource clsases may not support
  345. /// values other than 0 and -1.
  346. virtual void pause( F32 fadeOutTime = -1.f );
  347. /// Return the elapsed play time of the current loop cycle so far in seconds.
  348. virtual F32 getElapsedPlayTimeCurrentCycle() const;
  349. /// Return the total elapsed play time so far in seconds.
  350. virtual F32 getElapsedPlayTime() const;
  351. /// Return the total play time of the source in seconds. Positive infinity by default.
  352. ///
  353. /// @note For looping sounds, this must include only the playtime of a single cycle.
  354. virtual F32 getTotalPlayTime() const;
  355. /// @}
  356. /// @name 3D Sound
  357. /// @{
  358. /// Returns true if this is a 3D source.
  359. bool is3d() const { return mDescription->mIs3D; }
  360. /// Returns the last set velocity.
  361. const VectorF& getVelocity() const { return mVelocity; }
  362. /// Returns the last set transform.
  363. const MatrixF& getTransform() const { return mTransform; }
  364. /// Sets the position and orientation for a 3d buffer.
  365. virtual void setTransform( const MatrixF& transform );
  366. /// Sets the velocity for a 3d buffer.
  367. virtual void setVelocity( const VectorF& velocity );
  368. /// Sets the minimum and maximum distances for 3d falloff.
  369. void setMinMaxDistance( F32 min, F32 max ) { _setMinMaxDistance( min, max ); mFlags.set( CustomRadiusFlag ); }
  370. /// Set sound cone of a 3D sound.
  371. ///
  372. /// @param innerAngle Inner cone angle in degrees.
  373. /// @param outerAngle Outer cone angle in degrees.
  374. /// @param outerVolume Outer volume factor.
  375. void setCone( F32 innerAngle, F32 outerAngle, F32 outerVolume ) { _setCone( innerAngle, outerAngle, outerVolume ); mFlags.set( CustomConeFlag ); }
  376. /// Returns the last distance to the listener.
  377. /// @note Only works when distance attenuation calculations are being triggered by SFX and
  378. /// are not left exclusively to the SFX device.
  379. F32 getDistToListener() const { return mDistToListener; }
  380. /// @}
  381. /// @name Volume
  382. /// @{
  383. /// Returns the source volume at its unaltered initial setting,
  384. /// i.e. prior to fading, modulation, and attenuation.
  385. F32 getVolume() const { return mVolume; }
  386. /// Sets the source volume which will still be
  387. /// scaled by the master and group volumes.
  388. ///
  389. /// @note Note that if you set an explicit volume on a source
  390. void setVolume( F32 volume ) { _setVolume( volume ); mFlags.set( CustomVolumeFlag ); }
  391. ///
  392. F32 getModulativeVolume() const { return mModulativeVolume; }
  393. /// Set the per-source volume scale factor.
  394. void setModulativeVolume( F32 value );
  395. ///
  396. F32 getPreAttenuatedVolume() const { return mPreAttenuatedVolume; }
  397. /// Returns the volume with respect to the master
  398. /// and group volumes and the listener.
  399. F32 getAttenuatedVolume() const { return mAttenuatedVolume; }
  400. ///
  401. F32 getFadeInTime() const { return mFadeInTime; }
  402. ///
  403. F32 getFadeOutTime() const { return mFadeOutTime; }
  404. ///
  405. void setFadeTimes( F32 fadeInTime, F32 fadeOutTime );
  406. /// @}
  407. /// @name Pitch
  408. /// @{
  409. /// Returns the source pitch scale.
  410. F32 getPitch() const { return mPitch; }
  411. /// Sets the source pitch scale.
  412. void setPitch( F32 pitch ) { _setPitch( pitch ); mFlags.set( CustomPitchFlag ); }
  413. ///
  414. F32 getModulativePitch() const { return mModulativePitch; }
  415. ///
  416. void setModulativePitch( F32 value );
  417. ///
  418. F32 getEffectivePitch() const { return mEffectivePitch; }
  419. /// @}
  420. /// @name Dynamic Parameters
  421. ///
  422. /// Dynamic parameters allow to pass on values from the game system to the sound system
  423. /// and thus implement interactive audio.
  424. ///
  425. /// It is dependent on the back-end source implementation how it will react to parameter
  426. /// settings.
  427. ///
  428. /// @{
  429. ///
  430. U32 getNumParameters() const { return mParameters.size(); }
  431. ///
  432. SFXParameter* getParameter( U32 index )
  433. {
  434. AssertFatal( index < getNumParameters(), "SFXSource::getParameter() - index out of range" );
  435. return mParameters[ index ];
  436. }
  437. ///
  438. virtual void addParameter( SFXParameter* parameter );
  439. ///
  440. virtual void removeParameter( SFXParameter* parameter );
  441. /// @}
  442. /// @name Modifiers
  443. /// @{
  444. ///
  445. void addModifier( SFXModifier* modifier );
  446. ///
  447. void addMarker( const String& name, F32 pos );
  448. /// @}
  449. /// @name Virtualization
  450. /// @{
  451. /// Returns the source priority.
  452. F32 getPriority() const { return mPriority; }
  453. ///
  454. void setPriority( F32 priority ) { _setPriority( priority ); mFlags.set( CustomPriorityFlag ); }
  455. ///
  456. F32 getModulativePriority() const { return mModulativePriority; }
  457. ///
  458. void setModulativePriority( F32 value );
  459. ///
  460. F32 getEffectivePriority() const { return mEffectivePriority; }
  461. /// @}
  462. /// @}
  463. /// @name Change Notifications
  464. /// @{
  465. /// Notify the source that its attached SFXDescription has changed.
  466. virtual void notifyDescriptionChanged();
  467. /// Notify the source that its attached SFXTrack has changed.
  468. virtual void notifyTrackChanged();
  469. /// @}
  470. // SimGroup.
  471. virtual bool onAdd();
  472. virtual void onRemove();
  473. virtual void onDeleteNotify( SimObject* object );
  474. virtual bool acceptsAsChild( SimObject* object );
  475. virtual void onGroupAdd();
  476. static void initPersistFields();
  477. DECLARE_CONOBJECT( SFXSource );
  478. DECLARE_CATEGORY( "SFX" );
  479. DECLARE_DESCRIPTION( "SFX sound playback controller." );
  480. };
  481. /// A simple macro to automate the deletion of a source.
  482. ///
  483. /// @see SFXSource
  484. ///
  485. #undef SFX_DELETE
  486. #define SFX_DELETE( source ) \
  487. if( source ) \
  488. { \
  489. source->deleteObject(); \
  490. source = NULL; \
  491. } \
  492. #endif // !_SFXSOURCE_H_