sfxXAudioDevice.cpp 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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. #include "sfx/xaudio/sfxXAudioDevice.h"
  23. #include "platform/async/asyncUpdate.h"
  24. #include "core/stringTable.h"
  25. #include "console/console.h"
  26. #include "core/util/safeRelease.h"
  27. #include "core/tAlgorithm.h"
  28. #include "platform/profiler.h"
  29. SFXXAudioDevice::SFXXAudioDevice( SFXProvider* provider,
  30. const String& name,
  31. IXAudio2 *xaudio,
  32. U32 deviceIndex,
  33. U32 speakerChannelMask,
  34. U32 maxBuffers )
  35. : Parent( name, provider, false, maxBuffers ),
  36. mXAudio( xaudio ),
  37. mMasterVoice( NULL )
  38. {
  39. dMemset( &mListener, 0, sizeof( mListener ) );
  40. // If mMaxBuffers is negative then use some default value.
  41. // to decide on a good maximum value... or set 8.
  42. //
  43. // TODO: We should change the terminology to voices!
  44. if ( mMaxBuffers < 0 )
  45. mMaxBuffers = 64;
  46. // Create the mastering voice.
  47. HRESULT hr = mXAudio->CreateMasteringVoice( &mMasterVoice,
  48. XAUDIO2_DEFAULT_CHANNELS,
  49. XAUDIO2_DEFAULT_SAMPLERATE,
  50. 0,
  51. deviceIndex,
  52. NULL );
  53. if ( FAILED( hr ) || !mMasterVoice )
  54. {
  55. Con::errorf( "SFXXAudioDevice - Failed creating master voice!" );
  56. return;
  57. }
  58. mMasterVoice->GetVoiceDetails( &mMasterVoiceDetails );
  59. // Init X3DAudio.
  60. X3DAudioInitialize( speakerChannelMask,
  61. X3DAUDIO_SPEED_OF_SOUND,
  62. mX3DAudio );
  63. // Start the update thread.
  64. if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
  65. {
  66. SFXInternal::gUpdateThread = new AsyncUpdateThread
  67. ( "XAudio Update Thread", SFXInternal::gBufferUpdateList );
  68. SFXInternal::gUpdateThread->start();
  69. }
  70. }
  71. SFXXAudioDevice::~SFXXAudioDevice()
  72. {
  73. _releaseAllResources();
  74. if ( mMasterVoice )
  75. {
  76. mMasterVoice->DestroyVoice();
  77. mMasterVoice = NULL;
  78. }
  79. // Kill the engine.
  80. SAFE_RELEASE( mXAudio );
  81. }
  82. SFXBuffer* SFXXAudioDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description )
  83. {
  84. SFXXAudioBuffer* buffer = SFXXAudioBuffer::create( stream, description );
  85. if ( !buffer )
  86. return NULL;
  87. _addBuffer( buffer );
  88. return buffer;
  89. }
  90. SFXVoice* SFXXAudioDevice::createVoice( bool is3D, SFXBuffer *buffer )
  91. {
  92. // Don't bother going any further if we've
  93. // exceeded the maximum voices.
  94. if ( mVoices.size() >= mMaxBuffers )
  95. return NULL;
  96. AssertFatal( buffer, "SFXXAudioDevice::createVoice() - Got null buffer!" );
  97. SFXXAudioBuffer* xaBuffer = dynamic_cast<SFXXAudioBuffer*>( buffer );
  98. AssertFatal( xaBuffer, "SFXXAudioDevice::createVoice() - Got bad buffer!" );
  99. SFXXAudioVoice* voice = SFXXAudioVoice::create( mXAudio, is3D, xaBuffer );
  100. if ( !voice )
  101. return NULL;
  102. voice->mXAudioDevice = this;
  103. _addVoice( voice );
  104. return voice;
  105. }
  106. void SFXXAudioDevice::_setOutputMatrix( SFXXAudioVoice *voice )
  107. {
  108. X3DAUDIO_DSP_SETTINGS dspSettings = {0};
  109. FLOAT32 matrix[12] = { 0 };
  110. dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels;
  111. dspSettings.pMatrixCoefficients = matrix;
  112. const X3DAUDIO_EMITTER &emitter = voice->getEmitter();
  113. dspSettings.SrcChannelCount = emitter.ChannelCount;
  114. // Calculate the output volumes and doppler.
  115. X3DAudioCalculate( mX3DAudio,
  116. &mListener,
  117. &emitter,
  118. X3DAUDIO_CALCULATE_MATRIX |
  119. X3DAUDIO_CALCULATE_DOPPLER,
  120. &dspSettings );
  121. voice->mXAudioVoice->SetOutputMatrix( mMasterVoice,
  122. dspSettings.SrcChannelCount,
  123. dspSettings.DstChannelCount,
  124. dspSettings.pMatrixCoefficients,
  125. 4321 );
  126. voice->mXAudioVoice->SetFrequencyRatio( dspSettings.DopplerFactor * voice->mPitch,
  127. 4321 );
  128. // Commit the changes.
  129. mXAudio->CommitChanges( 4321 );
  130. }
  131. void SFXXAudioDevice::update()
  132. {
  133. PROFILE_SCOPE( SFXXAudioDevice_Update );
  134. Parent::update();
  135. X3DAUDIO_DSP_SETTINGS dspSettings = {0};
  136. FLOAT32 matrix[12] = { 0 };
  137. dspSettings.DstChannelCount = mMasterVoiceDetails.InputChannels;
  138. dspSettings.pMatrixCoefficients = matrix;
  139. dspSettings.DopplerFactor = mDopplerFactor;
  140. // Now update the volume and frequency of
  141. // all the active 3D voices.
  142. VoiceVector::iterator voice = mVoices.begin();
  143. for ( ; voice != mVoices.end(); voice++ )
  144. {
  145. SFXXAudioVoice* xaVoice = ( SFXXAudioVoice* ) *voice;
  146. // Skip 2D or stopped voices.
  147. if ( !xaVoice->is3D() ||
  148. xaVoice->getStatus() != SFXStatusPlaying )
  149. continue;
  150. const X3DAUDIO_EMITTER &emitter = xaVoice->getEmitter();
  151. dspSettings.SrcChannelCount = emitter.ChannelCount;
  152. // Calculate the output volumes and doppler.
  153. X3DAudioCalculate( mX3DAudio,
  154. &mListener,
  155. &emitter,
  156. X3DAUDIO_CALCULATE_MATRIX |
  157. X3DAUDIO_CALCULATE_DOPPLER,
  158. &dspSettings );
  159. xaVoice->mXAudioVoice->SetOutputMatrix( mMasterVoice,
  160. dspSettings.SrcChannelCount,
  161. dspSettings.DstChannelCount,
  162. dspSettings.pMatrixCoefficients,
  163. 4321 ) ;
  164. xaVoice->mXAudioVoice->SetFrequencyRatio( dspSettings.DopplerFactor * xaVoice->mPitch,
  165. 4321 );
  166. }
  167. // Commit the changes.
  168. mXAudio->CommitChanges( 4321 );
  169. }
  170. void SFXXAudioDevice::setListener( U32 index, const SFXListenerProperties& listener )
  171. {
  172. // Get the transform from the listener.
  173. const MatrixF& transform = listener.getTransform();
  174. transform.getColumn( 3, (Point3F*)&mListener.Position );
  175. transform.getColumn( 1, (Point3F*)&mListener.OrientFront );
  176. transform.getColumn( 2, (Point3F*)&mListener.OrientTop );
  177. // And the velocity...
  178. const VectorF& velocity = listener.getVelocity();
  179. mListener.Velocity.x = velocity.x;
  180. mListener.Velocity.y = velocity.y;
  181. mListener.Velocity.z = velocity.z;
  182. // XAudio and Torque use opposite handedness, so
  183. // flip the z coord to account for that.
  184. mListener.Position.z *= -1.0f;
  185. mListener.OrientFront.z *= -1.0f;
  186. mListener.OrientTop.z *= -1.0f;
  187. mListener.Velocity.z *= -1.0f;
  188. }
  189. void SFXXAudioDevice::setDistanceModel( SFXDistanceModel model )
  190. {
  191. mDistanceModel = model;
  192. }
  193. void SFXXAudioDevice::setDopplerFactor( F32 factor )
  194. {
  195. mDopplerFactor = factor;
  196. }
  197. void SFXXAudioDevice::setRolloffFactor( F32 factor )
  198. {
  199. mRolloffFactor = factor;
  200. }