sfxDevice.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  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/sfxDevice.h"
  23. #include "sfx/sfxBuffer.h"
  24. #include "sfx/sfxVoice.h"
  25. #include "sfx/sfxInternal.h"
  26. #include "core/tAlgorithm.h"
  27. #include "console/console.h"
  28. #include "console/consoleTypes.h"
  29. //-----------------------------------------------------------------------------
  30. SFXDevice::SFXDevice( const String& name, SFXProvider* provider, bool useHardware, S32 maxBuffers )
  31. : mName( name ),
  32. mProvider( provider ),
  33. mUseHardware( useHardware ),
  34. mMaxBuffers( maxBuffers ),
  35. mCaps( 0 ),
  36. mStatNumBuffers( 0 ),
  37. mStatNumVoices( 0 ),
  38. mStatNumBufferBytes( 0 )
  39. {
  40. AssertFatal( provider, "We must have a provider pointer on device creation!" );
  41. VECTOR_SET_ASSOCIATION( mBuffers );
  42. VECTOR_SET_ASSOCIATION( mVoices );
  43. SFXBuffer::smBufferDestroyedSignal.notify( this, &SFXDevice::_removeBuffer );
  44. SFXVoice::smVoiceDestroyedSignal.notify( this, &SFXDevice::_removeVoice );
  45. Con::addVariable( "SFX::Device::numBuffers", TypeS32, &mStatNumBuffers );
  46. Con::addVariable( "SFX::Device::numVoices", TypeS32, &mStatNumVoices );
  47. Con::addVariable( "SFX::Device::numBufferBytes", TypeS32, &mStatNumBufferBytes );
  48. }
  49. //-----------------------------------------------------------------------------
  50. SFXDevice::~SFXDevice()
  51. {
  52. Con::removeVariable( "SFX::Device::numBuffers" );
  53. Con::removeVariable( "SFX::Device::numVoices" );
  54. Con::removeVariable( "SFX::Device::numBufferBytes" );
  55. _releaseAllResources();
  56. }
  57. //-----------------------------------------------------------------------------
  58. void SFXDevice::_releaseAllResources()
  59. {
  60. using namespace SFXInternal;
  61. // Kill the update thread, if there is one.
  62. // Do this first so that further buffer processing
  63. // can be done synchronously by us.
  64. ThreadSafeRef< SFXUpdateThread > sfxThread = UPDATE_THREAD();
  65. if( sfxThread != NULL )
  66. {
  67. gUpdateThread = NULL; // Kill the global reference.
  68. sfxThread->stop();
  69. sfxThread->triggerUpdate();
  70. sfxThread->join();
  71. sfxThread = NULL;
  72. }
  73. // Clean up voices. Do this before cleaning up buffers so that
  74. // resources held by voices that are tied to resources held by buffers
  75. // get released properly.
  76. SFXVoice::smVoiceDestroyedSignal.remove( this, &SFXDevice::_removeVoice );
  77. for( VoiceIterator voice = mVoices.begin();
  78. voice != mVoices.end(); voice++ )
  79. ( *voice )->destroySelf();
  80. mVoices.clear();
  81. // Clean up buffers.
  82. SFXBuffer::smBufferDestroyedSignal.remove( this, &SFXDevice::_removeBuffer );
  83. for( BufferIterator buffer = mBuffers.begin();
  84. buffer != mBuffers.end(); ++ buffer )
  85. if( !( *buffer )->isDead() )
  86. ( *buffer )->destroySelf();
  87. mBuffers.clear();
  88. // Flush all asynchronous requests.
  89. THREAD_POOL().flushWorkItems();
  90. // Clean out the buffer update list and kill
  91. // all buffers that surfaced on the dead list.
  92. // Now the sound buffers are really gone.
  93. UPDATE_LIST().process();
  94. PurgeDeadBuffers();
  95. // Clean out stats.
  96. mStatNumBuffers = 0;
  97. mStatNumVoices = 0;
  98. mStatNumBufferBytes = 0;
  99. }
  100. //-----------------------------------------------------------------------------
  101. void SFXDevice::update()
  102. {
  103. using namespace SFXInternal;
  104. // If we don't have an update thread, do the
  105. // updates now on the main thread.
  106. if( !UPDATE_THREAD() )
  107. UPDATE_LIST().process( MAIN_THREAD_PROCESS_TIMEOUT );
  108. // Clean out buffers that have surfaced on the dead
  109. // buffer list.
  110. PurgeDeadBuffers();
  111. }
  112. //-----------------------------------------------------------------------------
  113. void SFXDevice::_addBuffer( SFXBuffer* buffer )
  114. {
  115. AssertFatal( buffer, "SFXDevice::_addBuffer() - Got a null buffer!" );
  116. // Register the buffer.
  117. mBuffers.push_back( buffer );
  118. mStatNumBuffers ++;
  119. mStatNumBufferBytes += buffer->getMemoryUsed();
  120. // Start loading the buffer.
  121. buffer->load();
  122. }
  123. //-----------------------------------------------------------------------------
  124. void SFXDevice::_removeBuffer( SFXBuffer* buffer )
  125. {
  126. AssertFatal( buffer, "SFXDevice::_removeBuffer() - Got a null buffer!" );
  127. BufferIterator iter = T3D::find( mBuffers.begin(), mBuffers.end(), buffer );
  128. if( iter != mBuffers.end() )
  129. {
  130. SFXBuffer* curBuf = *iter;
  131. mStatNumBufferBytes -= curBuf->getMemoryUsed();
  132. mStatNumBuffers --;
  133. mBuffers.erase( iter );
  134. }
  135. }
  136. //-----------------------------------------------------------------------------
  137. void SFXDevice::_addVoice( SFXVoice* voice )
  138. {
  139. AssertFatal( voice, "SFXDevice::_addVoice() - Got a null voice!" );
  140. using namespace SFXInternal;
  141. // Bind the voice to its buffer. This is deferred up to here in order
  142. // to only bind voices that have been successfully constructed.
  143. voice->_attachToBuffer();
  144. // Register the voice.
  145. mVoices.push_back( voice );
  146. mStatNumVoices ++;
  147. }
  148. //-----------------------------------------------------------------------------
  149. void SFXDevice::_removeVoice( SFXVoice* voice )
  150. {
  151. AssertFatal( voice, "SFXDevice::_removeVoice() - Got null voice!" );
  152. VoiceIterator iter = T3D::find( mVoices.begin(), mVoices.end(), voice );
  153. if( iter != mVoices.end() )
  154. {
  155. mStatNumVoices --;
  156. mVoices.erase( iter );
  157. }
  158. }