sfxALDevice.cpp 6.9 KB

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