Skip to content
Snippets Groups Projects
Select Git revision
  • cbf714f7200ba43b661128c8cfe024343e995c38
  • master default protected
  • gitkeep
  • dev protected
  • Issue/2449-GuidPidSlugToProjectSettings
  • Issue/2309-docs
  • Issue/2355-topLevelOrg
  • Issue/2328-noFailOnLog
  • Hotfix/2371-fixGitLabinRCV
  • Issue/2287-guestRole
  • Fix/xxxx-activateGitlab
  • Test/xxxx-enablingGitLab
  • Issue/2349-gitlabHttps
  • Issue/2259-updatePids
  • Issue/2101-gitLabResTypeUi
  • Hotfix/2202-fixNaNQuota
  • Issue/2246-quotaResoval
  • Issue/2221-projectDateCreated
  • Hotfix/2224-quotaSizeAnalytics
  • Fix/xxxx-resourceVisibility
  • Issue/2000-gitlabResourcesAPI
  • v4.4.3
  • v4.4.2
  • v4.4.1
  • v4.4.0
  • v4.3.4
  • v4.3.3
  • v4.3.2
  • v4.3.1
  • v4.3.0
  • v4.2.8
  • v4.2.7
  • v4.2.6
  • v4.2.5
  • v4.2.4
  • v4.2.3
  • v4.2.2
  • v4.2.1
  • v4.2.0
  • v4.1.1
  • v4.1.0
41 results

