sfxALDevice.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  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/openal/sfxALDevice.h"
  23. #include "sfx/openal/sfxALBuffer.h"
  24. #include "platform/async/asyncUpdate.h"
  25. //-----------------------------------------------------------------------------
  26. SFXALDevice::SFXALDevice( SFXProvider *provider,
  27. const OPENALFNTABLE &openal,
  28. String name,
  29. bool useHardware,
  30. S32 maxBuffers )
  31. : Parent( name, provider, useHardware, maxBuffers ),
  32. mOpenAL( openal ),
  33. mDevice( NULL ),
  34. mContext( NULL )
  35. {
  36. mMaxBuffers = getMax( maxBuffers, 8 );
  37. // TODO: The OpenAL device doesn't set the primary buffer
  38. // $pref::SFX::frequency or $pref::SFX::bitrate!
  39. mDevice = mOpenAL.alcOpenDevice( name );
  40. mOpenAL.alcGetError( mDevice );
  41. if( mDevice )
  42. {
  43. mContext = mOpenAL.alcCreateContext( mDevice, NULL );
  44. if( mContext )
  45. mOpenAL.alcMakeContextCurrent( mContext );
  46. U32 err = mOpenAL.alcGetError( mDevice );
  47. if( err != ALC_NO_ERROR )
  48. Con::errorf( "SFXALDevice - Initialization Error: %s", mOpenAL.alcGetString( mDevice, err ) );
  49. }
  50. AssertFatal( mDevice != NULL && mContext != NULL, "Failed to create OpenAL device and/or context!" );
  51. // Start the update thread.
  52. if( !Con::getBoolVariable( "$_forceAllMainThread" ) )
  53. {
  54. SFXInternal::gUpdateThread = new AsyncPeriodicUpdateThread
  55. ( "OpenAL Update Thread", SFXInternal::gBufferUpdateList,
  56. Con::getIntVariable( "$pref::SFX::updateInterval", SFXInternal::DEFAULT_UPDATE_INTERVAL ) );
  57. SFXInternal::gUpdateThread->start();
  58. }
  59. }
  60. //-----------------------------------------------------------------------------
  61. SFXALDevice::~SFXALDevice()
  62. {
  63. _releaseAllResources();
  64. mOpenAL.alcMakeContextCurrent( NULL );
  65. mOpenAL.alcDestroyContext( mContext );
  66. mOpenAL.alcCloseDevice( mDevice );
  67. }
  68. //-----------------------------------------------------------------------------
  69. SFXBuffer* SFXALDevice::createBuffer( const ThreadSafeRef< SFXStream >& stream, SFXDescription* description )
  70. {
  71. AssertFatal( stream, "SFXALDevice::createBuffer() - Got null stream!" );
  72. AssertFatal( description, "SFXALDevice::createBuffer() - Got null description!" );
  73. SFXALBuffer* buffer = SFXALBuffer::create( mOpenAL,
  74. stream,
  75. description,
  76. mUseHardware );
  77. if ( !buffer )
  78. return NULL;
  79. _addBuffer( buffer );
  80. return buffer;
  81. }
  82. //-----------------------------------------------------------------------------
  83. SFXVoice* SFXALDevice::createVoice( bool is3D, SFXBuffer *buffer )
  84. {
  85. // Don't bother going any further if we've
  86. // exceeded the maximum voices.
  87. if ( mVoices.size() >= mMaxBuffers )
  88. return NULL;
  89. AssertFatal( buffer, "SFXALDevice::createVoice() - Got null buffer!" );
  90. SFXALBuffer* alBuffer = dynamic_cast<SFXALBuffer*>( buffer );
  91. AssertFatal( alBuffer, "SFXALDevice::createVoice() - Got bad buffer!" );
  92. SFXALVoice* voice = SFXALVoice::create( this, alBuffer );
  93. if ( !voice )
  94. return NULL;
  95. _addVoice( voice );
  96. return voice;
  97. }
  98. //-----------------------------------------------------------------------------
  99. void SFXALDevice::setListener( U32 index, const SFXListenerProperties& listener )
  100. {
  101. if( index != 0 )
  102. return;
  103. // Torque and OpenAL are both right handed
  104. // systems, so no coordinate flipping is needed.
  105. const MatrixF &transform = listener.getTransform();
  106. Point3F pos, tupple[2];
  107. transform.getColumn( 3, &pos );
  108. transform.getColumn( 1, &tupple[0] );
  109. transform.getColumn( 2, &tupple[1] );
  110. const VectorF &velocity = listener.getVelocity();
  111. mOpenAL.alListenerfv( AL_POSITION, pos );
  112. mOpenAL.alListenerfv( AL_VELOCITY, velocity );
  113. mOpenAL.alListenerfv( AL_ORIENTATION, (const F32 *)&tupple[0] );
  114. }
  115. //-----------------------------------------------------------------------------
  116. void SFXALDevice::setDistanceModel( SFXDistanceModel model )
  117. {
  118. switch( model )
  119. {
  120. case SFXDistanceModelLinear:
  121. mOpenAL.alDistanceModel( AL_LINEAR_DISTANCE_CLAMPED );
  122. if( mRolloffFactor != 1.0f )
  123. _setRolloffFactor( 1.0f ); // No rolloff on linear.
  124. break;
  125. case SFXDistanceModelLogarithmic:
  126. mOpenAL.alDistanceModel( AL_INVERSE_DISTANCE_CLAMPED );
  127. if( mUserRolloffFactor != mRolloffFactor )
  128. _setRolloffFactor( mUserRolloffFactor );
  129. break;
  130. default:
  131. AssertWarn( false, "SFXALDevice::setDistanceModel - distance model not implemented" );
  132. }
  133. mDistanceModel = model;
  134. }
  135. //-----------------------------------------------------------------------------
  136. void SFXALDevice::setDopplerFactor( F32 factor )
  137. {
  138. mOpenAL.alDopplerFactor( factor );
  139. }
  140. //-----------------------------------------------------------------------------
  141. void SFXALDevice::_setRolloffFactor( F32 factor )
  142. {
  143. mRolloffFactor = factor;
  144. for( U32 i = 0, num = mVoices.size(); i < num; ++ i )
  145. mOpenAL.alSourcef( ( ( SFXALVoice* ) mVoices[ i ] )->mSourceName, AL_ROLLOFF_FACTOR, factor );
  146. }
  147. //-----------------------------------------------------------------------------
  148. void SFXALDevice::setRolloffFactor( F32 factor )
  149. {
  150. if( mDistanceModel == SFXDistanceModelLinear && factor != 1.0f )
  151. Con::errorf( "SFXALDevice::setRolloffFactor - rolloff factor <> 1.0f ignored in linear distance model" );
  152. else
  153. _setRolloffFactor( factor );
  154. mUserRolloffFactor = factor;
  155. }