JD2022-TU1/main/extern/Soundwich/Solution/Engine/Src/EngineImpl.cpp

1068 lines
23 KiB
C++

#include "EngineImpl.h"
#include "Synth.h"
#include "Components/External/Events/EventIn.h"
#include "Components/External/Events/EventInWithId.h"
#include "Components/External/Events/EventOut.h"
#include "Components/External/Controls/ControlIn.h"
#include "Components/External/Controls/ControlOut.h"
#include "Components/External/Switches/SwitchIn.h"
#include "Components/External/Switches/SwitchOut.h"
#include "Components/JustDance/PlayMenuMusic.h"
#include "Components/JustDance/StopMenuMusic.h"
#include "Components/JustDance/JDSound.h"
#include "Components/JustDance/JDSoundSyncOnTransition.h"
#include "Components/JustDance/JDRemoteSound.h"
#include "Components/JustDance/PlayEventBusMusic.h"
#include "Components/JustDance/StopEventBusMusic.h"
#include "Components/JustDance/StopAllEventBusMixes.h"
#include "Components/JustDance/PlayMusicMultiTrack.h"
#include "Commands.h"
#include "Inc/Defs.h"
#include "Util/Logger.h"
#include "Util/Directory.h"
#include "Util/StringHash.h"
Soundwich::IClientSystem* Soundwich::Engine::Impl::_clientSystem = nullptr;
Soundwich::Engine::Impl::Impl( )
: _audioDevice( nullptr )
#if defined( USE_PROCESSING_THREAD )
, _processing( false )
#endif
#if defined( USE_DEFERRED_COMMANDS )
, _sendCommands( 256 )
, _returnCommands( 64 )
#endif
, _logWriter( _logStream )
{
_synthFactory = new SynthFactory( this );
_logStream.Open( Util::Directory::GetCurrent( ) + "log.txt" );
LOG_INFO( GetLog( ), "Initialize Soundwich engine" );
}
Soundwich::Engine::Impl::~Impl( )
{
#if defined( USE_PROCESSING_THREAD )
// signal process thread to finish
_processing = false;
// wake it up if it is asleep waiting for a tick
_processThreadTickEvent.Signal( );
// wait for it to finish
_processThread.Join( );
#endif
#if defined( USE_DEFERRED_COMMANDS )
// discard pending return commands
_returnCommands.Clear( );
#endif
// release the audio device (ensures rendering has stopped)
DefaultAudioDevice::Release( _audioDevice );
// destroy synths
for( SynthDictionary::Iterator it = _synths.Begin( ); it != _synths.End( ); )
{
Synth* synth = it->second;
_synths.Erase( it++ );
delete synth;
}
delete _synthFactory;
}
SoundResult Soundwich::Engine::Impl::Run( )
{
#if defined( USE_NATIVE_AUDIO )
// create the audio device
SoundResult result = DefaultAudioDevice::Create( &_audioDevice, this ) ? Ok : Error;
#else
SoundResult result = Ok;
#endif
#if defined( USE_PROCESSING_THREAD )
if( result == Ok )
{
// start the processing thread
_processThread.Start( Engine::Impl::StartInternalProcessing, this );
}
#endif
return result;
}
void Soundwich::Engine::Impl::SetClientSystem( Soundwich::IClientSystem* clientSystem )
{
_clientSystem = clientSystem;
}
Soundwich::IClientSystem* Soundwich::Engine::Impl::GetClientSystem( )
{
AssertMessage( _clientSystem, "Client system is null" );
return _clientSystem;
}
SoundResult Soundwich::Engine::Impl::SetDataPath( const Util::String& dataPath )
{
_dataPath = dataPath;
return Ok;
}
SoundResult Soundwich::Engine::Impl::CreateSynthFromXmlFile( const Util::String& name, Soundwich::Synth** synth, const Util::String& fileName )
{
SoundResult result = Ok;
*synth = new Synth( this, name );
result = (*synth)->LoadFromXmlFile( ( _dataPath + "\\" + fileName + ".xws" ).Chars( ) );
if( result == Ok )
{
#if defined( USE_PROCESSING_THREAD )
Util::AutoLock lock ( _synthsLock );
#endif
_synths.Add( name, *synth );
}
else
{
delete *synth;
*synth = nullptr;
}
return result;
}
SoundResult Soundwich::Engine::Impl::CreateSynthFromMemory( const Util::String& name, Soundwich::Synth** synth, void* data, uint32 size )
{
SoundResult result = Ok;
*synth = new Synth( this, name );
result = (*synth)->LoadFromMemory( data, size );
if( result == Ok )
{
#if defined( USE_PROCESSING_THREAD )
Util::AutoLock lock ( _synthsLock );
#endif
_synths.Add( name, *synth );
}
else
{
delete *synth;
*synth = nullptr;
}
return result;
}
SoundResult Soundwich::Engine::Impl::CreateSynthFromXmlMemory( const Util::String& name, Soundwich::Synth** synth, const Util::String& xml )
{
SoundResult result = Ok;
*synth = new Synth( this, name );
result = (*synth)->LoadFromXmlMemory( xml );
if( result == Ok )
{
#if defined( USE_PROCESSING_THREAD )
Util::AutoLock lock ( _synthsLock );
#endif
_synths.Add( name, *synth );
}
else
{
delete *synth;
*synth = nullptr;
}
return result;
}
SoundResult Soundwich::Engine::Impl::SaveSynthToFile( Soundwich::Synth* synth, const Util::String& fileName )
{
AssertMessage( synth, "Synth is null" );
return synth->SaveToFile( ( _dataPath + "\\" + fileName + ".bws" ).Chars( ) );
}
SoundResult Soundwich::Engine::Impl::SaveSynthToXmlFile( Soundwich::Synth* synth, const Util::String& fileName )
{
AssertMessage( synth, "Synth is null" );
return synth->SaveToXmlFile( ( _dataPath + "\\" + fileName + ".xws" ).Chars( ) );
}
SoundResult Soundwich::Engine::Impl::DestroySynth( Synth* synth )
{
SoundResult result = Ok;
if( !_synths.ContainsValue( synth ) )
{
result = UnknownSynth;
}
else
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalDestroySynthCommand( synth ) );
#else
InternalDestroySynth( synth );
#endif
}
return result;
}
SoundResult Soundwich::Engine::Impl::ActivateSynth( Synth* synth )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalActivateSynthCommand( synth ) );
#else
InternalActivateSynth( synth );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::DeactivateSynth( Synth* synth )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalDeactivateSynthCommand( synth ) );
#else
InternalDeactivateSynth( synth );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::GetSynth( const Util::String& name, Synth** synth )
{
SoundResult result = Ok;
if( !_synths.TryGetValue( name, *synth ) )
{
result = UnknownSynth;
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetEventInComponent( Synth* synth, const Util::String& componentName, EventIn** eventIn )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != EventIn::GetType( ) )
{
*eventIn = nullptr;
result = ComponentNotEventIn;
}
else
{
*eventIn = (EventIn*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetEventInWithIdComponent( Synth* synth, const Util::String& componentName, EventInWithId** eventIn )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != EventInWithId::GetType( ) )
{
*eventIn = nullptr;
result = ComponentNotEventIn;
}
else
{
*eventIn = (EventInWithId*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetControlInComponent( Synth* synth, const Util::String& componentName, ControlIn** controlIn )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != ControlIn::GetType( ) )
{
*controlIn = nullptr;
result = ComponentNotControlIn;
}
else
{
*controlIn = (ControlIn*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetSwitchInComponent( Synth* synth, const Util::String& componentName, SwitchIn** switchIn )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != SwitchIn::GetType( ) )
{
*switchIn = nullptr;
result = Error;
}
else
{
*switchIn = (SwitchIn*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetEventOutComponent( Synth* synth, const Util::String& componentName, EventOut** eventOut )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != EventOut::GetType( ) )
{
*eventOut = nullptr;
result = Error;
}
else
{
*eventOut = (EventOut*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetControlOutComponent( Synth* synth, const Util::String& componentName, ControlOut** controlOut )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != ControlOut::GetType( ) )
{
*controlOut = nullptr;
result = Error;
}
else
{
*controlOut = (ControlOut*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::GetSwitchOutComponent( Synth* synth, const Util::String& componentName, SwitchOut** switchOut )
{
SoundResult result = Ok;
Component* component;
if( !synth->GetComponents( ).TryGetValue( componentName, component ) )
{
result = UnknownSynth;
}
else
{
if( component->GetDerivedType( ) != SwitchOut::GetType( ) )
{
*switchOut = nullptr;
result = Error;
}
else
{
*switchOut = (SwitchOut*)component;
}
}
return result;
}
SoundResult Soundwich::Engine::Impl::Tick( )
{
#if defined( USE_DEFERRED_COMMANDS )
// process all external commands returned from the engine
while( _returnCommands.Receive( ) );
_returnCommands.Clean( );
#endif
#if defined( USE_PROCESSING_THREAD )
// signal the engine to process all internal commands if threaded
_processThreadTickEvent.Signal( );
#else
#if defined( USE_DEFERRED_COMMANDS )
// process all commands and tick the engine
while( _sendCommands.Receive( ) );
_sendCommands.Clean( );
#endif
InternalTick( );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetEventIn( EventIn* eventIn )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalSetEventInCommand( eventIn ) );
#else
InternalSetEventIn( eventIn );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetEventInWithId( EventInWithId* eventIn, int32 val )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalSetEventInWithIdCommand( eventIn, val ) );
#else
InternalSetEventInWithId( eventIn, val );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetControlIn( ControlIn* controlIn, flt32 val )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalSetControlInCommand( controlIn, val ) );
#else
InternalSetControlIn( controlIn, val );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetSwitchIn( SwitchIn* switchIn, int32 val )
{
#if defined( USE_DEFERRED_COMMANDS )
_sendCommands.Send( new InternalSetSwitchInCommand( switchIn, val ) );
#else
InternalSetSwitchIn( switchIn, val );
#endif
return Ok;
}
SoundResult Soundwich::Engine::Impl::GetComponent( Synth* synth, const Util::String& componentName, Component** component )
{
return synth->GetComponents( ).TryGetValue( componentName, *component ) ? Ok : Error;
}
SoundResult Soundwich::Engine::Impl::SwitchTracking( Soundwich::Synth* synth, bool enable, const char* exportFilePath)
{
synth->SwitchTracking(enable, exportFilePath);
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetSynthDebugLogging( Synth* synth, bool enable )
{
synth->SetDebugLogging( enable );
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetComponentDebugLogging( Component* component, bool enable )
{
component->SetDebugLogging( enable );
return Ok;
}
SoundResult Soundwich::Engine::Impl::SetConnectionDebugLogging( Connection* connection, bool enable )
{
connection->SetDebugLogging( enable );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterEventOutCallback( IEventOutCallback* cb, EventOut* eventOut )
{
eventOut->RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterControlOutCallback( IControlOutCallback* cb, ControlOut* controlOut )
{
controlOut->RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterSwitchOutCallback( ISwitchOutCallback* cb, SwitchOut* switchOut )
{
switchOut->RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDancePlayMenuMusicCallback( IJustDancePlayMenuMusicCallback* cb )
{
PlayMenuMusic::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceStopMenuMusicCallback( IJustDanceStopMenuMusicCallback* cb )
{
StopMenuMusic::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceSoundEffectCallback( IJustDanceSoundEffectCallback* cb )
{
JDSound::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceSoundEffectOnTrackTransitionCallback( IJustDanceSoundEffectOnTrackTransitionCallback* cb )
{
JDSoundSyncOnTransition::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceRemoteSoundEffectCallback( IJustDanceRemoteSoundEffectCallback* cb )
{
JDRemoteSound::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDancePlayEventBusMusicCallback( IJustDancePlayEventBusMusicCallback* cb )
{
PlayEventBusMusic::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceStopEventBusMusicCallback( IJustDanceStopEventBusMusicCallback* cb )
{
StopEventBusMusic::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDanceStopAllEventBusMixesCallback(IJustDanceStopAllEventBusMixesCallback* cb)
{
StopAllEventBusMixes::RegisterCallback(cb);
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterJustDancePlayMusicMultiTrackCallback( IJustDancePlayMusicMultiTrackCallback* cb )
{
PlayMusicMultiTrack::RegisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::RegisterSoundwichTrackingCallback(ISoundwichTracking* cb)
{
for (SynthDictionary::Iterator item = _synths.begin(); item != _synths.end(); ++item)
{
Synth* synth = item->second;
if (synth != nullptr)
{
synth->RegisterTracker(cb);
}
}
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterEventOutCallback( IEventOutCallback* cb, EventOut* eventOut )
{
eventOut->UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterControlOutCallback( IControlOutCallback* cb, ControlOut* controlOut )
{
controlOut->UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterSwitchOutCallback( ISwitchOutCallback* cb, SwitchOut* switchOut )
{
switchOut->UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDancePlayMenuMusicCallback( IJustDancePlayMenuMusicCallback* cb )
{
PlayMenuMusic::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceStopMenuMusicCallback( IJustDanceStopMenuMusicCallback* cb )
{
StopMenuMusic::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceSoundEffectCallback( IJustDanceSoundEffectCallback* cb )
{
JDSound::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceSoundEffectOnTrackTransitionCallback( IJustDanceSoundEffectOnTrackTransitionCallback* cb )
{
JDSoundSyncOnTransition::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceRemoteSoundEffectCallback( IJustDanceRemoteSoundEffectCallback* cb )
{
JDRemoteSound::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDancePlayEventBusMusicCallback( IJustDancePlayEventBusMusicCallback* cb )
{
PlayEventBusMusic::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceStopEventBusMusicCallback( IJustDanceStopEventBusMusicCallback* cb )
{
StopEventBusMusic::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDanceStopAllEventBusMixesCallback(IJustDanceStopAllEventBusMixesCallback* cb)
{
StopAllEventBusMixes::UnregisterCallback(cb);
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterJustDancePlayMusicMultiTrackCallback( IJustDancePlayMusicMultiTrackCallback* cb )
{
PlayMusicMultiTrack::UnregisterCallback( cb );
return Ok;
}
SoundResult Soundwich::Engine::Impl::UnregisterSoundwichTrackingCallback(ISoundwichTracking* cb)
{
for (SynthDictionary::Iterator item = _synths.begin(); item != _synths.end(); ++item)
{
Synth* synth = item->second;
if (synth != nullptr)
{
synth->UnregisterTracker(cb);
}
}
return Ok;
}
void Soundwich::Engine::Impl::SetEventOut( EventOut* eventOut )
{
#if defined( USE_DEFERRED_COMMANDS )
_returnCommands.Send( new ExternalSetEventOutCommand( eventOut ) );
#else
ExternalSetEventOut( eventOut );
#endif
}
void Soundwich::Engine::Impl::SetControlOut( ControlOut* controlOut, flt32 val )
{
#if defined( USE_DEFERRED_COMMANDS )
_returnCommands.Send( new ExternalSetControlOutCommand( controlOut, val ) );
#else
ExternalSetControlOut( controlOut, val );
#endif
}
void Soundwich::Engine::Impl::SetSwitchOut( SwitchOut* switchOut, int32 val )
{
#if defined( USE_DEFERRED_COMMANDS )
_returnCommands.Send( new ExternalSetSwitchOutCommand( switchOut, val ) );
#else
ExternalSetSwitchOut( switchOut, val );
#endif
}
void Soundwich::Engine::Impl::StartInternalProcessing( void* data )
{
Engine::Impl* engine = (Engine::Impl*)data;
// run the process loop
engine->InternalProcessingLoop( );
}
void Soundwich::Engine::Impl::InternalProcessingLoop( )
{
#if defined( USE_PROCESSING_THREAD )
_processing = true;
while( _processing )
{
// wait on main thread Tick( )
_processThreadTickEvent.Wait( );
// process commands from main thread
while( _sendCommands.Receive( ) );
_sendCommands.Clean( );
InternalTick( );
}
#endif
}
void Soundwich::Engine::Impl::InternalShutdown( )
{
for( SynthArray::Iterator it = _ticking.Begin( ); it != _ticking.End( ); ++it )
{
Synth* synth = *it;
_ticking.Remove( synth );
#if defined( USE_NATIVE_AUDIO )
if( _rendering.Contains( synth ) )
{
_renderLock.Lock( );
_rendering.Remove( synth );
_renderLock.Unlock( );
}
#endif
}
}
void Soundwich::Engine::Impl::InternalDestroySynth( Synth* synth )
{
// ensure we are not currently active, deactivate if so
InternalDeactivateSynth( synth );
#if defined( USE_DEFERRED_COMMANDS )
// signal the main thread to destroy the synth next Tick( )
_returnCommands.Send( new ExternalDestroySynthCommand( synth ) );
#else
ExternalDestroySynth( synth );
#endif
}
void Soundwich::Engine::Impl::InternalActivateSynth( Synth* synth )
{
if( !_ticking.Contains( synth ) )
{
_ticking.PushBack( synth );
// give it a first tick to initialize values
synth->Tick( 0.0f );
}
#if defined( USE_NATIVE_AUDIO )
if( !_rendering.Contains( synth ) )
{
_renderLock.Lock( );
_rendering.PushBack( synth );
_renderLock.Unlock( );
}
#endif
}
void Soundwich::Engine::Impl::InternalDeactivateSynth( Synth* synth )
{
if( _ticking.Contains( synth ) )
{
_ticking.Remove( synth );
}
#if defined( USE_NATIVE_AUDIO )
if( _rendering.Contains( synth ) )
{
_renderLock.Lock( );
_rendering.Remove( synth );
_renderLock.Unlock( );
}
#endif
}
void Soundwich::Engine::Impl::InternalTick( )
{
// round to nearest millisec, in seconds
flt32 interval = 0.001f * Util::Maths::Round( (flt32)_systemTimer.GetTime( true ) * 0.001f );
for ( SynthArray::Iterator item = _ticking.begin() ; item != _ticking.end() ; ++item )
{
(*item)->Tick( interval );
}
#if defined( ENABLE_STATISTICS )
Stats stats;
for ( SynthArray::Iterator item = _ticking.begin() ; item != _ticking.end() ; ++item )
{
(*item)->GetStats( stats );
}
#endif
}
void Soundwich::Engine::Impl::InternalSetEventIn( EventIn* eventIn )
{
eventIn->Set( );
}
void Soundwich::Engine::Impl::InternalSetEventInWithId( EventInWithId* eventIn, int32 val )
{
eventIn->Set( val );
}
void Soundwich::Engine::Impl::InternalSetControlIn( ControlIn* controlIn, flt32 val )
{
controlIn->SetValue( val );
}
void Soundwich::Engine::Impl::InternalSetSwitchIn( SwitchIn* switchIn, int32 val )
{
switchIn->SetValue( val );
}
void Soundwich::Engine::Impl::ExternalDestroySynth( Synth* synth )
{
_synths.Remove( synth->GetName( ) );
delete synth;
}
void Soundwich::Engine::Impl::ExternalSetEventOut( EventOut* eventOut )
{
eventOut->ExecuteCallbacks( );
}
void Soundwich::Engine::Impl::ExternalSetControlOut( ControlOut* controlOut, flt32 val )
{
controlOut->ExecuteCallbacks( val );
}
void Soundwich::Engine::Impl::ExternalSetSwitchOut( SwitchOut* switchOut, int32 val )
{
switchOut->ExecuteCallbacks( val );
}
void Soundwich::Engine::Impl::RenderAudio( )
{
#if defined( USE_NATIVE_AUDIO )
_renderLock.Lock( );
SynthArray rendering = _rendering;
_renderLock.Unlock( );
for( auto item : rendering )
{
item->Render( );
}
#endif
}
void Soundwich::Engine::Impl::GetStats( Engine::Stats& stats )
{
for ( SynthDictionary::Iterator item = _synths.begin() ; item != _synths.end() ; ++item )
{
Synth* synth = item->second;
synth->GetStats( stats );
}
}