123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "sfx/sfxDevice.h"
- #include "sfx/sfxBuffer.h"
- #include "sfx/sfxVoice.h"
- #include "sfx/sfxInternal.h"
- #include "core/tAlgorithm.h"
- #include "console/console.h"
- #include "console/consoleTypes.h"
- //-----------------------------------------------------------------------------
- SFXDevice::SFXDevice( const String& name, SFXProvider* provider, bool useHardware, S32 maxBuffers )
- : mName( name ),
- mProvider( provider ),
- mUseHardware( useHardware ),
- mMaxBuffers( maxBuffers ),
- mCaps( 0 ),
- mStatNumBuffers( 0 ),
- mStatNumVoices( 0 ),
- mStatNumBufferBytes( 0 )
- {
- AssertFatal( provider, "We must have a provider pointer on device creation!" );
- VECTOR_SET_ASSOCIATION( mBuffers );
- VECTOR_SET_ASSOCIATION( mVoices );
- SFXBuffer::smBufferDestroyedSignal.notify( this, &SFXDevice::_removeBuffer );
- SFXVoice::smVoiceDestroyedSignal.notify( this, &SFXDevice::_removeVoice );
- Con::addVariable( "SFX::Device::numBuffers", TypeS32, &mStatNumBuffers );
- Con::addVariable( "SFX::Device::numVoices", TypeS32, &mStatNumVoices );
- Con::addVariable( "SFX::Device::numBufferBytes", TypeS32, &mStatNumBufferBytes );
- }
- //-----------------------------------------------------------------------------
- SFXDevice::~SFXDevice()
- {
- Con::removeVariable( "SFX::Device::numBuffers" );
- Con::removeVariable( "SFX::Device::numVoices" );
- Con::removeVariable( "SFX::Device::numBufferBytes" );
- _releaseAllResources();
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::_releaseAllResources()
- {
- using namespace SFXInternal;
- // Kill the update thread, if there is one.
- // Do this first so that further buffer processing
- // can be done synchronously by us.
- ThreadSafeRef< SFXUpdateThread > sfxThread = UPDATE_THREAD();
- if( sfxThread != NULL )
- {
- gUpdateThread = NULL; // Kill the global reference.
- sfxThread->stop();
- sfxThread->triggerUpdate();
- sfxThread->join();
- sfxThread = NULL;
- }
- // Clean up voices. Do this before cleaning up buffers so that
- // resources held by voices that are tied to resources held by buffers
- // get released properly.
- SFXVoice::smVoiceDestroyedSignal.remove( this, &SFXDevice::_removeVoice );
- for( VoiceIterator voice = mVoices.begin();
- voice != mVoices.end(); voice++ )
- ( *voice )->destroySelf();
- mVoices.clear();
- // Clean up buffers.
- SFXBuffer::smBufferDestroyedSignal.remove( this, &SFXDevice::_removeBuffer );
- for( BufferIterator buffer = mBuffers.begin();
- buffer != mBuffers.end(); ++ buffer )
- if( !( *buffer )->isDead() )
- ( *buffer )->destroySelf();
- mBuffers.clear();
- // Flush all asynchronous requests.
- THREAD_POOL().flushWorkItems();
- // Clean out the buffer update list and kill
- // all buffers that surfaced on the dead list.
- // Now the sound buffers are really gone.
- UPDATE_LIST().process();
- PurgeDeadBuffers();
- // Clean out stats.
- mStatNumBuffers = 0;
- mStatNumVoices = 0;
- mStatNumBufferBytes = 0;
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::update()
- {
- using namespace SFXInternal;
- // If we don't have an update thread, do the
- // updates now on the main thread.
- if( !UPDATE_THREAD() )
- UPDATE_LIST().process( MAIN_THREAD_PROCESS_TIMEOUT );
-
- // Clean out buffers that have surfaced on the dead
- // buffer list.
- PurgeDeadBuffers();
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::_addBuffer( SFXBuffer* buffer )
- {
- AssertFatal( buffer, "SFXDevice::_addBuffer() - Got a null buffer!" );
-
- // Register the buffer.
-
- mBuffers.push_back( buffer );
- mStatNumBuffers ++;
- mStatNumBufferBytes += buffer->getMemoryUsed();
-
- // Start loading the buffer.
- buffer->load();
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::_removeBuffer( SFXBuffer* buffer )
- {
- AssertFatal( buffer, "SFXDevice::_removeBuffer() - Got a null buffer!" );
- BufferIterator iter = T3D::find( mBuffers.begin(), mBuffers.end(), buffer );
- if( iter != mBuffers.end() )
- {
- SFXBuffer* curBuf = *iter;
- mStatNumBufferBytes -= curBuf->getMemoryUsed();
- mStatNumBuffers --;
-
- mBuffers.erase( iter );
- }
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::_addVoice( SFXVoice* voice )
- {
- AssertFatal( voice, "SFXDevice::_addVoice() - Got a null voice!" );
- using namespace SFXInternal;
- // Bind the voice to its buffer. This is deferred up to here in order
- // to only bind voices that have been successfully constructed.
- voice->_attachToBuffer();
-
- // Register the voice.
- mVoices.push_back( voice );
- mStatNumVoices ++;
- }
- //-----------------------------------------------------------------------------
- void SFXDevice::_removeVoice( SFXVoice* voice )
- {
- AssertFatal( voice, "SFXDevice::_removeVoice() - Got null voice!" );
- VoiceIterator iter = T3D::find( mVoices.begin(), mVoices.end(), voice );
- if( iter != mVoices.end() )
- {
- mStatNumVoices --;
- mVoices.erase( iter );
- }
- }
|