Project.csproj

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    VACoreImpl.cpp 142.64 KiB
    /*
     *  --------------------------------------------------------------------------------------------
     *
     *    VVV        VVV A           Virtual Acoustics (VA) | http://www.virtualacoustics.org
     *     VVV      VVV AAA          Licensed under the Apache License, Version 2.0
     *      VVV    VVV   AAA
     *       VVV  VVV     AAA        Copyright 2015-2018
     *        VVVVVV       AAA       Institute of Technical Acoustics (ITA)
     *         VVVV         AAA      RWTH Aachen University
     *
     *  --------------------------------------------------------------------------------------------
     */
    
    #include "VACoreImpl.h"
    
    // VA base
    #include <VA.h>
    
    // VA includes
    #include "Audiosignals/VAAudioSignalSourceManager.h"
    #include "Audiosignals/VAAudiofileSignalSource.h"
    #include "Audiosignals/VAAudiofileSignalSource.h"
    #include "Audiosignals/VAEngineSignalSource.h"
    #include "Audiosignals/VAMachineSignalSource.h"
    #include "Audiosignals/VASequencerSignalSource.h"
    #include "directivities/VADirectivityManager.h"
    #include "Rendering/VAAudioRenderer.h"
    #include "Rendering/VAAudioRendererRegistry.h"
    #include "Reproduction/VAAudioReproduction.h"
    #include "Reproduction/VAAudioReproductionRegistry.h"
    #include "Scene/VAScene.h"
    #include "Scene/VASoundSourceDesc.h"
    #include "Scene/VAListenerDesc.h"
    #include "Utils/VADebug.h"
    #include "Utils/VAUtils.h"
    #include "VAAudiostreamTracker.h"
    #include "VALog.h"
    #include "VACoreEventManager.h"
    #include "VACoreFactory.h"
    #include "VACoreThread.h"
    #include "VASourceListenerMetrics.h"
    
    #include "Drivers/Audio/VAAudioDriverBackend.h"
    #include "Drivers/Audio/VAAudioDriverConfig.h"
    
    #ifdef VACORE_WITH_AUDIO_BACKEND_ASIO
    #include "Drivers/Audio/VAASIOBackend.h"
    #endif
    #ifdef VACORE_WITH_AUDIO_BACKEND_PORTAUDIO
    #include "Drivers/Audio/VAPortaudioBackend.h"
    #endif
    #ifdef VACORE_WITH_AUDIO_BACKEND_VIRTUAL
    #include "Drivers/Audio/VAVirtualAudioDriverBackend.h"
    #endif
    
    // ITA includes
    #include <ITAASCIITable.h>
    #include <ITAClock.h>
    #include <ITAException.h>
    #include <ITAFileSystemUtils.h>
    #include <ITAFunctors.h>
    #include <ITAStreamDetector.h>
    #include <ITASoundSample.h>
    #include <ITASoundSampler.h>
    #include <ITASoundSamplePool.h>
    #include <ITAStreamAmplifier.h>
    #include <ITAStreamPatchBay.h>
    #include <ITAStreamProbe.h>
    #include <ITAStringUtils.h>
    
    // Vista includes
    #include <VistaTools/VistaFileSystemFile.h>
    #include <VistaTools/VistaFileSystemDirectory.h>
    
    // 3rdParty includes
    #include <DAFF.h>
    
    // STL includes
    #include <algorithm>
    #include <iomanip>
    #include <iostream>
    
    
    // We know about unreferenced formal parameters. There are a lot of unused methods for future use.
    #pragma warning( disable : 4100 )
    
    /*
    
    	Informationen
    	=-=-=-=-=-=-=
    
    	Thread-safety & locking
    
    	Alle durch die Schnittstelle nach aussen angebotenen Funktionen, werden
    	gegen Reentrance grob-granular mittels eines kritischen Bereiches gesperrt.
    	Damit sind auch parallele Calls auf unterschiedliche Methoden der Klasse
    	unterbunden. Sollte dies zu Performance-Problemen fhren, kann ein
    	verfeinerter Locking-Mechanismus entwickelt werden. Zunchst mal aber so.
    
    
    	TODO: berall sicherstellen, das ITAExceptions zu VAExceptions umgebaut werden!!!
    
    	*/
    
    
    // --= Hilfsmakros =--
    
    // berprfung ob Initialisiert
    #define VA_CHECK_INITIALIZED \
    { if (m_iState != VA_CORESTATE_READY) VA_EXCEPT2(MODAL_ERROR, "Core not initialized"); }
    
    // Mutex-Lock welches parallelen Methoden-Mehrfracheintritt (reentrance) im Methoden-Scope verhindert
    #define VA_NO_REENTRANCE \
    ITACriticalSectionLock oReentranceLock(m_csReentrance)
    
    // Manuelles das Lock gegen parallelen Methoden-Mehrfracheintritt (reentrance) holen
    #define VA_LOCK_REENTRANCE \
    m_csReentrance.enter()
    
    // Manuelle das Lock gegen parallelen Methoden-Mehrfracheintritt (reentrance) freigeben 
    #define VA_UNLOCK_REENTRANCE \
    m_csReentrance.leave()
    
    /*
    
    	Sichere Ausnahmebehandlung
    
    	Problem: Intern knnen auch andere Typen von Ausnahmen als
    	CVAException geworfen werden. Nach aussen hin drfen
    	aber NUR CVAExceptions geworfen werden (Konsistent)
    
    	Lsung: TRY-/CATCH-Makros fr abgesicherte Bereiche in allen Methoden
    	der externen Schnittstelle. Zweistufiger Aufbau.
    	1. (innen) Fange alle Exception-Typen und konvertiere sie in CVAExceptions
    	2. (aussen) Fange die einzig mgl. CVAExceptions und biete
    	gemeinsamen Catch-Weg zur Problemlsung (Aufrumen) an
    
    	try {
    	try {
    	// Code ...
    	} catch (ITAException& e) {
    	// Konvertiere zu CVAException
    	} catch (VistaExceptionBase& e) {
    	// Konvertiere zu CVAException
    	} catch (...)
    	// Generiere unerwartete CVAException
    	}
    	} catch (CVAException& e) {
    	// Gemeinsames Aufrumen
    	}
    
    	Beispiel:
    
    	VA_TRY {
    	// Code ..
    	} VA_CATCH {
    	// Mach was ...
    	}
    
    	Hinweis: Initiale/finale Geschweifte Klammer fehlen, da diese hinter die Makros geschrieben werden
    
    	*/
    
    #define VA_TRY \
    try { try
    
    #define VA_CATCH(EXPR) \
    catch( CVAException& e ) { throw e; } \
    catch( ITAException& e ) { throw convert2VAException( e ); } \
    catch( VistaExceptionBase& e ) { throw convert2VAException( e ); } \
    catch( ... ) { throw getDefaultUnexpectedVAException(); } \
    } catch( CVAException& EXPR )
    
    #define VA_FINALLY \
    catch( CVAException& e ) { throw e; } \
    catch( ITAException& e ) { throw convert2VAException( e ); } \
    catch( VistaExceptionBase& e ) { throw convert2VAException(e); } \
    catch( ... ) { throw getDefaultUnexpectedVAException(); } \
    } catch( ... )
    
    #define VA_RETHROW \
    catch( CVAException& e ) { throw e; } \
    catch( ITAException& e ) { throw convert2VAException( e ); } \
    catch( VistaExceptionBase& e ) { throw convert2VAException( e ); } \
    catch( ... ) { throw getDefaultUnexpectedVAException(); } \
    } catch( ... ) { throw; }
    
    
    IVAInterface* VACore::CreateCoreInstance( const CVAStruct& oArgs, std::ostream* pOutputStream )
    {
    	VA_TRACE( "Config", oArgs );
    	return new CVACoreImpl( oArgs, pOutputStream );
    }
    
    void VACore::StoreCoreConfigToFile( const CVAStruct& oConfig, const std::string& sConfigFilePath )
    {
    	StoreStructToINIFile( sConfigFilePath, oConfig );
    }
    
    CVAStruct VACore::LoadCoreConfigFromFile( const std::string& sConfigFilePath )
    {
    	CVAStruct oFinalCoreConfigStruct, oCurrentConfig;
    	std::list< VistaFileSystemFile > voConfigFiles;
    	std::vector< VistaFileSystemDirectory > voIncludePaths;
    	voConfigFiles.push_back( VistaFileSystemFile( sConfigFilePath ) );
    
    	VA_INFO( "Core", "Working directory: '" << VistaFileSystemDirectory::GetCurrentWorkingDirectory() << "'" );
    
    	while( voConfigFiles.empty() == false )
    	{
    		VistaFileSystemFile oCurrentConfigFile( voConfigFiles.front() );
    		voConfigFiles.pop_front();
    
    		if( oCurrentConfigFile.Exists() == false )
    		{
    			for( size_t n = 0; n < voIncludePaths.size(); n++ )
    			{
    				std::string sCombinedFilePath = voIncludePaths[ n ].GetName() + PATH_SEPARATOR + oCurrentConfigFile.GetLocalName();
    				oCurrentConfigFile.SetName( sCombinedFilePath );
    				if( oCurrentConfigFile.Exists() && oCurrentConfigFile.IsFile() )
    				{
    					VA_INFO( "Config", "Including further configuration file '" + oCurrentConfigFile.GetLocalName() +
    						"' from include path '" + voIncludePaths[ n ].GetName() + "'" );
    					break;
    				}
    			}
    
    			if( !oCurrentConfigFile.Exists() )
    			{
    				VA_EXCEPT2( FILE_NOT_FOUND, "Configuration file '" + oCurrentConfigFile.GetLocalName() + "' not found, aborting." );
    			}
    		}
    
    		VA_VERBOSE( "Config", std::string( "Reading INI file '" ) + oCurrentConfigFile.GetLocalName() + "'" );
    		LoadStructFromINIFIle( oCurrentConfigFile.GetName(), oCurrentConfig );
    
    		if( oCurrentConfig.HasKey( "paths" ) )
    		{
    			const CVAStruct& oPaths( oCurrentConfig[ "paths" ] );
    			CVAStruct::const_iterator it = oPaths.Begin();
    			while( it != oPaths.End() )
    			{
    				const CVAStructValue& oIncludePath( ( it++ )->second );
    				VistaFileSystemDirectory oNewPathDir( oIncludePath );
    				if( oNewPathDir.Exists() && oNewPathDir.IsDirectory() )
    					voIncludePaths.push_back( oNewPathDir );
    			}
    		}
    
    		if( oCurrentConfig.HasKey( "files" ) )
    		{
    			const CVAStruct& oPaths( oCurrentConfig[ "files" ] );
    			CVAStruct::const_iterator it = oPaths.Begin();
    			while( it != oPaths.End() )
    			{
    				const CVAStructValue& oIncludeFile( ( it++ )->second );
    
    				voConfigFiles.push_back( VistaFileSystemFile( oIncludeFile ) );
    			}
    		}
    
    		oCurrentConfig.RemoveKey( "files" );
    
    		// Merge structs (check for uniqueness)
    		oFinalCoreConfigStruct.Merge( oCurrentConfig, true );
    	}
    
    	return oFinalCoreConfigStruct;
    }
    
    #ifdef WIN32
    // Trick um DLL-Pfad zu ermitteln
    EXTERN_C IMAGE_DOS_HEADER __ImageBase;
    #endif
    
    std::string VACore::GetCoreLibFilePath()
    {
    #ifdef WIN32
    	CHAR pszPath[ MAX_PATH + 1 ] = { 0 };
    	GetModuleFileNameA( ( HINSTANCE ) &__ImageBase, pszPath, _countof( pszPath ) );
    	return std::string( pszPath );
    #else
    	VA_EXCEPT2( NOT_IMPLEMENTED, "This function is not implemented for your platform. Sorry." );
    	return "";
    #endif // WIN32
    }
    
    CVACoreImpl::CVACoreImpl( const CVAStruct& oArgs, std::ostream* pOutputStream )
    	: m_pAudioDriverBackend( nullptr )
    	, m_pGlobalSamplePool( nullptr )
    	, m_pGlobalSampler( nullptr )
    	, m_pSignalSourceManager( nullptr )
    	, m_pDirectivityManager( nullptr )
    	, m_pSceneManager( nullptr )
    	, m_pNewSceneState( nullptr )
    	, m_iCurActiveSoundReceiver( -1 )
    	, m_iNewActiveSoundReceiver( -1 )
    	, m_iUpdActiveSoundReceiver( -1 )
    	, m_pEventManager( nullptr )
    	, m_pCoreThread( nullptr )
    	, m_pInputAmp( nullptr )
    	, m_pR2RPatchbay( nullptr )
    	, m_pOutputPatchbay( nullptr )
    	, m_pInputStreamDetector( nullptr )
    	, m_pOutputStreamDetector( nullptr )
    	, m_pOutputTracker( nullptr )
    	, m_pStreamProbeDeviceInput( nullptr )
    	, m_pStreamProbeFinal( nullptr )
    	, m_pCurSceneState( nullptr )
    	, m_pClock( ITAClock::getDefaultClock() )
    	, m_pTicker( NULL )
    	, m_lSyncModOwner( -1 )
    	, m_lSyncModSpinCount( 0 )
    	, m_iState( VA_CORESTATE_CREATED )
    	, m_iGlobalAuralizationMode( IVAInterface::VA_AURAMODE_ALL )
    	, m_dOutputGain( 1 )
    	, m_dInputGain( 1 )
    	, m_bOutputMuted( false )
    	, m_bInputMuted( false )
    	, m_dStreamClockOffset( 0 )
    	, m_fCoreClockOffset( 0 )
    	, m_oCoreThreadLoopTotalDuration( "Core thread loop" )
    {
    	VA_NO_REENTRANCE;
    
    	if( pOutputStream )
    		SetOutputStream( pOutputStream );
    
    	VA_TRY
    	{
    		// read configuration
    		m_oCoreConfig.Init( oArgs );
    
    		// register core itself as a module
    		SetObjectName( "VACore" );
    		m_oModules.RegisterObject( this );
    		VA_VERBOSE( "Core", "Registered core module with name '" << GetObjectName() << "'" );
    
    		// Der Event-Manager muss immer verfgbar sein,
    		// unabhnging davon ob der Core initialisiert wurde oder nicht.
    		m_pEventManager = new CVACoreEventManager;
    
    		m_iState = VA_CORESTATE_CREATED;
    
    		VA_TRACE( "Core", "CVACoreImpl instance created [" << this << "]" );
    
    	}
    	VA_RETHROW;
    }
    
    CVACoreImpl::~CVACoreImpl()
    {
    	VA_NO_REENTRANCE;
    
    	// Implizit finalisieren, falls dies nicht durch den Benutzer geschah
    	if( m_iState == VA_CORESTATE_READY )
    	{
    		VA_TRY
    		{
    			Finalize();
    		}
    			VA_FINALLY
    		{
    			// Fehler beim Finalisieren ignorieren
    		};
    	}
    
    	// Nachricht senden [blocking], das die Kerninstanz gelscht wird.
    	CVAEvent ev;
    	ev.iEventType = CVAEvent::DESTROY;
    	ev.pSender = this;
    	m_pEventManager->BroadcastEvent( ev );
    
    	// Module deregistrieren
    	m_oModules.Clear();
    
    	// Nachrichten-Manager freigeben
    	VA_TRY
    	{
    		delete m_pEventManager;
    	}
    	VA_RETHROW;
    
    	VA_TRACE( "Core", "CVACoreImpl instance deleted [" << this << "]" );
    
    	// Profiling ausgeben
    	VA_VERBOSE( "Core", m_oCoreThreadLoopTotalDuration.ToString() );
    }
    
    void CVACoreImpl::SetOutputStream( std::ostream* posDebug )
    {
    	VALog_setOutputStream( posDebug );
    	VALog_setErrorStream( posDebug );
    }
    
    void CVACoreImpl::GetVersionInfo( CVAVersionInfo* pVersionInfo ) const
    {
    	if( !pVersionInfo )
    		return;
    
    	std::stringstream ss;
    	ss << VACORE_VERSION_MAJOR << "." << VACORE_VERSION_MINOR;
    	pVersionInfo->sVersion = ss.str();
    	ss.clear();
    #ifdef VACORE_CMAKE_DATE
    	ss << VACORE_CMAKE_DATE;
    #else
    	ss << "Unkown date";
    #endif
    	pVersionInfo->sDate = ss.str();
    	pVersionInfo->sFlags = "";
    
    #ifdef DEBUG
    	pVersionInfo->sComments = "debug";
    #else
    	pVersionInfo->sComments = "release";
    #endif
    }
    
    void CVACoreImpl::AttachEventHandler( IVAEventHandler* pCoreEventHandler )
    {
    	VA_TRY
    	{
    		// Immer mglich. Unabhngig vom Zustand. Thread-safety wird im Manager geregelt.
    		m_pEventManager->AttachHandler( pCoreEventHandler );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::DetachEventHandler( IVAEventHandler* pCoreEventHandler )
    {
    	VA_TRY
    	{
    		// Immer mglich. Unabhngig vom Zustand. Thread-safety wird im Manager geregelt.
    		m_pEventManager->DetachHandler( pCoreEventHandler );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetState() const
    {
    	VA_VERBOSE( "Core", "Core state requested, current state is " << m_iState );
    	return m_iState;
    }
    
    void CVACoreImpl::Initialize() {
    	VA_NO_REENTRANCE;
    
    	// TODO: Prfen ob im Fehlerfall zurck in den sauberen Grundzustand [WICHTIG!]
    
    	VA_VERBOSE( "Core", "Initializing core" );
    
    	VA_TRY
    	{
    		if( m_iState == VA_CORESTATE_READY )
    		VA_EXCEPT2( MODAL_ERROR, "Core already initialized." );
    
    		if( m_iState == VA_CORESTATE_FAIL )
    			VA_EXCEPT2( MODAL_ERROR, "Core corrupted, reinitialization impossible" );
    
    		m_pCoreThread = new CVACoreThread( this );
    
    		SetProgress( "Setting up audio hardware", "", 1 );
    		InitializeAudioDriver();
    
    		m_pR2RPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize );
    
    		// Create output patch bay with a single output that uses all available physical audio outputs from sound card
    		m_pOutputPatchbay = new ITAStreamPatchbay( m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize );
    		int iPhysicalHardwareOutput = m_pOutputPatchbay->AddOutput( m_oCoreConfig.oAudioDriverConfig.iOutputChannels );
    		m_pOutputPatchbay->SetOutputGain( iPhysicalHardwareOutput, m_dOutputGain );
    
    		m_iGlobalAuralizationMode = VA_AURAMODE_ALL;
    
    		// Set up input stream network
    		ITADatasource* pInputTail = nullptr;
    		if( m_oCoreConfig.oAudioDriverConfig.iInputChannels > 0 )
    		{
    			pInputTail = m_pAudioDriverBackend->getInputStreamDatasource();
    			if( pInputTail )
    			{
    				m_pInputAmp = new ITAStreamAmplifier( pInputTail, ( float ) m_dInputGain );
    				m_pInputStreamDetector = new ITAStreamDetector( m_pInputAmp );
    				m_pInputStreamDetector->SetProfilerEnabled( true );
    				pInputTail = m_pInputStreamDetector;
    
    				if( m_oCoreConfig.bRecordDeviceInputEnabled )
    				{
    					m_pStreamProbeDeviceInput = new ITAStreamProbe( pInputTail, m_oCoreConfig.sRecordDeviceInputFilePath );
    					pInputTail = m_pStreamProbeDeviceInput;
    				}
    			}
    		}
    
    		SetProgress( "Setting up resource managers", "", 2 );
    
    		assert( m_oCoreConfig.oAudioDriverConfig.iInputChannels >= 0 );
    		m_pSignalSourceManager = new CVAAudioSignalSourceManager( this, m_oCoreConfig.oAudioDriverConfig, pInputTail );
    		m_pGlobalSamplePool = ITASoundSamplePool::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate );
    		m_pGlobalSampler = ITASoundSampler::Create( 1, m_oCoreConfig.oAudioDriverConfig.dSampleRate, m_oCoreConfig.oAudioDriverConfig.iBuffersize, m_pGlobalSamplePool );
    		m_pGlobalSampler->AddMonoTrack();
    
    		m_pDirectivityManager = new CVADirectivityManager( this, m_oCoreConfig.oAudioDriverConfig.dSampleRate );
    		m_pDirectivityManager->Initialize();
    
    
    		SetProgress( "Setting up scene management", "", 3 );
    
    		m_pSceneManager = new CVASceneManager( m_pClock );
    		m_pSceneManager->Initialize();
    		m_pCurSceneState = m_pSceneManager->GetHeadSceneState();
    
    		SetProgress( "Setting up medium environment", "", 4 );
    
    		oHomogeneousMedium = m_oCoreConfig.oInitialHomogeneousMedium;
    
    
    		SetProgress( "Initializing rendering modules", "", 5 );
    
    		// Register all renderers and initialize
    		CVAAudioRendererRegistry::GetInstance()->RegisterInternalCoreFactoryMethods();
    		InitializeAudioRenderers();
    
    		if( m_voRenderers.empty() )
    			VA_EXCEPT1( "No audio renderers created" );
    
    
    		SetProgress( "Initializing reproduction modules", "", 6 );
    
    		// Register all reproductions and initialize
    		CVAAudioReproductionRegistry::GetInstance()->RegisterInternalCoreFactoryMethods();
    		InitializeReproductionModules();
    
    		if( m_voReproductionModules.empty() )
    			VA_EXCEPT1( "No audio reproduction modules created" );
    
    
    		SetProgress( "Patching audio i/o of rendering and reproduction modules", "", 7 );
    
    		// Patch renderer and reproduction modules
    		PatchRendererToReproductionModules();
    
    		// Patch audio reproduction to output
    		PatchReproductionModulesToOutput();
    
    
    		// Create output peak detector that uses patch bay output stream
    
    		m_pOutputStreamDetector = new ITAStreamDetector( m_pOutputPatchbay->GetOutputDatasource( iPhysicalHardwareOutput ) );
    		m_pOutputStreamDetector->SetProfilerEnabled( true );
    
    
    		// Setup output dump (if set)
    		ITADatasource* pOutputTail = m_pOutputStreamDetector;
    		if( m_oCoreConfig.bRecordDeviceOutputEnabled )
    		{
    			m_pStreamProbeFinal = new ITAStreamProbe( pOutputTail, m_oCoreConfig.sRecordFinalOutputFilePath );
    			pOutputTail = m_pStreamProbeFinal;
    		}
    
    		// Attach the stream tracker
    		m_pOutputTracker = new CVAAudiostreamTracker( pOutputTail, m_pClock, &m_fCoreClockOffset, &m_lSyncModOwner, m_pSignalSourceManager );
    		pOutputTail = m_pOutputTracker;
    
    		// Give output stream datasource to audio driver
    		m_pAudioDriverBackend->setOutputStreamDatasource( pOutputTail );
    
    		// Core-Clock auf 0 initialisieren
    		double dNow = m_pClock->getTime();
    		m_fCoreClockOffset = ( float ) dNow;
    		m_dStreamClockOffset = -1;
    
    		// Timer erzeugen und konfigurieren (wird fr Peak-Events benutzt)
    		m_pTicker = new VistaTicker();
    		m_pTicker->AddTrigger( new VistaTicker::TriggerContext( m_oCoreConfig.iTriggerUpdateMilliseconds, true ) );
    		m_pTicker->SetAfterPulseFunctor( this );
    
    		// Audio-Streaming starten
    		SetProgress( "Starting audio streaming", "", 8 );
    		m_pAudioDriverBackend->startStreaming();
    
    		// Timer fr Peak-Events starten
    		m_pTicker->StartTicker();
    
    		// Initialisierung erfolgreich!
    		m_iState = VA_CORESTATE_READY;
    
    		SetProgress( "Initialization finished", "", 9 );
    		FinishProgress();
    
    	}
    		VA_FINALLY
    	{
    		// Aufrumen und Exception weiterwerfen
    		Tidyup();
    		throw;
    	}
    }
    
    void CVACoreImpl::Reset()
    {
    	VA_CHECK_INITIALIZED;
    
    	// Wait for core thread
    	while( !m_pCoreThread->TryBreak() )
    		VASleep( 20 );
    
    	VA_NO_REENTRANCE;
    
    	if( GetUpdateLocked() )
    	{
    		VA_WARN( "Core", "Encountered locked scene during reset. Please unlock before resetting, skipping." );
    		m_pCoreThread->Continue();
    	}
    
    	VA_TRY
    	{
    		VA_INFO( "Core", "Resetting core" );
    
    		// Reset audio renderers
    		std::vector< CVAAudioRendererDesc >::iterator it = m_voRenderers.begin();
    		while( it != m_voRenderers.end() )
    		{
    			CVAAudioRendererDesc& oRend( *it++ );
    			oRend.pInstance->Reset();
    		}
    
    		if( m_pCurSceneState )
    		{
    			// Referenz entfernen welche in CoreThreadLoop hinzugefgt wurde
    			m_pCurSceneState->RemoveReference();
    			m_pCurSceneState = nullptr;
    		}
    
    		// Alle Szenenobjekte lschen
    		m_pSceneManager->Reset();
    		m_pSignalSourceManager->Reset();
    		m_pDirectivityManager->Reset();
    
    		// TODO: Check if the pool and sampler must really be recreated
    		/*
    		delete m_pGlobalSamplePool;
    		m_pGlobalSamplePool = nullptr;
    		m_pGlobalSamplePool = ITASoundSamplePool::Create(1, m_oCoreConfig.oAudioDriverConfig.dSamplerate);
    
    		// This causes a crash in patch bay
    		delete m_pGlobalSampler;
    		m_pGlobalSampler = nullptr;
    		m_pGlobalSampler = ITASoundSampler::Create(1, m_oCoreConfig.oAudioDriverConfig.dSamplerate, m_oCoreConfig.oAudioDriverConfig.iBuffersize, m_pGlobalSamplePool);
    		m_pGlobalSampler->AddMonoTrack();
    		*/
    		//m_pGlobalSampler->RemoveAllPlaybacks();
    
    		// Werte neusetzen
    		m_pCurSceneState = m_pSceneManager->GetHeadSceneState();
    		m_iCurActiveSoundReceiver = -1;
    		m_iNewActiveSoundReceiver = -1;
    
    		m_pCoreThread;
    
    		// Core-Thread fortsetzen
    		m_pCoreThread->Continue();
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::RESET;
    		ev.pSender = this;
    		m_pEventManager->BroadcastEvent( ev );
    
    	}
    		VA_FINALLY
    	{
    		Tidyup();
    		throw;
    	}
    }
    
    void CVACoreImpl::Tidyup() {
    	/*
    	 *  Hinweis: Diese Hilfsmethode wird nur innerhalb des Reentrance-Locks
    	 *           aufgerufen - daher keine weiter Absicherung ntig.
    	 */
    
    	VA_TRY
    	{
    		if( m_pTicker )
    		{
    			m_pTicker->StopTicker();
    			m_pTicker->SetAfterPulseFunctor( NULL );
    		}
    
    		FinalizeAudioDriver();
    		FinalizeRenderingModules();
    		FinalizeReproductionModules();
    
    		delete m_pTicker;
    		m_pTicker = nullptr;
    
    		delete m_pCoreThread;
    		m_pCoreThread = nullptr;
    
    		delete m_pInputAmp;
    		m_pInputAmp = nullptr;
    
    		delete m_pInputStreamDetector;
    		m_pInputStreamDetector = nullptr;
    
    		delete m_pR2RPatchbay;
    		m_pR2RPatchbay = nullptr;
    
    		delete m_pOutputPatchbay;
    		m_pOutputPatchbay = nullptr;
    
    		delete m_pOutputStreamDetector;
    		m_pOutputStreamDetector = nullptr;
    
    		delete m_pOutputTracker;
    		m_pOutputTracker = nullptr;
    
    		delete m_pStreamProbeDeviceInput;
    		m_pStreamProbeDeviceInput = nullptr;
    
    		delete m_pStreamProbeFinal;
    		m_pStreamProbeFinal = nullptr;
    
    		delete m_pSignalSourceManager;
    		m_pSignalSourceManager = nullptr;
    
    		delete m_pGlobalSampler;
    		m_pGlobalSampler = nullptr;
    
    		delete m_pGlobalSamplePool;
    		m_pGlobalSamplePool = nullptr;
    
    		if( m_pDirectivityManager )
    			m_pDirectivityManager->Finalize();
    		delete m_pDirectivityManager;
    		m_pDirectivityManager = nullptr;
    
    
    		if( m_pSceneManager )
    			m_pSceneManager->Finalize();
    		delete m_pSceneManager;
    		m_pSceneManager = nullptr;
    
    		m_iState = VA_CORESTATE_CREATED;
    
    	}
    		VA_FINALLY
    	{
    		m_iState = VA_CORESTATE_FAIL;
    	}
    }
    
    void CVACoreImpl::Finalize()
    {
    	VA_NO_REENTRANCE;
    
    	//VA_TRACE("Core", __FUNCTION__ << " entry");
    	VA_INFO( "Core", "Finalizing core" );
    
    	VA_TRY
    	{
    		// Mehrfaches Finialisieren fhrt nicht zu Fehlern
    		if( m_iState == VA_CORESTATE_CREATED )
    		return;
    
    		if( m_iState == VA_CORESTATE_FAIL )
    			VA_EXCEPT2( MODAL_ERROR, "Core corrupted, finalization impossible" );
    
    		// Core-Thread anhalten (wenn frei ist)
    		while( !m_pCoreThread->TryBreak() )
    			VASleep( 10 );
    		//m_pCoreThread->Break(); << deadlock
    
    		// Alle Filterketten lschen und warten bis Zustand sicher bernommen
    		// Wichtig: Dies muss vor dem Beenden des Streamings geschehen
    
    		// Reset audio renderers
    		for( std::vector<CVAAudioRendererDesc>::iterator it = m_voRenderers.begin(); it != m_voRenderers.end(); ++it )
    			it->pInstance->Reset();
    
    		// Peak-Nachrichten stoppen
    		m_pTicker->StopTicker();
    
    		// Audio-Streaming beenden
    		m_pAudioDriverBackend->stopStreaming();
    
    		InitProgress( "Stopping auralization threads", "", 2 );
    
    		// Stop and delete ticker
    		m_pTicker->SetAfterPulseFunctor( NULL );
    		delete m_pTicker;
    		m_pTicker = NULL;
    
    		// Hauptthread beenden und freigeben
    		delete m_pCoreThread;
    		m_pCoreThread = nullptr;
    
    		SetProgress( "Releasing audio hardware", "", 1 );
    		FinalizeAudioDriver();
    		FinalizeRenderingModules();
    		FinalizeReproductionModules();
    
    		SetProgress( "Cleaning up resources", "", 2 );
    		delete m_pInputAmp;
    		m_pInputAmp = nullptr;
    
    		if( m_pInputStreamDetector )
    			if( m_pInputStreamDetector->GetProfilerEnabled() )
    				VA_VERBOSE( "Core", "Input stream detector profiler: " << m_pInputStreamDetector->GetProfilerResult() );
    		delete m_pInputStreamDetector;
    		m_pInputStreamDetector = nullptr;
    
    		m_voReproductionModules.clear();
    
    		delete m_pR2RPatchbay;
    		m_pR2RPatchbay = nullptr;
    
    		delete m_pOutputPatchbay;
    		m_pOutputPatchbay = nullptr;
    
    		if( m_pOutputStreamDetector->GetProfilerEnabled() )
    			VA_VERBOSE( "Core", "Output stream detector profiler: " << m_pOutputStreamDetector->GetProfilerResult() );
    		delete m_pOutputStreamDetector;
    		m_pOutputStreamDetector = nullptr;
    
    		delete m_pOutputTracker;
    		m_pOutputTracker = nullptr;
    
    		delete m_pStreamProbeDeviceInput;
    		m_pStreamProbeDeviceInput = nullptr;
    
    		delete m_pStreamProbeFinal;
    		m_pStreamProbeFinal = nullptr;
    
    		delete m_pSignalSourceManager;
    		m_pSignalSourceManager = nullptr;
    
    		delete m_pGlobalSampler;
    		m_pGlobalSampler = nullptr;
    
    		delete m_pGlobalSamplePool;
    		m_pGlobalSamplePool = nullptr;
    
    		m_pDirectivityManager->Finalize();
    		delete m_pDirectivityManager;
    		m_pDirectivityManager = nullptr;
    
    		m_pSceneManager->Finalize();
    		delete m_pSceneManager;
    		m_pSceneManager = nullptr;
    
    		// Finalisierung erfolgreich. Nun wieder im Grundzustand!
    		m_iState = VA_CORESTATE_CREATED;
    
    		FinishProgress();
    
    	}
    		VA_FINALLY
    	{
    		// Nochmals versuchen aufzurumen
    		Tidyup();
    
    		// Allgemein: Fehler beim Finalisieren? => Core im Sack
    		m_iState = VA_CORESTATE_FAIL;
    
    		// VAExceptions unverndert nach aussen leiten
    		throw;
    	}
    }
    
    
    void CVACoreImpl::RegisterModule( CVAObject* pModule )
    {
    	m_oModules.RegisterObject( pModule );
    }
    
    void CVACoreImpl::GetModules( std::vector< CVAModuleInfo >& viModuleInfos ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    #ifdef VACORE_MODULE_INTERFACE_ENABLED
    	VA_TRY
    	{
    		std::vector<CVAObjectInfo> v;
    		m_oModules.GetObjectInfos( v );
    
    		VA_PRINT( "Available modules (" << v.size() << ")" );
    
    		viModuleInfos.clear();
    		viModuleInfos.resize( v.size() );
    		for( size_t i = 0; i < v.size(); i++ )
    		{
    			VA_PRINT( "'" << v[ i ].sName << "'\t\t\t" << v[ i ].sDesc );
    			viModuleInfos[ i ].sName = v[ i ].sName;
    			viModuleInfos[ i ].sDesc = v[ i ].sDesc;
    		}
    	}
    	VA_RETHROW;
    
    #else // VACORE_MODULE_INTERFACE_ENABLED
    
    	VA_EXCEPT1( "This VACore version does not provide modules" );
    
    #endif // VACORE_MODULE_INTERFACE_ENABLED
    
    }
    
    CVAStruct CVACoreImpl::CallModule( const std::string& sModuleName, const CVAStruct& oArgs )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    #ifdef VACORE_MODULE_INTERFACE_ENABLED
    
    	VA_TRY
    	{
    		CVAObject* pModule = m_oModules.FindObjectByName( sModuleName );
    		if( !pModule )
    		{
    			VA_EXCEPT2( INVALID_PARAMETER, "Module '" + sModuleName + "' not found" );
    		}
    
    #ifdef VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
    		ev.pSender = this;
    		ev.sObjectID = sModuleName;
    		ev;
    		m_pEventManager->BroadcastEvent( ev );
    		m_pEventManager->
    
    #else // not VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
    
    		return pModule->CallObject( oArgs );
    
    #endif // VACORE_MODULE_INTERFACE_MECHANISM_EVENT_BASED
    
    	}
    	VA_RETHROW;
    
    #else // VACORE_MODULE_INTERFACE_ENABLED
    
    #ifdef VACORE_NO_MODULE_INTERFACE_THROW_EXCEPTION
    	VA_EXCEPT1( "This VACore version does not provide modules" );
    #endif // VACORE_NO_MODULE_INTERFACE_THROW_EXCEPTION
    
    #endif // VACORE_MODULE_INTERFACE_ENABLED
    }
    
    CVAStruct CVACoreImpl::GetSearchPaths() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	CVAStruct oSearchPaths;
    	for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
    		oSearchPaths[ "path_" + std::to_string( long( i ) ) ] = m_oCoreConfig.vsSearchPaths[ i ];
    
    	return oSearchPaths;
    }
    
    CVAStruct CVACoreImpl::GetCoreConfiguration( const bool bFilterEnabled ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	CVAStruct oCoreConfig;
    
    	if( bFilterEnabled )
    	{
    		CVAStruct::const_iterator cit = m_oCoreConfig.GetStruct().Begin();
    		while( cit != m_oCoreConfig.GetStruct().End() )
    		{
    			const std::string sKey( cit->first );
    			const CVAStructValue& oVal( cit->second );
    			++cit;
    
    			if( oVal.IsStruct() )
    			{
    				const CVAStruct& oSection( oVal.GetStruct() );
    				if( oSection.HasKey( "enabled" ) )
    					if( bool( oSection[ "enabled" ] ) == false )
    						continue; // Only skip if explicitly not enabled
    				oCoreConfig[ sKey ] = oVal;
    			}
    		}
    
    	}
    	else
    	{
    		oCoreConfig = m_oCoreConfig.GetStruct();
    	}
    
    	return oCoreConfig;
    }
    
    CVAStruct CVACoreImpl::GetHardwareConfiguration() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    	return m_oCoreConfig.oHardwareSetup.GetStruct();
    }
    
    CVAStruct CVACoreImpl::GetFileList( const bool bRecursive, const std::string& sFileSuffixFilter ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	CVAStruct oFileList;
    	for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
    	{
    		if( bRecursive )
    		{
    			RecursiveFileList( m_oCoreConfig.vsSearchPaths[ i ], oFileList, sFileSuffixFilter );
    		}
    		else
    		{
    			std::vector< std::string > vsFileList;
    			FileList( m_oCoreConfig.vsSearchPaths[ i ], vsFileList, sFileSuffixFilter );
    
    			CVAStruct oMoreFiles;
    			for( size_t j = 0; j < vsFileList.size(); j++ )
    				oMoreFiles[ std::to_string( long( j ) ) ] = vsFileList[ j ];
    
    			oFileList[ m_oCoreConfig.vsSearchPaths[ i ] ] = oMoreFiles;
    		}
    	}
    	return oFileList;
    }
    
    int CVACoreImpl::CreateDirectivityFromParameters( const CVAStruct& oParams, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		int iDirID = m_pDirectivityManager->CreateDirectivity( oParams, sName );
    
    		assert( iDirID != -1 );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::DIRECTIVITY_LOADED;
    		ev.pSender = this;
    		ev.iObjectID = iDirID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Directivity successfully loaded, assigned directivity ID " << iDirID );
    
    		return iDirID;
    
    	} VA_RETHROW;
    }
    
    bool CVACoreImpl::DeleteDirectivity( const int iDirID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSuccess = m_pDirectivityManager->DeleteDirectivity( iDirID );
    		//assert( bSuccess );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::DIRECTIVITY_DELETED;
    		ev.pSender = this;
    		ev.iObjectID = iDirID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "FreeDirectivity successful, freed directivity " << iDirID );
    
    		return bSuccess;
    
    	} VA_RETHROW;
    }
    
    CVADirectivityInfo CVACoreImpl::GetDirectivityInfo( int iDirID ) const {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY{
    		return m_pDirectivityManager->GetDirectivityInfo( iDirID );
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::GetDirectivityInfos( std::vector<CVADirectivityInfo>& vdiDest ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pDirectivityManager->GetDirectivityInfos( vdiDest );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetDirectivityName( const int iID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
    		//m_pDirectivityManager->SetName( iID, sName );
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::GetDirectivityName( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVADirectivityInfo oInfo = m_pDirectivityManager->GetDirectivityInfo( iID );
    		return oInfo.sName;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetDirectivityParameters( const int iID, const CVAStruct& oParams )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
    		//m_pDirectivityManager->SetParameters( iID, oParams );
    	}
    	VA_RETHROW;
    }
    
    CVAStruct CVACoreImpl::GetDirectivityParameters( const int iID, const CVAStruct& ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVADirectivityInfo oInfo = m_pDirectivityManager->GetDirectivityInfo( iID );
    		return oInfo.oParams;
    
    		// @todo
    		//return m_pDirectivityManager->GetDirectivityParameters( iID, oParams );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::CreateAcousticMaterial( const CVAAcousticMaterial& oMaterial, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::CreateAcousticMaterialFromParameters( const CVAStruct& oParams, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    bool CVACoreImpl::DeleteAcousticMaterial( const int iID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    CVAAcousticMaterial CVACoreImpl::GetAcousticMaterialInfo( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::GetAcousticMaterialInfos( std::vector< CVAAcousticMaterial >& voDest ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetAcousticMaterialName( const int iID, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    std::string CVACoreImpl::GetAcousticMaterialName( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetAcousticMaterialParameters( const int iID, const CVAStruct& oParams )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    CVAStruct CVACoreImpl::GetAcousticMaterialParameters( const int iID, const CVAStruct& oParams ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::CreateGeometryMesh( const CVAGeometryMesh& oMesh, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::CreateGeometryMeshFromParameters( const CVAStruct& oParams, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    bool CVACoreImpl::DeleteGeometryMesh( const int iID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    CVAGeometryMesh CVACoreImpl::GetGeometryMesh( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::GetGeometryMeshIDs( std::vector< int >& viIDs ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetGeometryMeshName( const int iID, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    std::string CVACoreImpl::GetGeometryMeshName( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetGeometryMeshParameters( const int iID, const CVAStruct& oParams )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    CVAStruct CVACoreImpl::GetGeometryMeshParameters( const int iID, const CVAStruct& oParams ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetGeometryMeshEnabled( const int iID, const bool bEnabled )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    bool CVACoreImpl::GetGeometryMeshEnabled( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    std::string CVACoreImpl::CreateSignalSourceBufferFromParameters( const CVAStruct& oParams, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( oParams.HasKey( "filepath" ) )
    		{
    			const std::string sFilePath = oParams[ "filepath" ];
    			const std::string sDestFilePath = FindFilePath( sFilePath );
    			if( sDestFilePath.empty() )
    				VA_EXCEPT2( INVALID_PARAMETER, "Looked everywhere, but could not find file '" + sFilePath + "'" );
    
    			std::string sID = m_pSignalSourceManager->CreateAudiofileSignalSource( sDestFilePath, sName );
    			assert( !sID.empty() );
    
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
    			ev.pSender = this;
    			ev.sObjectID = sID;
    			m_pEventManager->BroadcastEvent( ev );
    
    			VA_INFO( "Core", "Created audiofile signal source (ID=" << sID << ", Name=\"" << sName << "\", Filename=\"" << sDestFilePath << "\")" );
    
    			return sID;
    		}
    		else
    		{
    			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret parameter arguments to create a buffer signal source" );
    		}
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::CreateSignalSourceTextToSpeech( const std::string& sName /*= "" */ )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		std::string sID = m_pSignalSourceManager->CreateTextToSpeechSignalSource( sName );
    		assert( !sID.empty() );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Created text-to-speech signal source ( ID=" << sID << ", Name=\"" << sName << "\" )" );
    
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::CreateSignalSourceSequencer( const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		std::string sID = m_pSignalSourceManager->CreateSequencerSignalSource( sName );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Created sequencer signal source (ID=" << sID << ", Name=\"" << sName << "\")" );
    
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::CreateSignalSourceNetworkStream( const std::string& sInterface, const int iPort, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_TRACE( "Core", "Attempting to connect to a netstream signal source on " << sInterface << " with port " << iPort );
    		std::string sID = m_pSignalSourceManager->CreateNetstreamSignalSource( sInterface, iPort, sName );
    		assert( !sID.empty() );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Created network stream signal source (ID=" << sID << ", Name='" << sName << "', Interface=" << sInterface << ":" << iPort << ")" );
    
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::CreateSignalSourceEngine( const CVAStruct&, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		std::string sID = m_pSignalSourceManager->CreateEngineSignalSource( sName );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_CREATED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Created engine signal source (ID=" << sID << ", Name=\"" << sName << "\")" );
    
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    
    std::string CVACoreImpl::CreateSignalSourceMachine( const CVAStruct&, const std::string& sName/*="" */ )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		std::string sID = m_pSignalSourceManager->CreateMachineSignalSource( sName );
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    
    bool CVACoreImpl::DeleteSignalSource( const std::string& sID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSignalSourceManager->DeleteSignalSource( sID );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_DELETED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_INFO( "Core", "Deleted signal source " << sID );
    		return true;
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::RegisterSignalSource( IVAAudioSignalSource* pSignalSource, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		std::string sID = m_pSignalSourceManager->RegisterSignalSource( pSignalSource, sName, false, false );
    		assert( !sID.empty() );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_REGISTERED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		return sID;
    	}
    	VA_RETHROW;
    }
    
    bool CVACoreImpl::UnregisterSignalSource( IVAAudioSignalSource* pSignalSource )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// ID der Quelle suchen
    		std::string sID = m_pSignalSourceManager->GetSignalSourceID( pSignalSource );
    		if( sID.empty() )
    			VA_EXCEPT2( INVALID_ID, "Invalid signal source ID" );
    
    		m_pSignalSourceManager->UnregisterSignalSource( sID );
    
    		// Ereignis generieren, wenn Operation erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_UNREGISTERED;
    		ev.pSender = this;
    		ev.sObjectID = sID;
    		m_pEventManager->BroadcastEvent( ev );
    	}
    	VA_RETHROW;
    
    	return true;
    }
    
    CVASignalSourceInfo CVACoreImpl::GetSignalSourceInfo( const std::string& sSignalSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASignalSourceInfo ssi = m_pSignalSourceManager->GetSignalSourceInfo( sSignalSourceID );
    		return ssi;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSignalSourceInfos( std::vector<CVASignalSourceInfo>& vssiDest ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSignalSourceManager->GetSignalSourceInfos( vssiDest );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetSignalSourceBufferPlaybackState( const std::string& sSignalSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    		CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
    
    		int iState = pAudiofileSource->GetPlaybackState();
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		return iState;
    	} VA_RETHROW;
    }
    
    CVAStruct CVACoreImpl::GetSignalSourceParameters( const std::string& sSignalSourceID, const CVAStruct& oParams ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    		CVAStruct oRet = pSource->GetParameters( oParams );
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    		return oRet;
    	} VA_RETHROW;
    
    }
    
    int CVACoreImpl::AddSignalSourceSequencerSample( const std::string& sSignalSourceID, const CVAStruct& oArgs )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED;
    }
    
    void CVACoreImpl::SetSignalSourceParameters( const std::string& sSignalSourceID, const CVAStruct& oParams )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    		pSource->SetParameters( oParams );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
    		ev.pSender = this;
    		ev.sObjectID = sSignalSourceID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		VA_VERBOSE( "Core", "Changed parameters of signal source " << sSignalSourceID );
    
    	} VA_RETHROW;
    
    }
    
    void CVACoreImpl::SetSignalSourceBufferPlaybackAction( const std::string& sSignalSourceID, const int iPlaybackAction )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( !GetSignalSourceBufferPlaybackActionValid( iPlaybackAction ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback action" );
    
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    
    		if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			VA_EXCEPT2( INVALID_PARAMETER, "Cannot set playback action for this type of signal source" );
    		}
    
    		CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
    		pAudiofileSource->SetPlaybackAction( iPlaybackAction );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
    		ev.pSender = this;
    		ev.sObjectID = sSignalSourceID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		VA_INFO( "Core", "Set audio file signal source '" << sSignalSourceID << "'"
    			<< " playstate action to " << IVAInterface::GetPlaybackActionStr( iPlaybackAction ) );
    
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::SetSignalSourceBufferPlaybackPosition( const std::string& sSignalSourceID, const double dPlaybackPosition )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// Parameter berprfen
    		if( dPlaybackPosition < 0 )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid playback position" );
    
    		// Quelle anfordern (prft auf gltige ID)
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    
    		// Playstate kann man nur bei Dateiquellen setzen
    		if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			VA_EXCEPT2( INVALID_PARAMETER, "Cannot set playstate for this type of signal source" );
    		}
    
    		/* TODO:
    		// Sicherstellen das es eine Dateiquelle ist
    		if (pSource->GetTypeMnemonic() != "af") {
    		m_pSignalSourceMan->ReleaseSignalSource(pSource);
    		VA_EXCEPT2(INVALID_PARAMETER, "Invalid auralization mode");
    		}
    		*/
    
    		// Zustand setzen
    		CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
    		try
    		{
    			pAudiofileSource->SetCursorSeconds( dPlaybackPosition );
    		}
    		catch( ... )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			throw;
    		}
    
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		VA_INFO( "Core", "Set audiofile signal source " << sSignalSourceID << " playback position to " << dPlaybackPosition );
    
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::SetSignalSourceBufferLooping( const std::string& sSignalSourceID, const bool bLooping )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    
    		if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			VA_EXCEPT2( INVALID_PARAMETER, "Cannot set looping mode for this type of signal source" );
    		}
    
    		CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
    		pAudiofileSource->SetIsLooping( bLooping );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SIGNALSOURCE_STATE_CHANGED;
    		ev.pSender = this;
    		ev.sObjectID = sSignalSourceID;
    		m_pEventManager->BroadcastEvent( ev );
    
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		VA_INFO( "Core", "Changed audiofile signal source '" << sSignalSourceID << "'"
    			<< " playstate looping mode to " << ( bLooping ? "looping" : "not looping" ) );
    
    	} VA_RETHROW;
    }
    
    bool CVACoreImpl::GetSignalSourceBufferLooping( const std::string& sSignalSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		IVAAudioSignalSource* pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    
    		if( pSource->GetType() != IVAAudioSignalSource::VA_SS_AUDIOFILE )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			VA_EXCEPT2( INVALID_PARAMETER, "Cannot set looping mode for this type of signal source" );
    		}
    
    		CVAAudiofileSignalSource* pAudiofileSource = dynamic_cast< CVAAudiofileSignalSource* >( pSource );
    		bool bLooping = pAudiofileSource->GetIsLooping();
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		return bLooping;
    
    	} VA_RETHROW;
    }
    
    int CVACoreImpl::AddSignalSourceSequencerPlayback( const std::string& sSignalSourceID, const int iSoundID, const int iFlags, const double dTimecode )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	IVAAudioSignalSource* pSource = nullptr;
    
    	VA_TRY
    	{
    		// Quelle anfordern (prft auf gltige ID)
    		pSource = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID );
    
    		// Playbacks kann man nur bei Sequencer-Quellen modifizieren
    		if( pSource->GetType() != IVAAudioSignalSource::VA_SS_SEQUENCER )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			VA_EXCEPT2( INVALID_PARAMETER, "Playbacks can only be added to sequencer signal sources" );
    		}
    
    		/* TODO:
    		// Sicherstellen das es eine Sampler ist
    		if (pSource->GetTypeMnemonic() != "af") {
    		m_pSignalSourceMan->ReleaseSignalSource(pSource);
    		VA_EXCEPT2(INVALID_PARAMETER, "Invalid auralization mode");
    		}
    		*/
    
    		// Zustand setzen
    		int iPlaybackID;
    		try
    		{
    			CVASequencerSignalSource* pSamplerSource = dynamic_cast< CVASequencerSignalSource* >( pSource );
    			iPlaybackID = pSamplerSource->AddSoundPlayback( iSoundID, iFlags, dTimecode );
    		}
    		catch( ... )
    		{
    			m_pSignalSourceManager->ReleaseSignalSource( pSource );
    			throw;
    		}
    
    		// Signalquelle freigeben
    		m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		VA_INFO( "Core", "Added sound playback (Signal source=" << sSignalSourceID << ", Sound=" << iSoundID << ", Flags=" << iFlags << ", Timecode=" << dTimecode << ")" );
    
    		return iPlaybackID;
    
    	}
    		VA_FINALLY
    	{
    		// Signalquelle freigeben
    		if( pSource ) m_pSignalSourceManager->ReleaseSignalSource( pSource );
    
    		// VAExceptions unverndert nach aussen leiten
    		throw;
    	}
    }
    
    void CVACoreImpl::RemoveSignalSourceSequencerSample( const std::string& sSignalSourceID, const int iSoundID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED;
    }
    
    
    bool CVACoreImpl::GetUpdateLocked() const
    {
    	VA_CHECK_INITIALIZED;
    	return ( m_lSyncModOwner != -1 );
    }
    
    void CVACoreImpl::LockUpdate()
    {
    	m_dSyncEntryTime = m_pClock->getTime();
    
    	VA_CHECK_INITIALIZED;
    	VA_LOCK_REENTRANCE;
    
    	if( m_lSyncModOwner != -1 )
    	{
    		// Thread already owner, increment spin counter
    		if( getCurrentThreadID() == m_lSyncModOwner )
    		{
    			++m_lSyncModSpinCount;
    			VA_UNLOCK_REENTRANCE;
    			VA_VERBOSE( "Core", "Attempt to enter synchronized scene modification ignored - already in a synchronized scene modification" );
    			return;
    		}
    	}
    
    	VA_UNLOCK_REENTRANCE;
    
    	VA_TRACE( "Core", "Beginning synchronized scene modification" );
    
    	/*
    	 *  Blocking wait des aufrufenden Thread.
    	 *  Wichtig: Dies muss ausserhalb des Reentrance-Lock geschehen,
    	 *           da sonst kein anderer Thread mehr auf der Schnittstelle aufrufen kann.
    	 */
    	m_mxSyncModLock.Lock();
    
    	VA_LOCK_REENTRANCE;
    
    	m_lSyncModOwner = getCurrentThreadID();
    	++m_lSyncModSpinCount;
    
    	VA_TRY
    	{
    		m_pNewSceneState = m_pSceneManager->CreateDerivedSceneState( m_pSceneManager->GetHeadSceneStateID(), m_dSyncEntryTime );
    		VA_UNLOCK_REENTRANCE;
    
    	}
    		VA_FINALLY
    	{
    		m_mxSyncModLock.Unlock();
    		m_lSyncModOwner = -1;
    		VA_UNLOCK_REENTRANCE;
    		throw;
    	}
    }
    
    int CVACoreImpl::UnlockUpdate()
    {
    	VA_CHECK_INITIALIZED;
    	VA_LOCK_REENTRANCE;
    
    	int iNewSceneID = -1;
    
    	VA_TRACE( "Core", "Unlocking scene" );
    
    	// Sicherheitscheck: Gar nicht innerhalb Synchronisation => Fehler
    	if( m_lSyncModOwner == -1 )
    	{
    		VA_UNLOCK_REENTRANCE;
    		VA_EXCEPT2( MODAL_ERROR, "Not within a synchronized modification phase" );
    	}
    
    	if( m_lSyncModOwner != getCurrentThreadID() )
    	{
    		VA_UNLOCK_REENTRANCE;
    		VA_EXCEPT2( MODAL_ERROR, "Synchronized modification may only be ended by the same thread that begun it" );
    	}
    
    	if( --m_lSyncModSpinCount > 0 )
    	{
    		// Nicht die letzte Freigabe des Token.
    		VA_UNLOCK_REENTRANCE;
    		return -1;
    	}
    
    	VA_TRY
    	{
    		m_pNewSceneState->Fix();
    
    		iNewSceneID = m_pNewSceneState->GetID();
    		m_pSceneManager->SetHeadSceneState( iNewSceneID );
    
    		m_iNewActiveSoundReceiver = m_iUpdActiveSoundReceiver;
    
    		m_lSyncModOwner = -1;
    		m_mxSyncModLock.Unlock();
    
    		VA_UNLOCK_REENTRANCE;
    	}
    		VA_FINALLY
    	{
    		VA_UNLOCK_REENTRANCE;
    		throw;
    	}
    		VA_TRY
    	{
    		m_pCoreThread->Trigger();
    		m_pEventManager->BroadcastEvents();
    		return iNewSceneID;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundSourceIDs( std::vector< int >& vSoundSourceIDs )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->GetHeadSceneState()->GetSoundSourceIDs( &vSoundSourceIDs );
    	}
    	VA_RETHROW;
    }
    
    CVASoundSourceInfo CVACoreImpl::GetSoundSourceInfo( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASoundSourceDesc* oDesc = m_pSceneManager->GetSoundSourceDesc( iID );
    		CVASoundSourceInfo oInfo;
    		oInfo.iID = oDesc->iID;
    		oInfo.bMuted = oDesc->bMuted;
    		oInfo.dSpoundPower = oDesc->fSoundPower;
    		oInfo.sName = oDesc->sName;
    		return oInfo;
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::CreateSoundSource( const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	const bool bInSyncMode = GetUpdateLocked();
    	if( !bInSyncMode )
    		LockUpdate();
    
    	VA_TRY
    	{
    		if( ( VACORE_MAX_NUM_SOUND_SOURCES != 0 ) && m_pNewSceneState )
    		{
    			int iSourcesRemain = VACORE_MAX_NUM_SOUND_SOURCES - m_pNewSceneState->GetNumSoundSources();
    			if( iSourcesRemain <= 0 )
    			{
    				std::stringstream ss;
    				ss << "Maximum number of sound sources reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_SOURCES << " sound sources.";
    				VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
    			}
    		}
    
    		// Schallquelle anlegen
    		int iSourceID = m_pNewSceneState->AddSoundSource();
    		assert( iSourceID != -1 );
    
    		// HINWEIS: Zunchst hier die statische Beschreibung der Quelle anlegen
    		CVASoundSourceDesc* pDesc = m_pSceneManager->CreateSoundSourceDesc( iSourceID );
    
    		// Keine Signalquelle zugewiesen. Wichtig: Stillepuffer einsetzen!
    		pDesc->pSignalSourceInputBuf = m_pSignalSourceManager->GetSilenceBuffer();
    
    		// Initiale Werte setzen
    		m_pSceneManager->SetSoundSourceName( iSourceID, sName );
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSourceID );
    		assert( pSourceState );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CREATED;
    		ev.pSender = this;
    		ev.iObjectID = iSourceID;
    		ev.sName = sName;
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bInSyncMode )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Created sound source '" << sName << "' and assigned ID " << iSourceID );
    
    		return iSourceID;
    	}
    		VA_FINALLY
    	{
    		if( bInSyncMode )
    		UnlockUpdate();
    
    		throw;
    	}
    }
    
    int CVACoreImpl::CreateSoundSourceExplicitRenderer( const std::string& sRendererID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	bool bSync = GetUpdateLocked();
    	if( !bSync )
    		LockUpdate();
    
    	VA_TRY
    	{
    		if( ( VACORE_MAX_NUM_SOUND_SOURCES != 0 ) && m_pNewSceneState )
    		{
    			int iSourcesRemain = VACORE_MAX_NUM_SOUND_SOURCES - m_pNewSceneState->GetNumSoundSources();
    			if( iSourcesRemain <= 0 )
    			{
    				std::stringstream ss;
    				ss << "Maximum number of sound sources reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_SOURCES << " sound sources.";
    				VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
    			}
    		}
    
    		int iSourceID = m_pNewSceneState->AddSoundSource();
    		assert( iSourceID != -1 );
    
    		CVASoundSourceDesc* pDesc = m_pSceneManager->CreateSoundSourceDesc( iSourceID );
    		pDesc->sExplicitRendererID = sRendererID;
    		pDesc->pSignalSourceInputBuf = m_pSignalSourceManager->GetSilenceBuffer();
    
    		m_pSceneManager->SetSoundSourceName( iSourceID, sName );
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSourceID );
    		assert( pSourceState );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CREATED;
    		ev.pSender = this;
    		ev.iObjectID = iSourceID;
    		ev.sName = sName;
    		ev.iAuralizationMode = VA_AURAMODE_ALL;
    		ev.dVolume = 1.0f;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Created sound receiver '" << sName << "' and assigned ID " << iSourceID << " explicitly for renderer '" << sRendererID << "' only" );
    
    		return iSourceID;
    	}
    		VA_FINALLY
    	{
    		if( bSync )
    		UnlockUpdate();
    		throw;
    	}
    }
    
    int CVACoreImpl::DeleteSoundSource( const  int iSoundSourceID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	bool bSync = GetUpdateLocked();
    	if( !bSync )
    		LockUpdate();
    
    	VA_TRY
    	{
    		m_pNewSceneState->RemoveSoundSource( iSoundSourceID );
    		int iResult = 0;
    
    		if( iResult == 0 )
    		{
    			// Ereignis generieren, wenn erfolgreich
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::SOUND_SOURCE_DELETED;
    			ev.pSender = this;
    			ev.iObjectID = iSoundSourceID;
    			m_pEventManager->EnqueueEvent( ev );
    		}
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Deleted sound source " << iSoundSourceID );
    
    		return iResult;
    
    	}
    		VA_FINALLY
    	{
    		if( !bSync )
    		UnlockUpdate();
    		throw;
    	}
    }
    
    void CVACoreImpl::SetSoundSourceEnabled( const int iSoundSourceID, const bool bEnabled )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    
    		if( pDesc->bEnabled != bEnabled )
    		{
    			pDesc->bEnabled = bEnabled;
    
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_MUTING; // @todo JST new event type
    			ev.pSender = this;
    			ev.iObjectID = iSoundSourceID;
    			//ev.bEnabled = bEnabled; // @todo JST
    			m_pEventManager->EnqueueEvent( ev );
    
    			// Trigger core thread
    			m_pCoreThread->Trigger();
    		}
    	}
    	VA_RETHROW;
    }
    
    bool CVACoreImpl::GetSoundSourceEnabled( const int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    		return pDesc->bEnabled;
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::GetSoundSourceName( const int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		return m_pSceneManager->GetSoundSourceName( iSoundSourceID );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceName( const int iSoundSourceID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->SetSoundSourceName( iSoundSourceID, sName );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_NAME;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.sName = sName;
    		m_pEventManager->BroadcastEvent( ev );
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::GetSoundSourceSignalSource( int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    		if( pDesc->pSignalSource.get() != nullptr )
    			return m_pSignalSourceManager->GetSignalSourceID( pDesc->pSignalSource );
    		else
    			return "";
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetSoundSourceGeometryMesh( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundSourceGeometryMesh( const int iSoundSourceID, const int iGeometryMeshID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundSourceSignalSource( int iSoundSourceID, const std::string& sSignalSourceID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	// Keine Signalquelle zugewiesen. Wichtig: Stillepuffer einsetzen!
    	IVAAudioSignalSource* pNewSrc( nullptr ); // Neu oder zustzlich ...
    	const ITASampleBuffer* pNewBuf( m_pSignalSourceManager->GetSilenceBuffer() );
    
    	VA_TRY
    	{
    		CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    
    		// Sicherstellen, das die Signalquellen ID gltig ist .. dann ID und Qu
    		if( !sSignalSourceID.empty() )
    			pNewSrc = m_pSignalSourceManager->RequestSignalSource( sSignalSourceID, &pNewBuf );
    
    		// Vorherige Bindung auflsen und Signalquelle freigeben
    		if( pDesc->pSignalSource.get() != nullptr )
    			m_pSignalSourceManager->ReleaseSignalSource( pDesc->pSignalSource );
    
    		// Vorhandene Signalquelle zu dieser SoundSource zuordnen (atomare Ops)
    		pDesc->pSignalSource.set( pNewSrc );
    		pDesc->pSignalSourceInputBuf.set( pNewBuf );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_SIGNALSOURCE;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.sParam = sSignalSourceID;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( pNewSrc == nullptr )
    		{
    			VA_INFO( "Core", "Removed signal source from sound source " << iSoundSourceID << " (now uses silence buffer samples)" );
    		}
    		else
    		{
    			VA_INFO( "Core", "Set sound source " << iSoundSourceID << " signal source '" << sSignalSourceID << "'" );
    		}
    
    		return;
    	}
    		VA_CATCH( ex )
    	{
    		// Referenz auf die neue Signalquelle wieder entfernen
    		if( pNewSrc )
    			m_pSignalSourceManager->ReleaseSignalSource( pNewSrc );
    		throw ex;
    	}
    }
    
    int CVACoreImpl::GetSoundSourceAuralizationMode( int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		return pSourceState->GetAuralizationMode();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceAuralizationMode( int iSoundSourceID, int iAuralizationMode )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// Parameter berprfen
    		if( !GetAuralizationModeValid( iAuralizationMode ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
    
    		bool bSync = GetUpdateLocked();
    		if( !bSync ) LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		pSourceState->SetAuralizationMode( iAuralizationMode );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_AURALIZATIONMODE;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.iAuralizationMode = iAuralizationMode;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceParameters( int iID, const CVAStruct& oParams )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSoundSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
    
    		if( !pSoundSourceState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		pSoundSourceState->SetParameters( oParams );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_NAME; // @todo create own core event "parameter changed"
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		// ev.oStruct @todo: add a struct to the event
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    	}
    	VA_RETHROW;
    }
    
    CVAStruct CVACoreImpl::GetSoundSourceParameters( int iID, const CVAStruct& oArgs ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSoundSourceState = pHeadState->GetSoundSourceState( iID );
    
    		if( !pSoundSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		return pSoundSourceState->GetParameters( oArgs );
    
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetSoundSourceDirectivity( int iSoundSourceID ) const {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    			// Quelle existiert nicht
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		return pSourceState->GetDirectivityID();
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceDirectivity( const int iSoundSourceID, const int iDirectivityID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		const IVADirectivity* pNewDirectivity = nullptr;
    		if( iDirectivityID != -1 )
    		{
    			pNewDirectivity = m_pDirectivityManager->RequestDirectivity( iDirectivityID );
    			if( !pNewDirectivity )
    			{
    				VA_EXCEPT2( INVALID_PARAMETER, "Invalid directivity ID" );
    				// TODO: Release des vernderten State?
    			}
    		}
    
    		pSourceState->SetDirectivityID( iDirectivityID );
    		pSourceState->SetDirectivityData( pNewDirectivity );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_DIRECTIVITY;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.iParamID = iDirectivityID;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync ) UnlockUpdate();
    
    	} VA_RETHROW;
    }
    
    double CVACoreImpl::GetSoundSourceSoundPower( const int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		return pSourceState->GetSoundPower();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceSoundPower( const int iSoundSourceID, const double dSoundPower )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// Parameter berprfen
    		if( !GetVolumeValid( dSoundPower ) )
    		{
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid volume" );
    		}
    
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		pSourceState->SetSoundPower( dSoundPower );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_SOUND_POWER;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.dVolume = dSoundPower;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync ) UnlockUpdate();
    
    	} VA_RETHROW;
    }
    
    bool CVACoreImpl::GetSoundSourceMuted( const int iSoundSourceID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    		return pDesc->bMuted;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceMuted( const int iSoundSourceID, const bool bMuted )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASoundSourceDesc* pDesc = m_pSceneManager->GetSoundSourceDesc( iSoundSourceID );
    
    		if( pDesc->bMuted != bMuted )
    		{
    			pDesc->bMuted = bMuted;
    
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_MUTING;
    			ev.pSender = this;
    			ev.iObjectID = iSoundSourceID;
    			ev.bMuted = bMuted;
    			m_pEventManager->EnqueueEvent( ev );
    
    			// Trigger core thread
    			m_pCoreThread->Trigger();
    		}
    	} VA_RETHROW;
    }
    
    
    void CVACoreImpl::GetSoundSourcePose( const int iSoundSourceID, VAVec3& v3Pos, VAQuat& qOrient ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		const CVAMotionState* pMotionState = pSourceState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
    
    		v3Pos = pMotionState->GetPosition();
    		qOrient = pMotionState->GetOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourcePose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
    		pNewMotionState->SetPosition( v3Pos );
    		pNewMotionState->SetOrientation( qOrient );
    
    		m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.vPos = v3Pos;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    VAVec3 CVACoreImpl::GetSoundSourcePosition( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iID );
    
    		if( !pSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		const CVAMotionState* pMotionState = pSourceState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetPosition();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourcePosition( const int iID, const VAVec3& v3Pos )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
    		pNewMotionState->SetPosition( v3Pos );
    
    		m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.vPos = v3Pos;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	} VA_RETHROW;
    }
    
    VAQuat CVACoreImpl::GetSoundSourceOrientation( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVASoundSourceState* pSourceState = pHeadState->GetSoundSourceState( iID );
    
    		if( !pSourceState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    
    		const CVAMotionState* pMotionState = pSourceState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound source has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundSourceOrientation( const int iID, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
    		pNewMotionState->SetOrientation( qOrient );
    
    		m_pSceneManager->GetSoundSourceDesc( iID )->bInitPositionOrientation = true;
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		//ev.qOrient = qOrient; // @todo
    		ConvertQuaternionToViewUp( qOrient, ev.vView, ev.vUp );
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundSourceOrientationVU( const int iID, VAVec3& v3View, VAVec3& v3Up ) const
    {
    	ConvertQuaternionToViewUp( GetSoundSourceOrientation( iID ), v3View, v3Up );
    }
    
    void CVACoreImpl::SetSoundSourceOrientationVU( const int iSoundSourceID, const VAVec3& v3View, const VAVec3& v3Up )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVASoundSourceState* pSourceState = m_pNewSceneState->AlterSoundSourceState( iSoundSourceID );
    
    		if( !pSourceState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound source ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pSourceState->AlterMotionState();
    		pNewMotionState->SetOrientationVU( v3View, v3Up );
    
    		m_pSceneManager->GetSoundSourceDesc( iSoundSourceID )->bInitPositionOrientation = true;
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_SOURCE_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iSoundSourceID;
    		ev.vView = v3View;
    		ev.vUp = v3Up;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundReceiverIDs( std::vector< int >& vSoundReceiverIDs ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->GetHeadSceneState()->GetListenerIDs( &vSoundReceiverIDs );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::CreateSoundReceiver( const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( ( VACORE_MAX_NUM_SOUND_RECEIVERS != 0 ) && m_pNewSceneState )
    		{
    			const int iListenersRemain = VACORE_MAX_NUM_SOUND_RECEIVERS - m_pNewSceneState->GetNumListeners();
    			if( iListenersRemain <= 0 )
    			{
    				std::stringstream ss;
    				ss << "Maximum number of listeners reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_RECEIVERS << " listeners.";
    				VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
    			}
    		}
    
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		// Hrer anlegen
    		const int iID = m_pNewSceneState->AddListener();
    		assert( iID != -1 );
    
    		// HINWEIS: Zunchst hier die statische Beschreibung der Quelle anlegen
    		m_pSceneManager->CreateListenerDesc( iID );
    
    		// Initiale Werte setzen
    		m_pSceneManager->SetListenerName( iID, sName );
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    		assert( pListenerState );
    
    		// INFO: Set the default position/orientation of the new listener
    		CVAMotionState* pMotionState = pListenerState->AlterMotionState();
    		pMotionState->SetPosition( VAVec3( 0, 0, 0 ) ); // Really?
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CREATED;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.sName = sName;
    		SetCoreEventParams( ev, pMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Created sound receiver '" << sName << "' and assigned ID " << iID );
    
    		return iID;
    
    	} VA_RETHROW;
    }
    
    int CVACoreImpl::DeleteSoundReceiver( const int iID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	bool bSync = GetUpdateLocked();
    	if( !bSync )
    		LockUpdate();
    
    	VA_TRY
    	{
    		if( iID == m_iCurActiveSoundReceiver )
    		{
    			UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Cannot delete a sound receiver that is set as active sound receiver" );
    		}
    
    		m_pNewSceneState->RemoveListener( iID );
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_DELETED;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Deleted sound receiver " << iID );
    
    		return 0;
    	}
    	VA_RETHROW;
    }
    
    CVASoundReceiverInfo CVACoreImpl::GetSoundReceiverInfo( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVAListenerDesc* oDesc = m_pSceneManager->GetListenerDesc( iID );
    		CVASoundReceiverInfo oInfo;
    		oInfo.iID = oDesc->iID;
    		oInfo.sName = oDesc->sName;
    		return oInfo;
    		// @todo improve
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::CreateSoundReceiverExplicitRenderer( const std::string& sRendererID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	bool bSync = GetUpdateLocked();
    	if( !bSync )
    		LockUpdate();
    
    	VA_TRY
    	{
    		if( ( VACORE_MAX_NUM_SOUND_RECEIVERS != 0 ) && m_pNewSceneState )
    		{
    			int iListenersRemain = VACORE_MAX_NUM_SOUND_RECEIVERS - m_pNewSceneState->GetNumListeners();
    			if( iListenersRemain <= 0 )
    			{
    				std::stringstream ss;
    				ss << "Maximum number of listeners reached. This version of VA only supports up to " << VACORE_MAX_NUM_SOUND_RECEIVERS << " listeners.";
    				VA_EXCEPT2( INVALID_PARAMETER, ss.str() );
    			}
    		}
    
    		int iListenerID = m_pNewSceneState->AddListener();
    		assert( iListenerID != -1 );
    
    		CVAListenerDesc* pDesc = m_pSceneManager->CreateListenerDesc( iListenerID );
    		pDesc->sExplicitRendererID = sRendererID;
    
    		m_pSceneManager->SetListenerName( iListenerID, sName );
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iListenerID );
    		assert( pListenerState );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CREATED;
    		ev.pSender = this;
    		ev.iObjectID = iListenerID;
    		ev.sName = sName;
    		ev.iAuralizationMode = VA_AURAMODE_ALL;
    		ev.dVolume = 1.0f;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Created sound receiver (ID=" << iListenerID << ", Name=\"" << sName << "\") explicitly for renderer '" << sRendererID << "' only" );
    
    		return iListenerID;
    	}
    		VA_FINALLY
    	{
    		if( bSync )
    		UnlockUpdate();
    		throw;
    	}
    }
    
    void CVACoreImpl::SetSoundReceiverEnabled( const int iID, const bool bEnabled )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVAListenerDesc* pDesc = m_pSceneManager->GetListenerDesc( iID );
    
    		if( pDesc->bEnabled != bEnabled )
    		{
    			pDesc->bEnabled = bEnabled;
    
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME; // @todo JST new event type
    			ev.pSender = this;
    			ev.iObjectID = iID;
    			//ev.bEnabled = bEnabled; // @todo JST
    			m_pEventManager->EnqueueEvent( ev );
    
    			// Trigger core thread
    			m_pCoreThread->Trigger();
    		}
    	} VA_RETHROW;
    }
    
    bool CVACoreImpl::GetSoundReceiverEnabled( const int iSoundReceiverID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const CVAListenerDesc* pDesc = m_pSceneManager->GetListenerDesc( iSoundReceiverID );
    		return pDesc->bEnabled;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetActiveSoundReceiverExplicitRenderer( const int iID, const std::string& sRendererID )
    {
    	// @todo JST call renderer and set active listener
    	VA_EXCEPT2( NOT_IMPLEMENTED, "This method is currently not available (not implented)." );
    }
    
    int CVACoreImpl::GetActiveSoundReceiverExplicitRenderer( const std::string& sRendererID ) const
    {
    	// @todo JST call renderer and return active listener
    	VA_EXCEPT2( NOT_IMPLEMENTED, "This method is currently not available (not implented)." );
    }
    
    std::string CVACoreImpl::GetSoundReceiverName( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		return m_pSceneManager->GetListenerName( iID );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverName( const int iID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->SetListenerName( iID, sName );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.sName = sName;
    		m_pEventManager->BroadcastEvent( ev );
    
    	} VA_RETHROW;
    }
    
    int CVACoreImpl::GetSoundReceiverAuralizationMode( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			// Hrer existiert nicht
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		return pListenerState->GetAuralizationMode();
    
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverAuralizationMode( const int iID, const int iAuralizationMode )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// Parameter berprfen
    		if( !GetAuralizationModeValid( iAuralizationMode ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
    
    		bool bSync = GetUpdateLocked();
    		if( !bSync ) LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState ) {
    			// Hrer existiert nicht
    			if( !bSync ) UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		pListenerState->SetAuralizationMode( iAuralizationMode );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_AURALIZATIONMODE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.iAuralizationMode = iAuralizationMode;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync ) UnlockUpdate();
    
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverParameters( const int iID, const CVAStruct& oParams )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID " + std::to_string( long( iID ) ) );
    		}
    
    		pListenerState->SetParameters( oParams );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_NAME; // @todo create own core event "parameter changed"
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		// ev.oStruct @todo: add a struct to the event
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    	}
    	VA_RETHROW;
    }
    
    CVAStruct CVACoreImpl::GetSoundReceiverParameters( const int iID, const CVAStruct& oArgs ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		return pListenerState->GetParameters( oArgs );
    
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetSoundReceiverDirectivity( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		return pListenerState->GetDirectivityID();
    
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverDirectivity( const int iID, const int iDirectivityID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		// Parameter berprfen
    		const IVADirectivity* pDirectivity = nullptr;
    		if( iDirectivityID != -1 )
    		{
    			pDirectivity = m_pDirectivityManager->RequestDirectivity( iDirectivityID );
    			if( !pDirectivity )
    				VA_EXCEPT2( INVALID_ID, "Invalid directivity dataset for ID " + std::to_string( iID ) );
    		}
    
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			// Quelle existiert nicht
    			if( !bSync )
    				UnlockUpdate();
    
    			if( pDirectivity )
    				m_pDirectivityManager->DeleteDirectivity( iDirectivityID );
    
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID " + std::to_string( iID ) );
    		}
    
    		pListenerState->SetDirectivityID( iDirectivityID );
    		pListenerState->SetDirectivity( pDirectivity );
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_DIRECTIVITY;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.iParamID = iDirectivityID;
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    		VA_INFO( "Core", "Linked sound receiver " + std::to_string( long( iID ) ) + " with HRIR dataset " + std::to_string( long( iDirectivityID ) ) );
    
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetSoundReceiverGeometryMesh( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundReceiverGeometryMesh( const int iSoundReceiverID, const int iGeometryMeshID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::GetSoundReceiverPose( const int iID, VAVec3& v3Pos, VAQuat& qOrient ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pListenerState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "SoundReceiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		v3Pos = pMotionState->GetPosition();
    		qOrient = pMotionState->GetOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverPose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID, not found in scene" );
    		}
    
    		CVAMotionState* pNewMotionState = pState->AlterMotionState();
    		pNewMotionState->SetPosition( v3Pos );
    		pNewMotionState->SetOrientation( qOrient );
    
    		//m_pSceneManager->GetListenerDesc( iID )->bInitPositionOrientation = true; // @todo
    
    		// Ereignis generieren, falls erfolgreich
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		ev.vPos = v3Pos;
    		//ev.qOrient = qOrient; // @todo
    		ConvertQuaternionToViewUp( qOrient, ev.vView, ev.vUp );
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    VAVec3 CVACoreImpl::GetSoundReceiverPosition( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pSoundReceiverState = pHeadState->GetReceiverState( iID );
    
    		if( !pSoundReceiverState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pSoundReceiverState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "SoundReceiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetPosition();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverPosition( const int iID, const VAVec3& v3Pos )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync ) UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		pNewMotionState->SetPosition( v3Pos );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	} VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundReceiverOrientationVU( const int iID, VAVec3& vView, VAVec3& vUp ) const
    {
    	ConvertQuaternionToViewUp( GetSoundReceiverOrientation( iID ), vView, vUp );
    }
    
    void CVACoreImpl::SetSoundReceiverOrientationVU( const int iID, const VAVec3& v3View, const VAVec3& v3Up )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		pNewMotionState->SetOrientationVU( v3View, v3Up );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    VAQuat CVACoreImpl::GetSoundReceiverOrientation( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pSoundReceiverState = pHeadState->GetReceiverState( iID );
    
    		if( !pSoundReceiverState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pSoundReceiverState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverOrientation( const int iID, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		pNewMotionState->SetOrientation( qOrient );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    VAQuat CVACoreImpl::GetSoundReceiverHeadAboveTorsoOrientation( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pListenerState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetHeadAboveTorsoOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverHeadAboveTorsoOrientation( const int iID, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		pNewMotionState->SetHeadAboveTorsoOrientation( qOrient );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundReceiverRealWorldPositionOrientationVU( const int iID, VAVec3& v3Pos, VAVec3& v3View, VAVec3& v3Up ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			// Hrer existiert nicht
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pListenerState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		v3Pos = pMotionState->GetRealWorldPose().vPos;
    		VAQuat qOrient = pMotionState->GetRealWorldPose().qOrient;
    		ConvertQuaternionToViewUp( qOrient, v3View, v3Up );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverRealWorldPositionOrientationVU( const int iID, const VAVec3& v3Pos, const VAVec3& v3View, const VAVec3& v3Up )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		CVAMotionState::CVAPose oNewPose;
    		oNewPose.vPos = v3Pos;
    		ConvertViewUpToQuaternion( v3View, v3Up, oNewPose.qOrient );
    		pNewMotionState->SetRealWorldPose( oNewPose );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_REAL_WORLD_POSE_CHANGED;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::GetSoundReceiverRealWorldPose( const int iID, VAVec3& v3Pos, VAQuat& qOrient ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			// Hrer existiert nicht
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pListenerState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		v3Pos = pMotionState->GetRealWorldPose().vPos;
    		qOrient = pMotionState->GetRealWorldPose().qOrient;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverRealWorldPose( const int iID, const VAVec3& v3Pos, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		CVAMotionState::CVAPose oNewPose;
    		oNewPose.vPos = v3Pos;
    		oNewPose.qOrient = qOrient;
    		pNewMotionState->SetRealWorldPose( oNewPose );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    
    	}
    	VA_RETHROW;
    }
    
    VAQuat CVACoreImpl::GetSoundReceiverRealWorldHeadAboveTorsoOrientation( const int iID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		CVASceneState* pHeadState = m_pSceneManager->GetHeadSceneState();
    		const CVAReceiverState* pListenerState = pHeadState->GetReceiverState( iID );
    
    		if( !pListenerState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    
    		const CVAMotionState* pMotionState = pListenerState->GetMotionState();
    		if( !pMotionState )
    			VA_EXCEPT2( INVALID_PARAMETER, "Sound receiver has invalid motion state, probably it has not been positioned, yet?" );
    
    		return pMotionState->GetRealWorldHeadAboveTorsoOrientation();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundReceiverRealWorldHeadAboveTorsoOrientation( const int iID, const VAQuat& qOrient )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		const bool bSync = GetUpdateLocked();
    		if( !bSync )
    			LockUpdate();
    
    		CVAReceiverState* pListenerState = m_pNewSceneState->AlterListenerState( iID );
    
    		if( !pListenerState )
    		{
    			if( !bSync )
    				UnlockUpdate();
    			VA_EXCEPT2( INVALID_PARAMETER, "Invalid sound receiver ID" );
    		}
    
    		CVAMotionState* pNewMotionState = pListenerState->AlterMotionState();
    		pNewMotionState->SetRealWorldHeadAboveTorsoOrientation( qOrient );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_RECEIVER_CHANGED_POSE;
    		ev.pSender = this;
    		ev.iObjectID = iID;
    		SetCoreEventParams( ev, pNewMotionState );
    		m_pEventManager->EnqueueEvent( ev );
    
    		if( !bSync )
    			UnlockUpdate();
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetHomogeneousMediumSoundSpeed( const double dSoundSpeed )
    {
    	VA_NO_REENTRANCE;
    	VA_TRY
    	{
    		if( dSoundSpeed <= 0.0f )
    		VA_EXCEPT2( INVALID_PARAMETER, "Speed of sound can not be zero or negative" );
    		oHomogeneousMedium.dSoundSpeed = dSoundSpeed;
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetHomogeneousMediumSoundSpeed() const
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.dSoundSpeed;
    }
    
    void CVACoreImpl::SetHomogeneousMediumTemperature( const double dDegreesCentigrade )
    {
    	VA_NO_REENTRANCE;
    	VA_TRY
    	{
    		if( dDegreesCentigrade <= -270.0f )
    		VA_EXCEPT2( INVALID_PARAMETER, "Temperature can not be below total zero" );
    		oHomogeneousMedium.dTemperatureDegreeCentigrade = dDegreesCentigrade;
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetHomogeneousMediumTemperature() const
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.dTemperatureDegreeCentigrade;
    }
    
    void CVACoreImpl::SetHomogeneousMediumStaticPressure( const double dPressurePascal )
    {
    	VA_NO_REENTRANCE;
    	VA_TRY
    	{
    		if( dPressurePascal <= 0.0f )
    		VA_EXCEPT2( INVALID_PARAMETER, "Static pressure can not be zero or negative" );
    		oHomogeneousMedium.dStaticPressurePascal = dPressurePascal;
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetHomogeneousMediumStaticPressure() const
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.dStaticPressurePascal;
    }
    
    void CVACoreImpl::SetHomogeneousMediumRelativeHumidity( const double dRelativeHumidityPercent )
    {
    	VA_NO_REENTRANCE;
    	VA_TRY
    	{
    		if( dRelativeHumidityPercent < 0.0f )
    		VA_EXCEPT2( INVALID_PARAMETER, "Relative humidity can not be negative" );
    		oHomogeneousMedium.dRelativeHumidityPercent = dRelativeHumidityPercent;
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetHomogeneousMediumRelativeHumidity()
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.dRelativeHumidityPercent;
    }
    
    void CVACoreImpl::SetHomogeneousMediumShiftSpeed( const VAVec3& v3TranslationSpeed )
    {
    	VA_NO_REENTRANCE;
    	VA_TRY
    	{
    		if( v3TranslationSpeed.Length() >= oHomogeneousMedium.dSoundSpeed )
    		VA_EXCEPT2( INVALID_PARAMETER, "Medium shift can not be equal or faster than sound speed" );
    		oHomogeneousMedium.v3ShiftSpeed = v3TranslationSpeed;
    	}
    	VA_RETHROW;
    }
    
    VAVec3 CVACoreImpl::GetHomogeneousMediumShiftSpeed() const
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.v3ShiftSpeed;
    }
    
    void CVACoreImpl::SetHomogeneousMediumParameters( const CVAStruct& oParams )
    {
    	VA_NO_REENTRANCE;
    	oHomogeneousMedium.oParameters = oParams;
    }
    
    CVAStruct CVACoreImpl::GetHomogeneousMediumParameters( const CVAStruct& oArgs )
    {
    	VA_NO_REENTRANCE;
    	return oHomogeneousMedium.oParameters;
    }
    
    std::string CVACoreImpl::CreateScene( const CVAStruct& oParams, const std::string& sSceneName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( oParams.HasKey( "filepath" ) )
    		{
    			const std::string sFilePath = oParams[ "filepath" ];
    			VA_INFO( "Core", "Loading scene from file '" << sFilePath << "'" );
    			std::string sDestFilename = correctPath( m_oCoreConfig.mMacros.SubstituteMacros( sFilePath ) );
    			for( std::vector<CVAAudioRendererDesc>::iterator it = m_voRenderers.begin(); it != m_voRenderers.end(); ++it )
    				it->pInstance->LoadScene( sDestFilename );
    
    			// @todo: create a scene manager and return a proper scene identifier
    			return sDestFilename;
    		}
    		else
    		{
    			VA_EXCEPT2( INVALID_PARAMETER, "Could not interpret scene parameters, missing key 'filepath'" );
    		}
    	}
    	VA_RETHROW;
    }
    
    CVASceneInfo CVACoreImpl::GetSceneInfo( const std::string& sSceneID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    	}
    	VA_RETHROW;
    }
    
    bool CVACoreImpl::GetSceneEnabled( const std::string& sID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    	}
    	VA_RETHROW;
    }
    
    
    int CVACoreImpl::CreateSoundPortal( const std::string& sName /*= "" */ )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    	//m_pSceneManager->CreatePortalDesc()
    }
    
    void CVACoreImpl::GetSceneIDs( std::vector< std::string >& vsIDs ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    
    std::string CVACoreImpl::GetSceneName( const std::string& sID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSceneName( const std::string& sID, const std::string& sName )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSceneEnabled( const std::string& sID, const bool bEnabled /*= true */ )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::GetSoundPortalIDs( std::vector< int >& vPortalIDs )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->GetHeadSceneState()->GetPortalIDs( &vPortalIDs );
    	}
    	VA_RETHROW;
    }
    
    CVASoundPortalInfo CVACoreImpl::GetSoundPortalInfo( const int iID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    std::string CVACoreImpl::GetSoundPortalName( const int iPortalID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		return m_pSceneManager->GetPortalName( iPortalID );
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundPortalName( const int iPortalID, const std::string& sName )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		m_pSceneManager->SetPortalName( iPortalID, sName );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::SOUND_PORTAL_CHANGED_NAME;
    		ev.pSender = this;
    		ev.iObjectID = iPortalID;
    		ev.sName = sName;
    		m_pEventManager->BroadcastEvent( ev );
    
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::SetSoundPortalMaterial( const int iSoundPortalID, const int iMaterialID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::GetSoundPortalMaterial( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalNextPortal( const int iSoundPortalID, const int iNextSoundPortalID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::GetSoundPortalNextPortal( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalSoundReceiver( const int iSoundPortalID, const int iSoundReceiverID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::GetSoundPortalSoundReceiver( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalSoundSource( const int iSoundPortalID, const int iSoundSourceID )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    int CVACoreImpl::GetSoundPortalSoundSource( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    bool CVACoreImpl::GetSoundPortalEnabled( const int iPortalID ) const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    	}
    	VA_RETHROW;
    }
    
    CVAStruct CVACoreImpl::GetSoundPortalParameters( const int iID, const CVAStruct& oArgs ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalParameters( const int iID, const CVAStruct& oParams )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalPosition( const int iSoundPortalID, const VAVec3& vPos )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    VAVec3 CVACoreImpl::GetSoundPortalPosition( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalOrientation( const int iSoundPortalID, const VAQuat& qOrient )
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    VAQuat CVACoreImpl::GetSoundPortalOrientation( const int iSoundPortalID ) const
    {
    	VA_EXCEPT_NOT_IMPLEMENTED_FUTURE_VERSION;
    }
    
    void CVACoreImpl::SetSoundPortalEnabled( const int iID, const bool bEnabled )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		VA_EXCEPT_NOT_IMPLEMENTED_NEXT_VERSION;
    		//m_pSceneManager->SetPortalEnabled( iID, bEnabled );
    	}
    	VA_RETHROW;
    }
    
    bool CVACoreImpl::GetInputMuted() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_bInputMuted;
    }
    
    void CVACoreImpl::SetInputMuted( const bool bMuted )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( m_bInputMuted == bMuted )
    		return;
    
    		m_bInputMuted = bMuted;
    
    		if( m_pInputAmp )
    		{
    			if( m_bInputMuted )
    				m_pInputAmp->SetGain( 0.0f );
    			else
    				m_pInputAmp->SetGain( ( float ) m_dInputGain );
    		}
    
    		VA_INFO( "Core", "Input mute toggled" );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::INPUT_MUTING_CHANGED;
    		ev.pSender = this;
    		ev.bMuted = m_bInputMuted;
    		m_pEventManager->BroadcastEvent( ev );
    
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetInputGain() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_dInputGain;
    }
    
    void CVACoreImpl::SetInputGain( double dGain )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( !GetVolumeValid( dGain ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid gain" );
    
    		if( m_dInputGain == dGain )
    			return;
    		m_dInputGain = dGain;
    
    		if( m_pInputAmp )
    		{
    			if( m_bInputMuted )
    				m_pInputAmp->SetGain( 0 );
    			else
    				m_pInputAmp->SetGain( ( float ) dGain );
    		}
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::INPUT_GAIN_CHANGED;
    		ev.pSender = this;
    		ev.dVolume = dGain;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_VERBOSE( "Core", "Set input gain = " << IVAInterface::GetVolumeStrDecibel( dGain ) );
    	}
    	VA_RETHROW;
    }
    
    double CVACoreImpl::GetOutputGain() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_dOutputGain;
    }
    
    void CVACoreImpl::SetOutputGain( const double dGain )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( !GetVolumeValid( dGain ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid gain" );
    
    		if( m_dOutputGain == dGain )
    			return;
    		m_dOutputGain = dGain;
    		if( m_pOutputPatchbay )
    		{
    			if( m_bOutputMuted )
    				m_pOutputPatchbay->SetOutputGain( 0, 0.0f );
    			else
    				m_pOutputPatchbay->SetOutputGain( 0, dGain );
    		}
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::OUTPUT_GAIN_CHANGED;
    		ev.pSender = this;
    		ev.dVolume = dGain;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_VERBOSE( "Core", "Set output gain = " << IVAInterface::GetVolumeStrDecibel( dGain ) );
    
    	}
    	VA_RETHROW;
    }
    
    bool CVACoreImpl::GetOutputMuted() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_bOutputMuted;
    }
    
    void CVACoreImpl::SetOutputMuted( const bool bMuted )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( m_bOutputMuted == bMuted )
    		return;
    		m_bOutputMuted = bMuted;
    		VA_INFO( "Core", "Output mute toggled" );
    
    		if( m_pOutputPatchbay )
    			m_pOutputPatchbay->SetOutputMuted( 0, bMuted );
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::OUTPUT_MUTING_CHANGED;
    		ev.pSender = this;
    		ev.bMuted = m_bOutputMuted;
    		m_pEventManager->BroadcastEvent( ev );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetGlobalAuralizationMode() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_iGlobalAuralizationMode;
    }
    
    void CVACoreImpl::SetGlobalAuralizationMode( const int iAuralizationMode )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( !GetAuralizationModeValid( iAuralizationMode ) )
    		VA_EXCEPT2( INVALID_PARAMETER, "Invalid auralization mode" );
    
    		if( m_iGlobalAuralizationMode == iAuralizationMode )
    		{
    			return;
    		}
    
    		m_iGlobalAuralizationMode = iAuralizationMode;
    
    		// Neuberechnung der Schallpfade triggern
    		m_pCoreThread->Trigger();
    
    		// Ereignis generieren
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::GLOBAL_AURALIZATION_MODE_CHANGED;
    		ev.pSender = this;
    		ev.iAuralizationMode = iAuralizationMode;
    		m_pEventManager->BroadcastEvent( ev );
    
    		VA_VERBOSE( "Core", "Set global auralization mode = " << IVAInterface::GetAuralizationModeStr( iAuralizationMode, true ) );
    	}
    	VA_RETHROW;
    }
    
    int CVACoreImpl::GetActiveSoundReceiver() const
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	return m_iCurActiveSoundReceiver;
    }
    
    void CVACoreImpl::SetActiveSoundReceiver( const int iListenerID )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	bool bSync = false;
    
    	VA_TRY
    	{
    		LockUpdate();
    		bSync = true;
    
    		// Prfen, ob Hrer in der aktuellen Konfig existiert.
    		if( !m_pNewSceneState->GetReceiverState( iListenerID ) )
    			VA_EXCEPT2( INVALID_PARAMETER, "Listener does not existing in head configuration" );
    		/* TODO: Auch -1 erlauben um Hrer zu entfernen
    		if (iListenerID != -1) {
    		if (!m_pNewSceneState->GetListenerState(iListenerID))
    		VA_EXCEPT2(INVALID_PARAMETER, "Listener does not existing in head configuration");
    		}
    		*/
    
    		if( iListenerID != m_iUpdActiveSoundReceiver )
    		{
    			m_iUpdActiveSoundReceiver = iListenerID;
    			m_iCurActiveSoundReceiver = iListenerID;
    
    			// Ereignis generieren
    			CVAEvent ev;
    			ev.iEventType = CVAEvent::ACTIVE_SOUND_RECEIVER_CHANGED;
    			ev.pSender = this;
    			ev.iObjectID = iListenerID;
    			m_pEventManager->EnqueueEvent( ev );
    
    			VA_VERBOSE( "Core", "Set sound receiver " << iListenerID << " the active receiver" );
    		}
    
    		bSync = false;
    		UnlockUpdate();
    
    	}
    		VA_FINALLY
    	{
    		if( bSync ) UnlockUpdate();
    		throw;
    	}
    }
    
    double CVACoreImpl::GetCoreClock() const
    {
    	// Clock ist immer da, reentrance hier erlaubt
    	double dNow = m_pClock->getTime();
    	double dOffset = ( double ) m_fCoreClockOffset;
    	return ( dNow - dOffset );
    }
    
    void CVACoreImpl::SetCoreClock( const double dSeconds )
    {
    	VA_NO_REENTRANCE;
    	VA_CHECK_INITIALIZED;
    
    	VA_TRY
    	{
    		if( dSeconds < 0 )
    		VA_EXCEPT2( INVALID_PARAMETER, "Time must not be negative" );
    
    		// Aktuelle Zeit holen
    		double dNow = m_pClock->getTime();
    		double dOffset = dSeconds - dNow;
    
    		// TODO: Sollte eigentlich ber doubles gehen. Leider noch keine AtomicDoubles...
    		m_fCoreClockOffset = ( float ) dOffset;
    
    		VA_VERBOSE( "Core", "Set clock to " << timeToString( dSeconds ) );
    
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::SubstituteMacros( const std::string& sStr ) const
    {
    	VA_TRY
    	{
    		return m_oCoreConfig.mMacros.SubstituteMacros( sStr );
    	}
    	VA_RETHROW;
    }
    
    std::string CVACoreImpl::FindFilePath( const std::string& sRelativeFilePath ) const
    {
    	VA_TRY
    	{
    		std::string sRelativeFilePathSubstituted = SubstituteMacros( sRelativeFilePath );
    		VistaFileSystemFile oFile( sRelativeFilePathSubstituted );
    		if( oFile.Exists() && oFile.IsFile() )
    			return sRelativeFilePathSubstituted;
    
    		// Search with paths list
    		std::string sFinalPathWithSearch;
    		for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
    		{
    			const std::string& sSearchPath( m_oCoreConfig.vsSearchPaths[ i ] );
    			std::string sCombinedFilePath = correctPath( sSearchPath + PATH_SEPARATOR + sRelativeFilePathSubstituted );
    			VistaFileSystemFile oFile( sCombinedFilePath );
    			VA_TRACE( "Core:FindFilePath", "Searching in directory '" + sSearchPath + "' for file '" + sRelativeFilePathSubstituted + "'" );
    			if( oFile.Exists() && oFile.IsFile() )
    			{
    				if( sFinalPathWithSearch.empty() )
    				{
    					sFinalPathWithSearch = sCombinedFilePath;
    				}
    				else
    				{
    					VA_WARN( "Core", "Found ambiguous file path '" + sCombinedFilePath + "' (skipped), using first path '" + sFinalPathWithSearch + "'" );
    				}
    			}
    
    		}
    		return sFinalPathWithSearch;
    	}
    	VA_RETHROW;
    }
    
    void CVACoreImpl::InitializeAudioDriver()
    {
    #ifdef VACORE_WITH_AUDIO_BACKEND_ASIO
    	if( m_oCoreConfig.oAudioDriverConfig.sDriver == "ASIO" )
    		m_pAudioDriverBackend = new CVAASIOBackend( &m_oCoreConfig.oAudioDriverConfig );
    #endif
    #ifdef VACORE_WITH_AUDIO_BACKEND_PORTAUDIO
    	if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Portaudio" )
    		m_pAudioDriverBackend = new CVAPortaudioBackend( &m_oCoreConfig.oAudioDriverConfig );
    #endif
    #ifdef VACORE_WITH_AUDIO_BACKEND_VIRTUAL
    	if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Virtual" )
    	{
    
    		if( m_oCoreConfig.oAudioDriverConfig.iBuffersize == -1 )
    			VA_EXCEPT2( INVALID_PARAMETER, "For a virtual audio device, the buffer size has to be set (AUTO detect not possible)" );
    
    		if( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == -1 )
    			VA_EXCEPT2( INVALID_PARAMETER, "For a virtual audio device, the output channel number has to be set (AUTO detect not possible)" );
    
    		m_oCoreConfig.oAudioDriverConfig.iInputChannels = 0; // not allowed, override
    
    		CVAVirtualAudioDriverBackend* pAudioDriverBackend = new CVAVirtualAudioDriverBackend( &m_oCoreConfig.oAudioDriverConfig );
    		RegisterModule( pAudioDriverBackend );
    		m_pAudioDriverBackend = pAudioDriverBackend;
    
    		// Overwride default block pointer by manual clock
    		CVAVirtualAudioDriverBackend::ManualClock* pManualClock = new CVAVirtualAudioDriverBackend::ManualClock();
    		RegisterModule( pManualClock );
    		m_pClock = pManualClock;
    	}
    #else
    #endif
    
    	if( m_pAudioDriverBackend == nullptr )
    		VA_EXCEPT2( INVALID_PARAMETER, "Unkown, uninitializable or unsupported audio driver backend '" + m_oCoreConfig.oAudioDriverConfig.sDriver + "'" );
    
    	try
    	{
    		VA_INFO( "Core", "Initializing audio device '" << m_pAudioDriverBackend->getDeviceName() << "' using '" << m_pAudioDriverBackend->getDriverName() << "' driver" );
    
    		VA_TRACE( "Core", "Desired settings: sampling rate " << m_oCoreConfig.oAudioDriverConfig.dSampleRate << " Hz, " <<
    			( m_oCoreConfig.oAudioDriverConfig.iInputChannels == CVAAudioDriverConfig::AUTO ? "all" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iInputChannels ) ) << " inputs, " <<
    			( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == CVAAudioDriverConfig::AUTO ? "all" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ) ) << " outputs, " <<
    			"buffer size = " << ( m_oCoreConfig.oAudioDriverConfig.iBuffersize == 0 ? "auto" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iBuffersize ) ) );
    
    		m_pAudioDriverBackend->initialize();
    
    		m_oCoreConfig.oAudioDriverConfig.dSampleRate = m_pAudioDriverBackend->getOutputStreamProperties()->dSamplerate;
    		m_oCoreConfig.oAudioDriverConfig.iInputChannels = m_pAudioDriverBackend->getNumberOfInputs();
    		m_oCoreConfig.oAudioDriverConfig.iOutputChannels = m_pAudioDriverBackend->getOutputStreamProperties()->uiChannels;
    		m_oCoreConfig.oAudioDriverConfig.iBuffersize = m_pAudioDriverBackend->getOutputStreamProperties()->uiBlocklength;
    
    		VA_INFO( "Core", "Streaming at " << std::fixed << std::setw( 3 ) << std::setprecision( 1 ) << ( m_oCoreConfig.oAudioDriverConfig.dSampleRate / 1000.0f ) << " kHz on " <<
    			( m_oCoreConfig.oAudioDriverConfig.iInputChannels == 0 ? "no" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iInputChannels ) ) << " inputs and " <<
    			( m_oCoreConfig.oAudioDriverConfig.iOutputChannels == 0 ? "no" : std::to_string( m_oCoreConfig.oAudioDriverConfig.iOutputChannels ) ) <<
    			" outputs with a buffer size of " << m_oCoreConfig.oAudioDriverConfig.iBuffersize << " samples." );
    
    	}
    	catch( ... )
    	{
    		m_pAudioDriverBackend->finalize();
    
    		delete m_pAudioDriverBackend;
    		m_pAudioDriverBackend = nullptr;
    
    		throw;
    	}
    }
    
    void CVACoreImpl::FinalizeAudioDriver()
    {
    	if( m_pAudioDriverBackend )
    	{
    		VA_INFO( "Core", "Finalizing audio device \"" << m_oCoreConfig.oAudioDriverConfig.sDevice <<
    			"\" [" << m_oCoreConfig.oAudioDriverConfig.sDriver << "]" );
    
    		m_pAudioDriverBackend->finalize();
    		delete m_pAudioDriverBackend;
    		m_pAudioDriverBackend = nullptr;
    	}
    }
    
    void CVACoreImpl::FinalizeRenderingModules()
    {
    	for( size_t i = 0; i < m_voRenderers.size(); i++ )
    	{
    		m_voRenderers[ i ].Finalize();
    	}
    }
    
    void CVACoreImpl::FinalizeReproductionModules()
    {
    	for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
    	{
    		m_voReproductionModules[ i ].Finalize();
    	}
    }
    
    bool CVACoreImpl::IsStreaming() const
    {
    	return ( m_pAudioDriverBackend ? m_pAudioDriverBackend->isStreaming() : false );
    }
    
    void CVACoreImpl::InitializeAudioRenderers()
    {
    	CVAAudioRendererRegistry* pRegistry( CVAAudioRendererRegistry::GetInstance() );
    	const CVAStruct& oConfig( GetCoreConfig()->GetStruct() );
    
    	// Parse config for audio renderers and try to instantiate them
    	CVAStruct::const_iterator cit = oConfig.Begin();
    	while( cit != oConfig.End() )
    	{
    		const std::string& sKey( cit->first );
    		const CVAStruct& oArgs( cit->second );
    
    		std::vector< std::string > vsKeyParts = splitString( sKey, ':' );
    		if( vsKeyParts.size() == 2 && cit->second.GetDatatype() == CVAStructValue::STRUCT )
    		{
    			std::string sCategory( toUppercase( vsKeyParts[ 0 ] ) );
    			std::string sID( vsKeyParts[ 1 ] );
    
    			if( sCategory == "RENDERER" )
    			{
    				CVAConfigInterpreter conf( oArgs );
    				conf.SetErrorPrefix( "Configuration error in section \"" + cit->first + "\"" );
    				std::string sClass;
    				conf.ReqString( "Class", sClass );
    
    				bool bEnabled;
    				conf.OptBool( "Enabled", bEnabled, true );
    				if( !bEnabled )
    				{
    					cit++;
    					continue; // Skip
    				}
    
    				// Initialization parameters
    				CVAAudioRendererInitParams oParams;
    				oParams.sID = sID;
    				oParams.sClass = sClass;
    				oParams.pCore = this;
    				oParams.pConfig = &cit->second.GetStruct();
    				oParams.bOfflineRendering = ( m_oCoreConfig.oAudioDriverConfig.sDriver == "Virtual" ) ? true : false;
    
    				conf.ReqStringListRegex( "Reproductions", oParams.vsReproductions, "\\s*,\\s*" );
    				std::unique( oParams.vsReproductions.begin(), oParams.vsReproductions.end() );
    
    				conf.OptBool( "OutputDetectorEnabled", oParams.bOutputLevelMeterEnabled, false );
    
    				conf.OptBool( "RecordOutputEnabled", oParams.bRecordOutputEnabled, false );
    				if( oParams.bRecordOutputEnabled )
    				{
    					std::string sFilePathRAW;
    					conf.ReqString( "RecordOutputFilePath", sFilePathRAW );
    					oParams.sRecordOutputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAW );
    				}
    
    				// Get factory method to create requested rendering module (if available from registry)
    				IVAAudioRendererFactory* pFactory = pRegistry->FindFactory( sClass );
    				if( !pFactory )
    					conf.Error( "Unknown class \"" + sClass + "\"" );
    
    				IVAAudioRenderer* pRenderer = pFactory->Create( oParams );
    				// TODO: Active umsetzen
    
    				CVAAudioRendererDesc oRendererDesc( pRenderer );
    				oRendererDesc.sID = sID;
    				oRendererDesc.sClass = sClass;
    				oRendererDesc.bEnabled = bEnabled;
    
    				ITADatasource* pRendererOutputTail = pRenderer->GetOutputDatasource();;
    				if( oParams.bRecordOutputEnabled )
    				{
    					oRendererDesc.pOutputRecorder = new ITAStreamProbe( pRendererOutputTail, oParams.sRecordOutputFilePath );
    					pRendererOutputTail = oRendererDesc.pOutputRecorder;
    				}
    
    				if( oParams.bOutputLevelMeterEnabled )
    				{
    					oRendererDesc.pOutputDetector = new ITAStreamDetector( pRendererOutputTail );
    					pRendererOutputTail = oRendererDesc.pOutputDetector;
    				}
    
    				// Setup the intermediate patchbay input [temporary]
    				int iInput = m_pR2RPatchbay->AddInput( pRendererOutputTail );
    
    				// Create direct output in output patchbay for each output group [todo, not allowed yet]
    				for( size_t i = 0; i < oParams.vsReproductions.size(); i++ )
    				{
    					const std::string& sOutputID( oParams.vsReproductions[ i ] );
    
    					const CVAHardwareOutput* pOutput = m_oCoreConfig.oHardwareSetup.GetOutput( sOutputID );
    					if( pOutput )
    					{
    						// Output found, use direct out (no renderer)
    						VA_EXCEPT2( NOT_IMPLEMENTED, "Direct output to an audio hardware group is currently not supported. Use the Talkthrough reproduction module instead." );
    					}
    				}
    
    				oRendererDesc.iR2RPatchBayInput = iInput;
    				oRendererDesc.vsOutputs = oParams.vsReproductions;
    				m_voRenderers.push_back( oRendererDesc );
    			}
    		}
    		cit++;
    	}
    
    	const size_t nNumRenderingModules = m_voRenderers.size();
    	if( nNumRenderingModules == 1 )
    	{
    		VA_INFO( "Core", "Started one rendering module" );
    	}
    	else
    	{
    		VA_INFO( "Core", "Started " << nNumRenderingModules << " rendering modules" );
    	}
    
    	for( size_t i = 0; i < nNumRenderingModules; i++ )
    	{
    		std::string sReproductionFeedStr = ( m_voRenderers[ i ].vsOutputs.size() == 1 ) ? "one reproduction module." : std::to_string( long( m_voRenderers[ i ].vsOutputs.size() ) ) + " reproduction modules.";
    		VA_INFO( "Core", "    +    " << m_voRenderers[ i ].sID << " (" << m_voRenderers[ i ].sClass << ") feeding " << sReproductionFeedStr );
    	}
    }
    
    void CVACoreImpl::InitializeReproductionModules()
    {
    	CVAAudioReproductionRegistry* pRegistry( CVAAudioReproductionRegistry::GetInstance() );
    	const CVAStruct& oConfig( GetCoreConfig()->GetStruct() );
    
    	// Parse config for reproduction modules and try to instantiate them
    	CVAStruct::const_iterator cit = oConfig.Begin();
    	while( cit != oConfig.End() )
    	{
    		const std::string& sKey( cit->first );
    		const CVAStruct& oArgs( cit->second );
    
    		std::vector< std::string > vsKeyParts = splitString( sKey, ':' );
    		if( vsKeyParts.size() == 2 && cit->second.GetDatatype() == CVAStructValue::STRUCT )
    		{
    			std::string sCategory( toUppercase( vsKeyParts[ 0 ] ) );
    
    			if( sCategory == "REPRODUCTION" )
    			{
    				CVAConfigInterpreter conf( oArgs );
    				conf.SetErrorPrefix( "Configuration error in section \"" + cit->first + "\"" );
    
    				// Initialization parameters
    				CVAAudioReproductionInitParams oParams;
    				oParams.pCore = this;
    				oParams.pConfig = &cit->second.GetStruct();
    
    				oParams.sID = vsKeyParts[ 1 ];
    				conf.ReqString( "Class", oParams.sClass );
    
    				bool bEnabled;
    				conf.OptBool( "Enabled", bEnabled, true );
    				if( !bEnabled )
    				{
    					cit++;
    					continue; // Skip this entry
    				}
    
    				conf.OptBool( "InputDetectorEnabled", oParams.bInputDetectorEnabled, false );
    				conf.OptBool( "OutputDetectorEnabled", oParams.bOutputDetectorEnabled, false );
    
    				conf.OptBool( "RecordInputEnabled", oParams.bRecordInputEnabled, false );
    				if( oParams.bRecordInputEnabled )
    				{
    					std::string sFilePathRAW;
    					conf.ReqString( "RecordInputFilePath", sFilePathRAW );
    					oParams.sRecordInputInputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAW );
    				}
    
    				conf.OptBool( "RecordOutputEnabled", oParams.bRecordOutputEnabled, false );
    				if( oParams.bRecordOutputEnabled )
    				{
    					std::string sFilePathRAW;
    					conf.ReqString( "RecordOutputFilePath", sFilePathRAW );
    					oParams.sRecordOutputInputFilePath = m_oCoreConfig.mMacros.SubstituteMacros( sFilePathRAW );
    				}
    
    				// Parse outputs
    				std::vector< std::string > vsOutputs;
    				conf.ReqStringListRegex( "Outputs", vsOutputs, "\\s*,\\s*" );
    				std::unique( vsOutputs.begin(), vsOutputs.end() ); // Uniqueness, baby!
    
    				// Check outputs in hardware setup
    				std::vector< std::string >::const_iterator cjt = vsOutputs.begin();
    				while( cjt != vsOutputs.end() )
    				{
    					const std::string& sOutput( *cjt );
    					const CVAHardwareOutput* pOutput = m_oCoreConfig.oHardwareSetup.GetOutput( sOutput );
    					if( pOutput == nullptr )
    						conf.Error( "Referring to unknown output \"" + sOutput + "\"" );
    					oParams.vpOutputs.push_back( pOutput );
    					cjt++;
    				}
    
    				// Register this reproduction module
    				IVAAudioReproductionFactory* pFactory = pRegistry->FindFactory( oParams.sClass );
    				if( !pFactory )
    					conf.Error( "Unknown class \"" + oParams.sClass + "\"" );
    
    				// Create the module
    				CVAAudioReproductionModuleDesc oDesc( pFactory->Create( oParams ) );
    				oDesc.sID = oParams.sID;
    				oDesc.sClass = oParams.sClass;
    				oDesc.vpOutputs = oParams.vpOutputs;
    				oDesc.bEnabled = bEnabled;
    
    				// Add output in Renderer-to-Reproduction patch bay
    				int iReproductionModuleNumInputChannels = oDesc.pInstance->GetNumInputChannels();
    				oDesc.iR2RPatchBayOutput = m_pR2RPatchbay->AddOutput( iReproductionModuleNumInputChannels );
    
    				ITADatasource* pInputTail = m_pR2RPatchbay->GetOutputDatasource( oDesc.iR2RPatchBayOutput );
    				if( oParams.bInputDetectorEnabled )
    				{
    					oDesc.pInputDetector = new ITAStreamDetector( pInputTail );
    					pInputTail = oDesc.pInputDetector;
    				}
    				if( oParams.bRecordInputEnabled )
    				{
    					oDesc.pInputRecorder = new ITAStreamProbe( pInputTail, oParams.sRecordInputInputFilePath );
    					pInputTail = oDesc.pInputRecorder;
    				}
    
    				// Assign Renderer-to-Reproduction patch bay output datasource as input for reproduction module
    				oDesc.pInstance->SetInputDatasource( pInputTail );
    
    
    				ITADatasource* pOutputTail = oDesc.pInstance->GetOutputDatasource();
    				if( oParams.bOutputDetectorEnabled )
    				{
    					oDesc.pOutputDetector = new ITAStreamDetector( pOutputTail );
    					pOutputTail = oDesc.pOutputDetector;
    				}
    				if( oParams.bRecordOutputEnabled )
    				{
    					oDesc.pOutputRecorder = new ITAStreamProbe( pOutputTail, oParams.sRecordOutputInputFilePath );
    					pOutputTail = oDesc.pOutputRecorder;
    				}
    
    				// Add input in output patch bay and assign reproduction module datasource output to this input
    				oDesc.iOutputPatchBayInput = m_pOutputPatchbay->AddInput( pOutputTail );
    
    				// TODO: Active umsetzen ggf. in Params rein
    				m_voReproductionModules.push_back( oDesc );
    			}
    		}
    		cit++;
    	}
    
    	const size_t nNumReproductionModules = m_voReproductionModules.size();
    	if( nNumReproductionModules == 1 )
    	{
    		VA_INFO( "Core", "Started one reproduction module" );
    	}
    	else
    	{
    		VA_INFO( "Core", "Started " << nNumReproductionModules << " reproduction modules" );
    	}
    
    	for( size_t i = 0; i < nNumReproductionModules; i++ )
    	{
    		std::string sOutputGroupFeedStr = ( m_voReproductionModules[ i ].vpOutputs.size() == 1 ) ? "one output group." : std::to_string( long( m_voReproductionModules[ i ].vpOutputs.size() ) ) + " output groups.";
    		VA_INFO( "Core", "    +    " << m_voReproductionModules[ i ].sID << " (" << m_voReproductionModules[ i ].sClass << ") feeding " << sOutputGroupFeedStr );
    	}
    
    	return;
    }
    
    void CVACoreImpl::PatchRendererToReproductionModules()
    {
    	std::vector<CVAAudioRendererDesc>::iterator rendit = m_voRenderers.begin();
    	while( rendit != m_voRenderers.end() )
    	{
    		const CVAAudioRendererDesc& renddesc( *rendit );
    		int iRendererNumOutputChannels = renddesc.pInstance->GetOutputDatasource()->GetNumberOfChannels();
    		int iRendererR2RPatchBayInput = renddesc.iR2RPatchBayInput;
    
    		// Iterate over all target reproduction modules
    		std::vector< std::string >::const_iterator ocit = renddesc.vsOutputs.begin();
    		while( ocit != renddesc.vsOutputs.end() )
    		{
    			const std::string& sTargetReproductionModule( *ocit );
    
    			std::vector< CVAAudioReproductionModuleDesc >::const_iterator repcit = m_voReproductionModules.begin();
    			while( repcit != m_voReproductionModules.end() )
    			{
    				const CVAAudioReproductionModuleDesc& repdesc( *repcit );
    				if( repdesc.sID == sTargetReproductionModule )
    				{
    					// Get R2R patch bay output of target reproduction module and patch channels from renderer input
    					for( int k = 0; k < iRendererNumOutputChannels; k++ )
    						m_pR2RPatchbay->ConnectChannels( iRendererR2RPatchBayInput, k, repdesc.iR2RPatchBayOutput, k );
    
    					break; // break after target reproduction module is patched and continue with next
    				}
    				repcit++;
    			}
    			ocit++;
    		}
    		rendit++;
    	}
    
    	return;
    }
    
    void CVACoreImpl::PatchReproductionModulesToOutput()
    {
    	int iMaxPhysicalChannelsAvailable = m_pOutputPatchbay->GetOutputNumChannels( 0 );
    
    	std::vector<CVAAudioReproductionModuleDesc>::iterator it = m_voReproductionModules.begin();
    	while( it != m_voReproductionModules.end() )
    	{
    		CVAAudioReproductionModuleDesc& oRepDesc( *it );
    
    		std::vector< const CVAHardwareOutput* >::iterator jt = oRepDesc.vpOutputs.begin();
    		while( jt != oRepDesc.vpOutputs.end() )
    		{
    			const CVAHardwareOutput* pOutput( *jt );
    
    			// Only consider outputs for patching, that are set enabled via configuration
    			if( pOutput->IsEnabled() == false )
    			{
    				jt++;
    				continue;
    			}
    
    			for( size_t k = 0; k < pOutput->GetPhysicalOutputChannels().size(); k++ )
    			{
    				int iPhysicalOutputChannel = pOutput->GetPhysicalOutputChannels()[ k ] - 1;
    				if( iPhysicalOutputChannel < iMaxPhysicalChannelsAvailable )
    					m_pOutputPatchbay->ConnectChannels( oRepDesc.iOutputPatchBayInput, int( k ), 0, iPhysicalOutputChannel );
    				else
    					VA_EXCEPT2( INVALID_PARAMETER, "VACore/ConnectRendererWithReproductionModules: Group '" +
    					pOutput->sIdentifier + "' output channel out of range for this sound card" );
    			}
    			jt++;
    		}
    		it++;
    	}
    
    	return;
    }
    
    
    void CVACoreImpl::RecursiveFileList( const std::string& sBasePath, CVAStruct& oFileList, const std::string sFileSuffixMask ) const
    {
    	std::vector< std::string > vsFileList;
    	FileList( sBasePath, vsFileList, sFileSuffixMask );
    
    	CVAStruct oMoreFiles;
    	for( size_t j = 0; j < vsFileList.size(); j++ )
    		oMoreFiles[ std::to_string( long( j ) ) ] = vsFileList[ j ];
    
    	oFileList[ sBasePath ] = oMoreFiles;
    
    	std::vector< std::string > vsFolderList;
    	FolderList( sBasePath, vsFolderList );
    
    	for( size_t j = 0; j < vsFolderList.size(); j++ )
    		RecursiveFileList( vsFolderList[ j ], oFileList, sFileSuffixMask );
    }
    
    void CVACoreImpl::FolderList( const std::string& sBasePath, std::vector< std::string >& vsFolderList ) const
    {
    	vsFolderList.clear();
    
    	VistaFileSystemDirectory oFolder( sBasePath );
    	if( !oFolder.Exists() || !oFolder.IsDirectory() )
    		return;
    
    	VistaFileSystemDirectory::const_iterator cit = oFolder.begin();
    	while( cit != oFolder.end() )
    	{
    		VistaFileSystemNode* pNode( *cit++ );
    		if( pNode->IsDirectory() && pNode->GetLocalName() != "." && pNode->GetLocalName() != ".." )
    			vsFolderList.push_back( pNode->GetName() );
    	}
    }
    
    void CVACoreImpl::FileList( const std::string& sBasePath, std::vector< std::string >& vsFileList, const std::string& sFileSuffixMask ) const
    {
    	vsFileList.clear();
    
    	VistaFileSystemDirectory oFolder( sBasePath );
    	if( !oFolder.Exists() || !oFolder.IsDirectory() )
    		return;
    
    	VistaFileSystemDirectory::const_iterator cit = oFolder.begin();
    	while( cit != oFolder.end() )
    	{
    		VistaFileSystemNode* pNode( *cit++ );
    		if( pNode->IsFile() )
    		{
    			const std::string sFileName = pNode->GetLocalName();
    			if( sFileSuffixMask != "*" && !sFileSuffixMask.empty() )
    			{
    				if( sFileName.substr( sFileName.find_last_of( "." ) + 1 ).compare( sFileSuffixMask ) )
    					vsFileList.push_back( pNode->GetName() );
    			}
    			else
    				vsFileList.push_back( pNode->GetName() );
    		}
    	}
    }
    
    // --= Progress =---------------------------------------------------
    
    ITACriticalSection m_csProgress;
    CVAProgress m_Progress;
    
    void CVACoreImpl::InitProgress( const std::string& sAction, const std::string& sSubaction, const int iMaxStep )
    {
    	m_csProgress.enter();
    
    	m_Progress.sAction = sAction;
    	m_Progress.sSubaction = sSubaction;
    	m_Progress.iCurrentStep = 0;
    	m_Progress.iMaxStep = iMaxStep;
    
    	// Fortschritts-Ereignis senden
    	CVAEvent ev;
    	ev.iEventType = CVAEvent::PROGRESS_UPDATE;
    	ev.pSender = this;
    	ev.oProgress = m_Progress;
    	m_pEventManager->BroadcastEvent( ev );
    
    	m_csProgress.leave();
    }
    
    void CVACoreImpl::SetProgress( const std::string& sAction, const std::string& sSubaction, const int iCurrentStep )
    {
    	m_csProgress.enter();
    
    	m_Progress.sAction = sAction;
    	m_Progress.sSubaction = sSubaction;
    	m_Progress.iCurrentStep = iCurrentStep;
    
    	// Fortschritts-Ereignis senden
    	CVAEvent ev;
    	ev.iEventType = CVAEvent::PROGRESS_UPDATE;
    	ev.pSender = this;
    	ev.oProgress = m_Progress;
    	m_pEventManager->BroadcastEvent( ev );
    
    	m_csProgress.leave();
    }
    
    void CVACoreImpl::FinishProgress()
    {
    	m_csProgress.enter();
    
    	// Die Aktionen bleiben, nur die aktuelle Schritt = maximaler Schritt
    	m_Progress.iCurrentStep = m_Progress.iMaxStep;
    
    	// Fortschritts-Ereignis senden
    	CVAEvent ev;
    	ev.iEventType = CVAEvent::PROGRESS_UPDATE;
    	ev.pSender = this;
    	ev.oProgress = m_Progress;
    	m_pEventManager->BroadcastEvent( ev );
    
    	m_csProgress.leave();
    }
    
    /* +----------------------------------------------------------+ *
     * |                                                          | *
     * |   Core-Thread                                            | *
     * |                                                          | *
     * +----------------------------------------------------------+ */
    
    void CVACoreImpl::CoreThreadLoop()
    {
    	m_oCoreThreadLoopTotalDuration.start();
    
    	assert( m_pCurSceneState != nullptr );
    	assert( m_pCurSceneState->GetNumReferences() >= 1 );
    
    	// Auf nderungen der Szene berprfen
    	CVASceneState* pNewSceneState = m_pSceneManager->GetHeadSceneState();
    
    	assert( pNewSceneState != nullptr );
    	assert( pNewSceneState->GetNumReferences() >= 1 );
    
    	pNewSceneState->AddReference();
    
    	// TODO: Aktiver Hrer wird erstmal ignoriert.
    	//int iNewActiveListener = m_iNewActiveListener;
    
    	if( pNewSceneState != m_pCurSceneState )
    	{
    		VA_TRACE( "CoreThread", "Update scene state " << m_pCurSceneState->GetID() << " -> " << pNewSceneState->GetID() );
    
    		// Audio renderer
    		std::vector< CVAAudioRendererDesc >::iterator rendit = m_voRenderers.begin();
    		while( rendit != m_voRenderers.end() )
    		{
    			CVAAudioRendererDesc& rendesc( *rendit );
    			rendesc.pInstance->UpdateScene( pNewSceneState );
    			rendit++;
    		}
    
    		// Audio reproduction modules
    		std::vector< CVAAudioReproductionModuleDesc >::iterator repit = m_voReproductionModules.begin();
    		while( repit != m_voReproductionModules.end() )
    		{
    			CVAAudioReproductionModuleDesc& repdesc( *repit );
    			repdesc.pInstance->UpdateScene( pNewSceneState );
    			repit++;
    		}
    	}
    
    
    	// nderung des globalen Auralisierungsmodus in den Schallpfaden bercksichtigen
    	/**
    	  * Da es keine Versionierung des AuraModes gibt, muss der Audio
    	  * Renderer selbst entscheiden, was zu tun ist.
    	  */
    	std::vector< CVAAudioRendererDesc >::iterator rendit = m_voRenderers.begin();
    	while( rendit != m_voRenderers.end() )
    	{
    		CVAAudioRendererDesc& rendesc( *rendit );
    		rendesc.pInstance->UpdateGlobalAuralizationMode( m_iGlobalAuralizationMode );
    
    		rendit++;
    	}
    
    	// Referenzen verwalten: Alter Szenezustand wird nun nicht mehr bentigt
    	if( m_pCurSceneState != pNewSceneState )
    	{
    		// Alter Zustand wird nicht mehr bentigt
    		m_pCurSceneState->RemoveReference();
    
    		// Aktuelle Szene ist nun die neu erzeugte (abgeleitete) Szene
    		m_pCurSceneState = pNewSceneState;
    	}
    	else
    	{
    		// Remove reference of new/current state again
    		pNewSceneState->RemoveReference();
    	}
    
    	m_oCoreThreadLoopTotalDuration.stop();
    
    	// @todo: signal event to process object calls (in-sync exec with internal core)
    
    	return;
    }
    
    void CVACoreImpl::SendAudioDeviceDetectorUpdateEvent()
    {
    	CVAEvent ev;
    	ev.iEventType = CVAEvent::MEASURES_UPDATE;
    	ev.pSender = this;
    
    	if( m_pInputStreamDetector )
    	{
    		ev.vfInputPeaks.resize( m_oCoreConfig.oAudioDriverConfig.iInputChannels );
    		m_pInputStreamDetector->GetPeaks( ev.vfInputPeaks, true );
    		ev.vfInputRMSs.resize( m_oCoreConfig.oAudioDriverConfig.iInputChannels );
    		m_pInputStreamDetector->GetRMSs( ev.vfInputRMSs, true );
    	}
    
    	if( m_pOutputStreamDetector )
    	{
    		ev.vfOutputPeaks.resize( m_oCoreConfig.oAudioDriverConfig.iOutputChannels );
    		m_pOutputStreamDetector->GetPeaks( ev.vfOutputPeaks, true );
    		ev.vfOutputRMSs.resize( m_oCoreConfig.oAudioDriverConfig.iOutputChannels );
    		m_pOutputStreamDetector->GetRMSs( ev.vfOutputRMSs, true );
    	}
    
    	ev.fSysLoad = 0;
    	// TODO: Sollte am Ende gemessen werden! => StreamTracker
    	ev.fDSPLoad = 0;
    	//ev.fDSPLoad = m_pAudiostreamProcessor->GetDSPLoad();
    
    	m_pEventManager->BroadcastEvent( ev );
    }
    
    void CVACoreImpl::SendRenderingModuleOutputDetectorsUpdateEvents()
    {
    	for( size_t i = 0; i < m_voRenderers.size(); i++ )
    	{
    		CVAAudioRendererDesc& oRenderer( m_voRenderers[ i ] );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::MEASURES_UPDATE;
    		ev.pSender = this;
    		ev.sObjectID = oRenderer.sID;
    		ev.sParam = "RenderingModule"; // Use generic parameter slot to mark rendering module source
    
    		if( oRenderer.pOutputDetector )
    		{
    			ev.vfOutputRMSs.resize( oRenderer.pOutputDetector->GetNumberOfChannels() );
    			oRenderer.pOutputDetector->GetRMSs( ev.vfOutputRMSs, true );
    			ev.vfOutputPeaks.resize( oRenderer.pOutputDetector->GetNumberOfChannels() );
    			oRenderer.pOutputDetector->GetPeaks( ev.vfOutputPeaks, true );
    		}
    
    		m_pEventManager->BroadcastEvent( ev );
    	}
    }
    
    void CVACoreImpl::SendReproductionModuleOIDetectorsUpdateEvents()
    {
    	for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
    	{
    		CVAAudioReproductionModuleDesc& oReproduction( m_voReproductionModules[ i ] );
    
    		CVAEvent ev;
    		ev.iEventType = CVAEvent::MEASURES_UPDATE;
    		ev.pSender = this;
    		ev.sObjectID = oReproduction.sID;
    		ev.sParam = "ReproductionModule"; // Use generic parameter slot to mark reproduction module source
    
    		if( oReproduction.pInputDetector )
    		{
    			ev.vfInputRMSs.resize( oReproduction.pInputDetector->GetNumberOfChannels() );
    			oReproduction.pInputDetector->GetRMSs( ev.vfInputRMSs, true );
    			ev.vfInputPeaks.resize( oReproduction.pInputDetector->GetNumberOfChannels() );
    			oReproduction.pInputDetector->GetPeaks( ev.vfInputPeaks, true );
    		}
    
    		if( oReproduction.pOutputDetector )
    		{
    			ev.vfOutputRMSs.resize( oReproduction.pOutputDetector->GetNumberOfChannels() );
    			oReproduction.pOutputDetector->GetRMSs( ev.vfOutputRMSs, true );
    			ev.vfOutputPeaks.resize( oReproduction.pOutputDetector->GetNumberOfChannels() );
    			oReproduction.pOutputDetector->GetPeaks( ev.vfOutputPeaks, true );
    		}
    
    		m_pEventManager->BroadcastEvent( ev );
    	}
    }
    
    bool CVACoreImpl::operator()()
    {
    #ifndef DO_NOT_SEND_MEASURE_UPDATE_EVENTS
    
    	// Audio device I/O detectors
    	SendAudioDeviceDetectorUpdateEvent();
    
    	// Rendering module output detectors
    	SendRenderingModuleOutputDetectorsUpdateEvents();
    
    	// Rerproduction module I/O detectors
    	SendReproductionModuleOIDetectorsUpdateEvents();
    
    	return true;
    #else
    	return false;
    #endif
    }
    
    CVAObjectInfo CVACoreImpl::GetObjectInfo() const
    {
    	CVAObjectInfo oCoreModuleInfo;
    	oCoreModuleInfo.iID = GetObjectID();
    	oCoreModuleInfo.sName = GetObjectName();
    	oCoreModuleInfo.sDesc = "VA core module";
    	return oCoreModuleInfo;
    }
    
    // Handle calls to the kernel from the module interface
    CVAStruct CVACoreImpl::CallObject( const CVAStruct& oArgs )
    {
    	VA_VERBOSE( "Core", "Core module has been called" );
    	CVAStruct oReturn;
    
    	if( oArgs.HasKey( "help" ) || oArgs.HasKey( "info" ) || oArgs.IsEmpty() )
    	{
    		oReturn[ "help" ] = "Get comprehensive help online at http://www.virtualacoustics.org ...";
    		oReturn[ "version" ] = "Returns version information";
    		oReturn[ "addsearchpath" ] = "Adds a search path";
    		oReturn[ "getsearchpaths" ] = "Returns all search paths";
    		oReturn[ "getloglevel" ] = "Returns current core log level (integer)";
    		oReturn[ "setloglevel" ] = "Sets current core log level (integer)";
    		oReturn[ "structrebound" ] = "Rebounds argument of any content to client (for testing VA structs)";
    	}
    
    	if( oArgs.HasKey( "version" ) )
    	{
    		CVAVersionInfo oVersionInfo;
    		GetVersionInfo( &oVersionInfo );
    		oReturn[ "comments" ] = oVersionInfo.sComments;
    		oReturn[ "date" ] = oVersionInfo.sDate;
    		oReturn[ "flags" ] = oVersionInfo.sFlags;
    		oReturn[ "version" ] = oVersionInfo.sVersion;
    		oReturn[ "string" ] = oVersionInfo.ToString();
    	}
    
    	if( oArgs.HasKey( "addsearchpath" ) )
    	{
    		if( oArgs[ "addsearchpath" ].IsString() )
    		{
    			std::string sPath = oArgs[ "addsearchpath" ];
    			VistaFileSystemDirectory oDir( sPath );
    			oReturn[ "pathvalid" ] = false;
    			if( oDir.Exists() )
    			{
    				m_oCoreConfig.vsSearchPaths.push_back( sPath );
    				oReturn[ "pathvalid" ] = true;
    			}
    		}
    	}
    
    	if( oArgs.HasKey( "getsearchpaths" ) )
    	{
    		CVAStruct oSearchPaths;
    		for( size_t i = 0; i < m_oCoreConfig.vsSearchPaths.size(); i++ )
    			oSearchPaths[ "path_" + std::to_string( long( i ) ) ] = m_oCoreConfig.vsSearchPaths[ i ];
    		oReturn[ "searchpaths" ] = oSearchPaths;
    	}
    
    	if( oArgs.HasKey( "getmacros" ) )
    	{
    		CVAStruct oMacros;
    		for( auto& macro : m_oCoreConfig.mMacros.GetMacroMapCopy() )
    			oMacros[ macro.first ] = macro.second;
    		oReturn[ "macros" ] = oMacros;
    	}
    
    	if( oArgs.HasKey( "getloglevel" ) )
    	{
    		oReturn[ "loglevel" ] = VALog_GetLogLevel();
    	}
    
    	if( oArgs.HasKey( "setloglevel" ) )
    	{
    		int iLogLevel = oArgs[ "setloglevel" ];
    		VALog_SetLogLevel( iLogLevel );
    	}
    	if( oArgs.HasKey( "structrebound" ) )
    	{
    		oReturn = oArgs[ "structrebound" ];
    	}
    
    	VA_VERBOSE( "Core", "Core module will transmit answer now" );
    	return oReturn;
    }
    
    const CVACoreConfig* CVACoreImpl::GetCoreConfig() const
    {
    	return &m_oCoreConfig;
    }
    
    const CVASceneManager* CVACoreImpl::GetSceneManager() const
    {
    	return m_pSceneManager;
    }
    
    const CVAAudioSignalSourceManager* CVACoreImpl::GetSignalSourceManager() const
    {
    	return m_pSignalSourceManager;
    }
    
    void CVACoreImpl::SetRenderingModuleMuted( const std::string& sModuleID, const bool bMuted )
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    		{
    			m_pR2RPatchbay->SetInputMuted( oRend.iR2RPatchBayInput, bMuted );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    }
    
    void CVACoreImpl::SetRenderingModuleGain( const std::string& sModuleID, const double dGain )
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    		{
    			m_pR2RPatchbay->SetInputGain( oRend.iR2RPatchBayInput, dGain );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    }
    
    double CVACoreImpl::GetRenderingModuleGain( const std::string& sModuleID ) const
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    			return m_pR2RPatchbay->GetInputGain( oRend.iR2RPatchBayInput );
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    	return 0.0f;
    }
    
    void CVACoreImpl::SetRenderingModuleAuralizationMode( const std::string& sModuleID, const int iAM )
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    		{
    			oRend.pInstance->UpdateGlobalAuralizationMode( iAM );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    }
    
    int CVACoreImpl::GetRenderingModuleAuralizationMode( const std::string& sModuleID ) const
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    			return oRend.pInstance->GetAuralizationMode();
    	}
    
    	VA_EXCEPT2( INVALID_PARAMETER, "Could not find rendering module '" + sModuleID + "'" );
    }
    
    bool CVACoreImpl::GetRenderingModuleMuted( const std::string& sModuleID ) const
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    			return m_pR2RPatchbay->IsInputMuted( oRend.iR2RPatchBayInput );
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    	return true;
    }
    
    void CVACoreImpl::SetReproductionModuleMuted( const std::string& sModuleID, const bool bMuted )
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
    		if( oRepro.sID == sModuleID )
    		{
    			m_pOutputPatchbay->SetInputMuted( oRepro.iOutputPatchBayInput, bMuted );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
    }
    
    void CVACoreImpl::SetReproductionModuleGain( const std::string& sModuleID, const double dGain )
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
    		if( oRepro.sID == sModuleID )
    		{
    			m_pOutputPatchbay->SetInputGain( oRepro.iOutputPatchBayInput, dGain );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
    }
    
    double CVACoreImpl::GetReproductionModuleGain( const std::string& sModuleID ) const
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
    		if( oRepro.sID == sModuleID )
    			return m_pOutputPatchbay->GetInputGain( oRepro.iOutputPatchBayInput );
    	}
    
    	VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
    	return 0.0f;
    }
    
    bool CVACoreImpl::GetReproductionModuleMuted( const std::string& sModuleID ) const
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ n ] );
    		if( oRepro.sID == sModuleID )
    			return m_pOutputPatchbay->IsInputMuted( oRepro.iOutputPatchBayInput );
    	}
    
    	VA_ERROR( "Core", "Could not find reproduction module '" << sModuleID << "'" );
    	return true;
    }
    
    void CVACoreImpl::GetRenderingModules( std::vector< CVAAudioRendererInfo >& vRenderers, const bool bFilterEnabled /* = true */ ) const
    {
    	vRenderers.clear();
    	for( size_t i = 0; i < m_voRenderers.size(); i++ )
    	{
    		const CVAAudioRendererDesc& oRenderer( m_voRenderers[ i ] );
    		CVAAudioRendererInfo oRendererInfo;
    		oRendererInfo.sID = oRenderer.sID;
    		oRendererInfo.sClass = oRenderer.sClass;
    		oRendererInfo.sDescription = oRendererInfo.sDescription;
    		oRendererInfo.bEnabled = oRenderer.bEnabled;
    		oRendererInfo.bOutputDetectorEnabled = oRenderer.bOutputDetectorEnabled;
    		oRendererInfo.oParams = oRenderer.oParams;
    		oRendererInfo.sOutputRecordingFilePath = oRenderer.sOutputRecordingFilePath;
    		if( !bFilterEnabled || oRendererInfo.bEnabled )
    			vRenderers.push_back( oRendererInfo );
    	}
    }
    
    
    void CVACoreImpl::SetReproductionModuleParameters( const std::string& sModuleID, const CVAStruct& oParams )
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRep( m_voReproductionModules[ n ] );
    		if( oRep.sID == sModuleID )
    		{
    			oRep.pInstance->SetParameters( oParams );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find Reproduction module '" << sModuleID << "'" );
    }
    
    CVAStruct CVACoreImpl::GetReproductionModuleParameters( const std::string& sModuleID, const CVAStruct& oParams ) const
    {
    	for( size_t n = 0; n < m_voReproductionModules.size(); n++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRep( m_voReproductionModules[ n ] );
    		if( oRep.sID == sModuleID )
    			return oRep.pInstance->GetParameters( oParams );
    	}
    
    	VA_ERROR( "Core", "Could not find Reproduction module '" << sModuleID << "'" );
    	return CVAStruct();
    }
    
    void CVACoreImpl::GetReproductionModules( std::vector< CVAAudioReproductionInfo >& vRepros, const bool bFilterEnabled /* = true */ ) const
    {
    	vRepros.clear();
    	for( size_t i = 0; i < m_voReproductionModules.size(); i++ )
    	{
    		const CVAAudioReproductionModuleDesc& oRepro( m_voReproductionModules[ i ] );
    		CVAAudioReproductionInfo oRepInfo;
    		oRepInfo.sID = oRepro.sID;
    		oRepInfo.sClass = oRepro.sClass;
    		oRepInfo.sDescription = oRepro.sDescription;
    		oRepInfo.bEnabled = oRepro.bEnabled;
    		oRepInfo.bInputDetectorEnabled = oRepro.bInputDetectorEnabled;
    		oRepInfo.sInputRecordingFilePath = oRepro.sInputRecordingFilePath;
    		oRepInfo.bOutputDetectorEnabled = oRepro.bOutputDetectorEnabled;
    		oRepInfo.sOutputRecordingFilePath = oRepro.sOutputRecordingFilePath;
    		oRepInfo.oParams = oRepro.oParams;
    		if( !bFilterEnabled || oRepInfo.bEnabled )
    			vRepros.push_back( oRepInfo );
    	}
    }
    
    void CVACoreImpl::SetRenderingModuleParameters( const std::string& sModuleID, const CVAStruct& oParams )
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    		{
    			oRend.pInstance->SetParameters( oParams );
    			return;
    		}
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    }
    
    CVAStruct CVACoreImpl::GetRenderingModuleParameters( const std::string& sModuleID, const CVAStruct& oParams ) const
    {
    	for( size_t n = 0; n < m_voRenderers.size(); n++ )
    	{
    		const CVAAudioRendererDesc& oRend( m_voRenderers[ n ] );
    		if( oRend.sID == sModuleID )
    			return oRend.pInstance->GetParameters( oParams );
    	}
    
    	VA_ERROR( "Core", "Could not find rendering module '" << sModuleID << "'" );
    	return CVAStruct();
    }