sfxALDevice.cpp 6.8 KB

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