sfxCommon.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  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 _SFXCOMMON_H_
  23. #define _SFXCOMMON_H_
  24. #ifndef _PLATFORM_H_
  25. #include "platform/platform.h"
  26. #endif
  27. #ifndef _MMATHFN_H_
  28. #include "math/mMathFn.h"
  29. #endif
  30. #ifndef _MRANDOM_H_
  31. #include "math/mRandom.h"
  32. #endif
  33. #ifndef _MMATRIX_H_
  34. #include "math/mMatrix.h"
  35. #endif
  36. #ifndef _MPOINT3_H_
  37. #include "math/mPoint3.h"
  38. #endif
  39. #ifndef _TYPETRAITS_H_
  40. #include "platform/typetraits.h"
  41. #endif
  42. #ifndef _DYNAMIC_CONSOLETYPES_H_
  43. #include "console/dynamicTypes.h"
  44. #endif
  45. class SFXEnvironment;
  46. class SFXPlayList;
  47. //-----------------------------------------------------------------------------
  48. // SFXStatus.
  49. //-----------------------------------------------------------------------------
  50. /// The sound playback state.
  51. enum SFXStatus
  52. {
  53. /// Initial state; no operation yet performed on sound.
  54. SFXStatusNull,
  55. /// Sound is playing.
  56. SFXStatusPlaying,
  57. /// Sound has been stopped.
  58. SFXStatusStopped,
  59. /// Sound is paused.
  60. SFXStatusPaused,
  61. /// Sound stream is starved and playback blocked.
  62. SFXStatusBlocked,
  63. /// Temporary state while transitioning to another state. This is used when multiple
  64. /// threads concurrently maintain a status and need to perform a sequence of actions before
  65. /// being able to fully go from a previous to a new current state. In this case, the
  66. /// transition state marks the status as being under update on another thread.
  67. ///
  68. /// @note Not all places that use SFXStatus actually use this state.
  69. SFXStatusTransition,
  70. };
  71. DefineEnumType( SFXStatus );
  72. inline const char* SFXStatusToString( SFXStatus status )
  73. {
  74. switch ( status )
  75. {
  76. case SFXStatusPlaying: return "playing";
  77. case SFXStatusStopped: return "stopped";
  78. case SFXStatusPaused: return "paused";
  79. case SFXStatusBlocked: return "blocked";
  80. case SFXStatusTransition: return "transition";
  81. case SFXStatusNull:
  82. default: ;
  83. }
  84. return "null";
  85. }
  86. //-----------------------------------------------------------------------------
  87. // SFXChannel.
  88. //-----------------------------------------------------------------------------
  89. /// Animatable channels in the SFX system.
  90. enum SFXChannel
  91. {
  92. SFXChannelVolume,
  93. SFXChannelPitch,
  94. SFXChannelPriority,
  95. SFXChannelPositionX,
  96. SFXChannelPositionY,
  97. SFXChannelPositionZ,
  98. SFXChannelRotationX,
  99. SFXChannelRotationY,
  100. SFXChannelRotationZ,
  101. SFXChannelVelocityX,
  102. SFXChannelVelocityY,
  103. SFXChannelVelocityZ,
  104. SFXChannelMinDistance,
  105. SFXChannelMaxDistance,
  106. SFXChannelConeInsideAngle,
  107. SFXChannelConeOutsideAngle,
  108. SFXChannelConeOutsideVolume,
  109. SFXChannelCursor,
  110. SFXChannelStatus,
  111. SFXChannelUser0,
  112. SFXChannelUser1,
  113. SFXChannelUser2,
  114. SFXChannelUser3,
  115. /// Total number of animatable channels.
  116. SFX_NUM_CHANNELS
  117. };
  118. DefineEnumType( SFXChannel );
  119. //-----------------------------------------------------------------------------
  120. // SFXDistanceModel.
  121. //-----------------------------------------------------------------------------
  122. /// Rolloff curve used for distance volume attenuation of 3D sounds.
  123. enum SFXDistanceModel
  124. {
  125. SFXDistanceModelLinear, ///< Volume decreases linearly from min to max where it reaches zero.
  126. SFXDistanceModelLogarithmic, ///< Volume halves every min distance steps starting from min distance; attenuation stops at max distance.
  127. };
  128. DefineEnumType( SFXDistanceModel );
  129. /// Compute the distance attenuation based on the given distance model.
  130. ///
  131. /// @param minDistance Reference distance; attenuation starts here.
  132. /// @param maxDistance
  133. /// @param distance Actual distance of sound from listener.
  134. /// @param volume Unattenuated volume.
  135. /// @param rolloffFactor Rolloff curve scale factor.
  136. ///
  137. /// @return The attenuated volume.
  138. inline F32 SFXDistanceAttenuation( SFXDistanceModel model, F32 minDistance, F32 maxDistance, F32 distance, F32 volume, F32 rolloffFactor )
  139. {
  140. F32 gain = 1.0f;
  141. switch( model )
  142. {
  143. case SFXDistanceModelLinear:
  144. distance = getMax( distance, minDistance );
  145. distance = getMin( distance, maxDistance );
  146. gain = ( 1 - ( distance - minDistance ) / ( maxDistance - minDistance ) );
  147. break;
  148. case SFXDistanceModelLogarithmic:
  149. distance = getMax( distance, minDistance );
  150. distance = getMin( distance, maxDistance );
  151. gain = minDistance / ( minDistance + rolloffFactor * ( distance - minDistance ) );
  152. break;
  153. }
  154. return ( volume * gain );
  155. }
  156. //-----------------------------------------------------------------------------
  157. // SFXFormat.
  158. //-----------------------------------------------------------------------------
  159. /// This class defines the various types of sound data that may be
  160. /// used in the sound system.
  161. ///
  162. /// Unlike with most sound APIs, we consider each sample point to comprise
  163. /// all channels in a sound stream rather than only one value for a single
  164. /// channel.
  165. class SFXFormat
  166. {
  167. protected:
  168. /// The number of sound channels in the data.
  169. U8 mChannels;
  170. /// The number of bits per sound sample.
  171. U8 mBitsPerSample;
  172. /// The frequency in samples per second.
  173. U32 mSamplesPerSecond;
  174. public:
  175. SFXFormat( U8 channels = 0,
  176. U8 bitsPerSample = 0,
  177. U32 samplesPerSecond = 0 )
  178. : mChannels( channels ),
  179. mBitsPerSample( bitsPerSample ),
  180. mSamplesPerSecond( samplesPerSecond )
  181. {}
  182. /// Copy constructor.
  183. SFXFormat( const SFXFormat &format )
  184. : mChannels( format.mChannels ),
  185. mBitsPerSample( format.mBitsPerSample ),
  186. mSamplesPerSecond( format.mSamplesPerSecond )
  187. {}
  188. public:
  189. /// Sets the format.
  190. void set( U8 channels,
  191. U8 bitsPerSample,
  192. U32 samplesPerSecond )
  193. {
  194. mChannels = channels;
  195. mBitsPerSample = bitsPerSample;
  196. mSamplesPerSecond = samplesPerSecond;
  197. }
  198. /// Comparision between formats.
  199. bool operator == ( const SFXFormat& format ) const
  200. {
  201. return mChannels == format.mChannels &&
  202. mBitsPerSample == format.mBitsPerSample &&
  203. mSamplesPerSecond == format.mSamplesPerSecond;
  204. }
  205. /// Returns the number of sound channels.
  206. U8 getChannels() const { return mChannels; }
  207. /// Returns true if there is a single sound channel.
  208. bool isMono() const { return mChannels == 1; }
  209. /// Is true if there are two sound channels.
  210. bool isStereo() const { return mChannels == 2; }
  211. /// Is true if there are more than two sound channels.
  212. bool isMultiChannel() const { return mChannels > 2; }
  213. ///
  214. U32 getSamplesPerSecond() const { return mSamplesPerSecond; }
  215. /// The bits of data per channel.
  216. U8 getBitsPerChannel() const { return mBitsPerSample / mChannels; }
  217. /// The number of bytes of data per channel.
  218. U8 getBytesPerChannel() const { return getBitsPerChannel() / 8; }
  219. /// The number of bits per sound sample.
  220. U8 getBitsPerSample() const { return mBitsPerSample; }
  221. /// The number of bytes of data per sample.
  222. /// @note Be aware that this comprises all channels.
  223. U8 getBytesPerSample() const { return mBitsPerSample / 8; }
  224. /// Returns the duration from the sample count.
  225. U32 getDuration( U32 samples ) const
  226. {
  227. // Use 64bit types to avoid overflow during division.
  228. return ( (U64)samples * (U64)1000 ) / (U64)mSamplesPerSecond;
  229. }
  230. ///
  231. U32 getSampleCount( U32 ms ) const
  232. {
  233. return U64( mSamplesPerSecond ) * U64( ms ) / U64( 1000 );
  234. }
  235. /// Returns the data length in bytes.
  236. U32 getDataLength( U32 ms ) const
  237. {
  238. U32 bytes = ( ( (U64)ms * (U64)mSamplesPerSecond ) * (U64)getBytesPerSample() ) / (U64)1000;
  239. return bytes;
  240. }
  241. };
  242. //-----------------------------------------------------------------------------
  243. // SFXReverb.
  244. //-----------------------------------------------------------------------------
  245. /// Reverb environment properties.
  246. ///
  247. /// @note A given device may not implement all properties.
  248. class SFXReverbProperties
  249. {
  250. public:
  251. typedef void Parent;
  252. F32 mEnvSize;
  253. F32 mEnvDiffusion;
  254. S32 mRoom;
  255. S32 mRoomHF;
  256. S32 mRoomLF;
  257. F32 mDecayTime;
  258. F32 mDecayHFRatio;
  259. F32 mDecayLFRatio;
  260. S32 mReflections;
  261. F32 mReflectionsDelay;
  262. F32 mReflectionsPan[ 3 ];
  263. S32 mReverb;
  264. F32 mReverbDelay;
  265. F32 mReverbPan[ 3 ];
  266. F32 mEchoTime;
  267. F32 mEchoDepth;
  268. F32 mModulationTime;
  269. F32 mModulationDepth;
  270. F32 mAirAbsorptionHF;
  271. F32 mHFReference;
  272. F32 mLFReference;
  273. F32 mRoomRolloffFactor;
  274. F32 mDiffusion;
  275. F32 mDensity;
  276. S32 mFlags;
  277. SFXReverbProperties()
  278. : mEnvSize( 7.5f ),
  279. mEnvDiffusion( 1.0f ),
  280. mRoom( -1000 ),
  281. mRoomHF( -100 ),
  282. mRoomLF( 0 ),
  283. mDecayTime( 1.49f ),
  284. mDecayHFRatio( 0.83f ),
  285. mDecayLFRatio( 1.0f ),
  286. mReflections( -2602 ),
  287. mReflectionsDelay( 0.007f ),
  288. mReverb( 200 ),
  289. mReverbDelay( 0.011f ),
  290. mEchoTime( 0.25f ),
  291. mEchoDepth( 0.0f ),
  292. mModulationTime( 0.25f ),
  293. mModulationDepth( 0.0f ),
  294. mAirAbsorptionHF( -5.0f ),
  295. mHFReference( 5000.0f ),
  296. mLFReference( 250.0f ),
  297. mRoomRolloffFactor( 0.0f ),
  298. mDiffusion( 100.0f ),
  299. mDensity( 100.0f ),
  300. mFlags( 0 )
  301. {
  302. mReflectionsPan[ 0 ] = 0.0f;
  303. mReflectionsPan[ 1 ] = 0.0f;
  304. mReflectionsPan[ 2 ] = 0.0f;
  305. mReverbPan[ 0 ] = 0.0f;
  306. mReverbPan[ 1 ] = 0.0f;
  307. mReverbPan[ 2 ] = 0.0f;
  308. }
  309. void validate()
  310. {
  311. mEnvSize = mClampF( mEnvSize, 1.0f, 100.0f );
  312. mEnvDiffusion = mClampF( mEnvDiffusion, 0.0f, 1.0f );
  313. mRoom = mClamp( mRoom, -10000, 0 );
  314. mRoomHF = mClamp( mRoomHF, -10000, 0 );
  315. mRoomLF = mClamp( mRoomLF, -10000, 0 );
  316. mDecayTime = mClampF( mDecayTime, 0.1f, 20.0f );
  317. mDecayHFRatio = mClampF( mDecayHFRatio, 0.1f, 2.0f );
  318. mDecayLFRatio = mClampF( mDecayLFRatio, 0.1f, 2.0f );
  319. mReflections = mClamp( mReflections, -10000, 1000 );
  320. mReflectionsDelay = mClampF( mReflectionsDelay, 0.0f, 0.3f );
  321. mReverb = mClamp( mReverb, -10000, 2000 );
  322. mReverbDelay = mClampF( mReverbDelay, 0.0f, 0.1f );
  323. mEchoTime = mClampF( mEchoTime, 0.075f, 0.25f );
  324. mEchoDepth = mClampF( mEchoDepth, 0.0f, 1.0f );
  325. mModulationTime = mClampF( mModulationTime, 0.04f, 4.0f );
  326. mModulationDepth = mClampF( mModulationDepth, 0.0f, 1.0f );
  327. mAirAbsorptionHF = mClampF( mAirAbsorptionHF, -100.0f, 0.0f );
  328. mHFReference = mClampF( mHFReference, 1000.0f, 20000.0f );
  329. mLFReference = mClampF( mLFReference, 20.0f, 1000.0f );
  330. mRoomRolloffFactor = mClampF( mRoomRolloffFactor, 0.0f, 10.0f );
  331. mDiffusion = mClampF( mDiffusion, 0.0f, 100.0f );
  332. mDensity = mClampF( mDensity, 0.0f, 100.0f );
  333. }
  334. };
  335. //-----------------------------------------------------------------------------
  336. // SFXSoundReverbProperties.
  337. //-----------------------------------------------------------------------------
  338. /// Sound reverb properties.
  339. ///
  340. /// @note A given SFX device may not implement all properties.
  341. class SFXSoundReverbProperties
  342. {
  343. public:
  344. typedef void Parent;
  345. S32 mDirect;
  346. S32 mDirectHF;
  347. S32 mRoom;
  348. S32 mRoomHF;
  349. S32 mObstruction;
  350. F32 mObstructionLFRatio;
  351. S32 mOcclusion;
  352. F32 mOcclusionLFRatio;
  353. F32 mOcclusionRoomRatio;
  354. F32 mOcclusionDirectRatio;
  355. S32 mExclusion;
  356. F32 mExclusionLFRatio;
  357. S32 mOutsideVolumeHF;
  358. F32 mDopplerFactor;
  359. F32 mRolloffFactor;
  360. F32 mRoomRolloffFactor;
  361. F32 mAirAbsorptionFactor;
  362. S32 mFlags;
  363. SFXSoundReverbProperties()
  364. : mDirect( 0 ),
  365. mDirectHF( 0 ),
  366. mRoom( 0 ),
  367. mRoomHF( 0 ),
  368. mObstruction( 0 ),
  369. mObstructionLFRatio( 0.0f ),
  370. mOcclusion( 0 ),
  371. mOcclusionLFRatio( 0.25f ),
  372. mOcclusionRoomRatio( 1.5f ),
  373. mOcclusionDirectRatio( 1.0f ),
  374. mExclusion( 0 ),
  375. mExclusionLFRatio( 1.0f ),
  376. mOutsideVolumeHF( 0 ),
  377. mDopplerFactor( 0.0f ),
  378. mRolloffFactor( 0.0f ),
  379. mRoomRolloffFactor( 0.0f ),
  380. mAirAbsorptionFactor( 1.0f ),
  381. mFlags( 0 )
  382. {
  383. }
  384. void validate()
  385. {
  386. mDirect = mClamp( mDirect, -10000, 1000 );
  387. mDirectHF = mClamp( mDirectHF, -10000, 0 );
  388. mRoom = mClamp( mRoom, -10000, 1000 );
  389. mRoomHF = mClamp( mRoomHF, -10000, 0 );
  390. mObstruction = mClamp( mObstruction, -10000, 0 );
  391. mObstructionLFRatio = mClampF( mObstructionLFRatio, 0.0f, 1.0f );
  392. mOcclusion = mClamp( mOcclusion, -10000, 0 );
  393. mOcclusionLFRatio = mClampF( mOcclusionLFRatio, 0.0f, 1.0f );
  394. mOcclusionRoomRatio = mClampF( mOcclusionRoomRatio, 0.0f, 10.0f );
  395. mOcclusionDirectRatio= mClampF( mOcclusionDirectRatio, 0.0f, 10.0f );
  396. mExclusion = mClamp( mExclusion, -10000, 0 );
  397. mExclusionLFRatio = mClampF( mExclusionLFRatio, 0.0f, 1.0f );
  398. mOutsideVolumeHF = mClamp( mOutsideVolumeHF, -10000, 0 );
  399. mDopplerFactor = mClampF( mDopplerFactor, 0.0f, 10.0f );
  400. mRolloffFactor = mClampF( mRolloffFactor, 0.0f, 10.0f );
  401. mRoomRolloffFactor = mClampF( mRoomRolloffFactor, 0.0f, 10.0f );
  402. mAirAbsorptionFactor = mClampF( mAirAbsorptionFactor, 0.0f, 10.0f );
  403. }
  404. };
  405. //-----------------------------------------------------------------------------
  406. // SFXListenerProperties.
  407. //-----------------------------------------------------------------------------
  408. ///
  409. class SFXListenerProperties
  410. {
  411. public:
  412. typedef void Parent;
  413. /// Position and orientation of the listener.
  414. MatrixF mTransform;
  415. ///
  416. Point3F mVelocity;
  417. SFXListenerProperties()
  418. : mTransform( true ),
  419. mVelocity( 0.0f, 0.0f, 0.0f ) {}
  420. SFXListenerProperties( const MatrixF& transform, const Point3F& velocity )
  421. : mTransform( transform ),
  422. mVelocity( velocity ) {}
  423. ///
  424. const MatrixF& getTransform() const { return mTransform; }
  425. MatrixF& getTransform() { return mTransform; }
  426. ///
  427. const Point3F& getVelocity() const { return mVelocity; }
  428. Point3F& getVelocity() { return mVelocity; }
  429. };
  430. //-----------------------------------------------------------------------------
  431. // SFXMaterialProperties.
  432. //-----------------------------------------------------------------------------
  433. ///
  434. class SFXMaterialProperties
  435. {
  436. public:
  437. typedef void Parent;
  438. ///
  439. bool mDoubleSided;
  440. ///
  441. F32 mDirectOcclusion;
  442. ///
  443. F32 mReverbOcclusion;
  444. SFXMaterialProperties()
  445. : mDoubleSided( false ),
  446. mDirectOcclusion( 0.5f ),
  447. mReverbOcclusion( 0.5f ) {}
  448. void validate()
  449. {
  450. mDirectOcclusion = mClampF( mDirectOcclusion, 0.0f, 1.0f );
  451. mReverbOcclusion = mClampF( mReverbOcclusion, 0.0f, 1.0f );
  452. }
  453. };
  454. //-----------------------------------------------------------------------------
  455. // SFXVariantFloat.
  456. //-----------------------------------------------------------------------------
  457. /// An array of float values with optional random variances.
  458. template< S32 NUM_VALUES >
  459. struct SFXVariantFloat
  460. {
  461. /// Base value.
  462. F32 mValue[ NUM_VALUES ];
  463. /// Variance of value. Final value will be
  464. ///
  465. /// mClampF( randF( mValue + mVariance[ 0 ], mValue + mVariance[ 1 ] ), min, max )
  466. ///
  467. /// with min and max being dependent on the context of the value.
  468. F32 mVariance[ NUM_VALUES ][ 2 ];
  469. F32 getValue( U32 index = 0, F32 min = TypeTraits< F32 >::MIN, F32 max = TypeTraits< F32 >::MAX ) const
  470. {
  471. AssertFatal( index < NUM_VALUES, "SFXVariantFloat::getValue() - index out of range!" );
  472. return mClampF( gRandGen.randF( mValue[ index ] + mVariance[ index ][ 0 ],
  473. mValue[ index ] + mVariance[ index ][ 1 ] ),
  474. min, max );
  475. }
  476. void validate()
  477. {
  478. for( U32 i = 0; i < NUM_VALUES; ++ i )
  479. mVariance[ i ][ 0 ] = getMin( mVariance[ i ][ 0 ], mVariance[ i ][ 1 ] );
  480. }
  481. };
  482. #endif // _SFXCOMMON_H_