2
0

sfxALDevice.cpp 6.8 KB

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