Torque3D/Engine/source/sfx/sfxDevice.cpp

211 lines
6.4 KiB
C++
Raw Normal View History

2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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 ),
2015-07-03 13:52:38 +00:00
mCaps( 0 ),
2012-09-19 15:15:01 +00:00
mStatNumBuffers( 0 ),
mStatNumVoices( 0 ),
2015-07-03 13:52:38 +00:00
mStatNumBufferBytes( 0 )
2012-09-19 15:15:01 +00:00
{
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 );
2012-09-19 15:15:01 +00:00
if( iter != mBuffers.end() )
{
2018-03-14 02:25:02 +00:00
SFXBuffer* curBuf = *iter;
2012-09-19 15:15:01 +00:00
2018-03-14 02:25:02 +00:00
mStatNumBufferBytes -= curBuf->getMemoryUsed();
2012-09-19 15:15:01 +00:00
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 );
2012-09-19 15:15:01 +00:00
if( iter != mVoices.end() )
{
mStatNumVoices --;
mVoices.erase( iter );
}
}