WIP on offline simulation feature using virtual sound card, currently only...

WIP on offline simulation feature using virtual sound card, currently only working for binaural free field due to a manual reset impl requirement
parent aebdafdd
......@@ -110,8 +110,8 @@ endif( )
if( NOT DEFINED ITA_VACORE_WITH_AUDIO_BACKEND_PORTAUDIO )
set( ITA_VACORE_WITH_AUDIO_BACKEND_PORTAUDIO ON CACHE BOOL "Build VACore with Portaudio audio backend support" )
endif( )
if( NOT DEFINED ITA_VACORE_WITH_AUDIO_BACKEND_DUMMY )
set( ITA_VACORE_WITH_AUDIO_BACKEND_DUMMY OFF CACHE BOOL "Build VACore with dummy audio backend support" )
if( NOT DEFINED ITA_VACORE_WITH_AUDIO_BACKEND_VIRTUAL )
set( ITA_VACORE_WITH_AUDIO_BACKEND_VIRTUAL OFF CACHE BOOL "Build VACore with virtual audio backend support (for offline simulations)" )
endif( )
......@@ -248,8 +248,8 @@ endif( )
if( ITA_VACORE_WITH_AUDIO_BACKEND_PORTAUDIO )
add_definitions( -DVACORE_WITH_AUDIO_BACKEND_PORTAUDIO )
endif( )
if( ITA_VACORE_WITH_AUDIO_BACKEND_DUMMY )
add_definitions( -DVACORE_WITH_AUDIO_BACKEND_DUMMY )
if( ITA_VACORE_WITH_AUDIO_BACKEND_VIRTUAL )
add_definitions( -DVACORE_WITH_AUDIO_BACKEND_VIRTUAL )
endif( )
# Rendering definitions
......
#include "VADummyAudioDriverBackend.h"
#include "VAVirtualAudioDriverBackend.h"
#include "../../Utils/VADebug.h"
#include <VAException.h>
#include <ITAException.h>
#include <ITANumericUtils.h>
......@@ -8,8 +9,8 @@
#include <cassert>
CVADummyAudioDriverBackend::CVADummyAudioDriverBackend( const CVAAudioDriverConfig* pConfig )
: CVAObject( "VirtualAudioDriver" )
CVAVirtualAudioDriverBackend::CVAVirtualAudioDriverBackend( const CVAAudioDriverConfig* pConfig )
: CVAObject( "VirtualAudioDevice" )
, m_oConfig( *pConfig )
, m_pDataSource( NULL )
, m_bStarted( false )
......@@ -19,72 +20,77 @@ CVADummyAudioDriverBackend::CVADummyAudioDriverBackend( const CVAAudioDriverConf
m_oOutputStreamProps.uiBlocklength = ( unsigned int ) m_oConfig.iBuffersize;
}
CVADummyAudioDriverBackend::~CVADummyAudioDriverBackend()
CVAVirtualAudioDriverBackend::~CVAVirtualAudioDriverBackend()
{
}
std::string CVADummyAudioDriverBackend::getDriverName() const
std::string CVAVirtualAudioDriverBackend::getDriverName() const
{
return "Dummy";
}
std::string CVADummyAudioDriverBackend::getDeviceName() const
std::string CVAVirtualAudioDriverBackend::getDeviceName() const
{
return "Dummy";
}
int CVADummyAudioDriverBackend::getNumberOfInputs() const
int CVAVirtualAudioDriverBackend::getNumberOfInputs() const
{
return m_oConfig.iInputChannels;
}
const ITAStreamProperties* CVADummyAudioDriverBackend::getOutputStreamProperties() const
const ITAStreamProperties* CVAVirtualAudioDriverBackend::getOutputStreamProperties() const
{
return &m_oOutputStreamProps;
}
void CVADummyAudioDriverBackend::setOutputStreamDatasource( ITADatasource* pDatasource )
void CVAVirtualAudioDriverBackend::setOutputStreamDatasource( ITADatasource* pDatasource )
{
m_pDataSource = pDatasource;
}
ITADatasource* CVADummyAudioDriverBackend::getInputStreamDatasource() const
ITADatasource* CVAVirtualAudioDriverBackend::getInputStreamDatasource() const
{
return nullptr;
}
void CVADummyAudioDriverBackend::initialize()
void CVAVirtualAudioDriverBackend::initialize()
{
}
void CVADummyAudioDriverBackend::finalize()
void CVAVirtualAudioDriverBackend::finalize()
{
}
void CVADummyAudioDriverBackend::startStreaming()
void CVAVirtualAudioDriverBackend::startStreaming()
{
m_bStarted = true;
}
bool CVADummyAudioDriverBackend::isStreaming()
bool CVAVirtualAudioDriverBackend::isStreaming()
{
return m_bStarted;
}
void CVADummyAudioDriverBackend::stopStreaming()
void CVAVirtualAudioDriverBackend::stopStreaming()
{
m_bStarted = false;
}
CVAStruct CVADummyAudioDriverBackend::CallObject( const CVAStruct& oArgs )
CVAStruct CVAVirtualAudioDriverBackend::CallObject( const CVAStruct& oArgs )
{
CVAStruct oReturn;
if( oArgs.HasKey( "trigger" ) && m_pDataSource )
{
// Trigger block pointer getter, then increment
for( int n = 0; n < (int) m_pDataSource->GetNumberOfChannels(); n++ )
m_pDataSource->GetBlockPointer( n, &m_oStreamInfo );
m_pDataSource->IncrementBlockPointer();
}
if( oArgs.HasKey( "help" ) || oArgs.HasKey( "info" ) )
{
......@@ -93,3 +99,48 @@ CVAStruct CVADummyAudioDriverBackend::CallObject( const CVAStruct& oArgs )
return oReturn;
}
CVAVirtualAudioDriverBackend::ManualClock::ManualClock()
: CVAObject( "ManualClock" )
, m_dTime( 0.0f )
{
}
CVAVirtualAudioDriverBackend::ManualClock::~ManualClock()
{
}
double CVAVirtualAudioDriverBackend::ManualClock::getTime()
{
m_csTime.enter();
double dTime = m_dTime;
m_csTime.leave();
return dTime;
}
void CVAVirtualAudioDriverBackend::ManualClock::SetTime( double dNow )
{
m_csTime.enter();
assert( m_dTime < dNow );
m_dTime = dNow;
m_csTime.leave();
}
CVAStruct CVAVirtualAudioDriverBackend::ManualClock::CallObject( const CVAStruct& oArgs )
{
if( oArgs.HasKey( "info" ) || oArgs.HasKey( "help" ) )
{
CVAStruct oRet;
oRet[ "usage" ] = "Set the manual clock with the key 'time' and a floating point value. Time has to be strict monotonously increasing";
return oRet;
}
else if( oArgs.HasKey( "time" ) )
{
SetTime( oArgs[ "time" ] );
return CVAStruct();
}
else
{
VA_EXCEPT2( INVALID_PARAMETER, "Could npt understand call, 'time' key missing. use 'help' for more information" );
}
}
......@@ -11,8 +11,8 @@
* --------------------------------------------------------------------------------------------
*/
#ifndef IW_VACORE_DUMMY_AUDIO_DRIVER_BACKEND
#define IW_VACORE_DUMMY_AUDIO_DRIVER_BACKEND
#ifndef IW_VACORE_VIRTUAL_AUDIO_DRIVER_BACKEND
#define IW_VACORE_VIRTUAL_AUDIO_DRIVER_BACKEND
#include "VAAudioDriverBackend.h"
#include "VAAudioDriverConfig.h"
......@@ -21,14 +21,17 @@
#include <ITAStreamProperties.h>
#include <ITADatasource.h>
#include <ITACriticalSection.h>
#include <ITAClock.h>
#include <ITAStreamInfo.h>
#pragma warning( disable : 4512 ) // yep no copy constructor
class CVADummyAudioDriverBackend : public IVAAudioDriverBackend, public CVAObject
class CVAVirtualAudioDriverBackend : public IVAAudioDriverBackend, public CVAObject
{
public:
CVADummyAudioDriverBackend( const CVAAudioDriverConfig* pConfig );
~CVADummyAudioDriverBackend();
CVAVirtualAudioDriverBackend( const CVAAudioDriverConfig* pConfig );
~CVAVirtualAudioDriverBackend();
std::string getDriverName() const;
std::string getDeviceName() const;
......@@ -45,11 +48,28 @@ public:
CVAStruct CallObject( const CVAStruct& oArgs );
class ManualClock : public ITAClock, public CVAObject
{
public:
ManualClock();
~ManualClock();
inline std::string getName() const { return "ManualClock"; };
inline double getResolution() const { return -1.0f; };
double getFrequency() const { return -1.0f; };
inline double getTime();
inline void SetTime( const double dManualNow );
CVAStruct CallObject( const CVAStruct& oArgs );
private:
ITACriticalSection m_csTime;
double m_dTime;
};
private:
const CVAAudioDriverConfig m_oConfig;
ITAStreamProperties m_oOutputStreamProps;
ITAStreamInfo m_oStreamInfo;
ITADatasource* m_pDataSource;
bool m_bStarted;
};
#endif // IW_VACORE_DUMMY_AUDIO_DRIVER_BACKEND
#endif // IW_VACORE_VIRTUAL_AUDIO_DRIVER_BACKEND
......@@ -17,8 +17,8 @@ endif( )
if( ITA_VACORE_WITH_AUDIO_BACKEND_PORTAUDIO )
list( APPEND DirFiles VAPortaudioBackend.cpp VAPortaudioBackend.h )
endif( )
if( ITA_VACORE_WITH_AUDIO_BACKEND_DUMMY )
list( APPEND DirFiles VADummyAudioDriverBackend.cpp VADummyAudioDriverBackend.h )
if( ITA_VACORE_WITH_AUDIO_BACKEND_VIRTUAL )
list( APPEND DirFiles VAVirtualAudioDriverBackend.cpp VAVirtualAudioDriverBackend.h )
endif( )
set( DirFiles_SourceGroup "${RelativeSourceGroup}" )
......
......@@ -188,19 +188,20 @@ private:
friend class CVABFFSoundPathFactory;
};
class CVABFFSoundPathFactory : public IVAPoolObjectFactory {
class CVABFFSoundPathFactory : public IVAPoolObjectFactory
{
public:
CVABFFSoundPathFactory( double dSamplerate, int iBlocklength, int iHRIRFilterLength, int iDirFilterLength )
: m_dSamplerate( dSamplerate )
, m_iBlocklength( iBlocklength )
, m_iHRIRFilterLength( iHRIRFilterLength )
, m_iDirFilterLength( iDirFilterLength )
{}
{};
CVAPoolObject* CreatePoolObject()
{
return new CVABFFSoundPath( m_dSamplerate, m_iBlocklength, m_iHRIRFilterLength, m_iDirFilterLength );
}
};
private:
double m_dSamplerate; //!< Abtastrate
......@@ -266,6 +267,7 @@ CVABinauralFreeFieldAudioRenderer::CVABinauralFreeFieldAudioRenderer( const CVAA
, m_iHRIRFilterLength( -1 )
, m_dAdditionalStaticDelaySeconds( 0.0f )
, m_oParams( oParams )
, m_bManualResetApparent( false )
{
// read config
Init( *oParams.pConfig );
......@@ -362,12 +364,13 @@ void CVABinauralFreeFieldAudioRenderer::Reset()
VA_VERBOSE( "BinauralFreeFieldAudioRenderer", "Received reset call, indicating reset now" );
ctxAudio.m_iResetFlag = 1; // Request reset
if( ctxAudio.m_iStatus == 0 )
if( ctxAudio.m_iStatus == 0 || m_bManualResetApparent )
{
VA_VERBOSE( "BinauralFreeFieldAudioRenderer", "Was not streaming, will reset manually" );
// if no streaming active, reset manually
//SyncInternalData();
ResetInternalData();
m_bManualResetApparent = false;
}
else
{
......@@ -1391,6 +1394,12 @@ CVAStruct CVABinauralFreeFieldAudioRenderer::CallObject( const CVAStruct& oArgs
VA_EXCEPT2( INVALID_PARAMETER, "Invalid command (\"" + sCommandOrg + "\")" );
}
void CVABinauralFreeFieldAudioRenderer::SetParameters( const CVAStruct& oParams )
{
if( oParams.HasKey( "prepare_manual_reset" ) )
m_bManualResetApparent = true;
}
void CVABinauralFreeFieldAudioRenderer::onStartDumpListeners( const std::string& sFilenameFormat )
{
if( m_bDumpListeners )
......
......@@ -118,6 +118,7 @@ public:
// --= Module interface =--
CVAStruct CallObject( const CVAStruct& oArgs );
void SetParameters( const CVAStruct& oParams );
void onStartDumpListeners( const std::string& sFilenameFormat );
void onStopDumpListeners();
......@@ -339,6 +340,8 @@ private:
ITAAtomicInt m_iStatus; //!< Current status flag: 0=stopped, 1=running
} ctxAudio;
bool m_bManualResetApparent; //!< Special case .. for resetting manually with no audio thread to sync with
void Init( const CVAStruct& oArgs );
void ManageSoundPaths( const CVASceneState* pCurScene, const CVASceneState* pNewScene, const CVASceneStateDiff* pDiff );
......
......@@ -49,8 +49,8 @@
#ifdef VACORE_WITH_AUDIO_BACKEND_PORTAUDIO
#include "Drivers/Audio/VAPortaudioBackend.h"
#endif
#ifdef VACORE_WITH_AUDIO_BACKEND_DUMMY
#include "Drivers/Audio/VADummyAudioDriverBackend.h"
#ifdef VACORE_WITH_AUDIO_BACKEND_VIRTUAL
#include "Drivers/Audio/VAVirtualAudioDriverBackend.h"
#endif
// ITA includes
......@@ -762,7 +762,8 @@ void CVACoreImpl::Finalize()
VA_TRY
{
// Mehrfaches Finialisieren fhrt nicht zu Fehlern
if( m_iState == VA_CORESTATE_CREATED ) return;
if( m_iState == VA_CORESTATE_CREATED )
return;
if( m_iState == VA_CORESTATE_FAIL )
VA_EXCEPT2( MODAL_ERROR, "Core corrupted, finalization impossible" );
......@@ -4328,14 +4329,20 @@ void CVACoreImpl::InitializeAudioDriver()
if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Portaudio" )
m_pAudioDriverBackend = new CVAPortaudioBackend( &m_oCoreConfig.oAudioDriverConfig );
#endif
#ifdef VACORE_WITH_AUDIO_BACKEND_DUMMY
#ifdef VACORE_WITH_AUDIO_BACKEND_VIRTUAL
if( m_oCoreConfig.oAudioDriverConfig.sDriver == "Virtual" )
{
m_oCoreConfig.oAudioDriverConfig.iInputChannels = 0; // not allowed
CVADummyAudioDriverBackend* pAudioDriverBackend = new CVADummyAudioDriverBackend( &m_oCoreConfig.oAudioDriverConfig );
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 )
......
......@@ -9,6 +9,9 @@ using namespace std;
IVAInterface* pCore = NULL;
const int g_iBlockLength = 128;
const double g_dSampleRate = 44100.0f;
//! Trigger virtual audio device block increment in audio processing thread
/**
......@@ -23,7 +26,7 @@ void TriggerVirtualAudioDeviceBlockIncrement();
* ... used for scene modification time stamps. This lets the user control the
* asynchronous update beaviour independent from the audio processing thread.
*/
void ManualCoreClockUpdate( const float );
void ManualCoreClockUpdate( const double );
void TestOfflineSimulationVirtualAudioDevice()
{
......@@ -45,24 +48,25 @@ void TestOfflineSimulationVirtualAudioDevice()
pCore->SetSoundSourceSignalSource( iSourceID, sFileSignalID );
// --- Simulation loop using time steps and locked scene/audio updates --- //
// --- Simulation loop using time steps and synchronized scene & audio updates --- //
const int iNumSteps = 300;
const float fTimeStepIncrement = 0.02f; // 20 ms between updates (do not confuse with virtual audio device updates)
float fManualCoreTime = 0.0f;
const int iNumSteps = 3445; // will produce 10 seconds of scene updates & audio processing
const double dTimeStepIncrement = double( g_iBlockLength ) / g_dSampleRate; // Set to audio stream block length for synced example
double dManualCoreTime = 0.0f;
// Motion
float fXPos = -100.0f;
const float fXPosIncrement = 1.0f;
const float fXPosIncrement = 0.05f;
for( int n = 0; n < iNumSteps; n++ )
{
pCore->SetSoundSourcePosition( iSourceID, VAVec3( fXPos, 1.7f, -2.0f ) );
fXPos -= fXPosIncrement;
fXPos += fXPosIncrement;
dManualCoreTime += dTimeStepIncrement;
ManualCoreClockUpdate( dManualCoreTime ); // Scene clock increment
fManualCoreTime += fTimeStepIncrement;
ManualCoreClockUpdate( fManualCoreTime );
TriggerVirtualAudioDeviceBlockIncrement();
TriggerVirtualAudioDeviceBlockIncrement(); // Audio processing increment
}
}
......@@ -72,7 +76,7 @@ CVAStruct CreateOfflineSimulationVirtualDeviceConfig()
CVAStruct oConfig, oAudioDevice;
CVAStruct oSectionDebug;
oSectionDebug[ "loglevel" ] = 5;
oSectionDebug[ "loglevel" ] = IVAInterface::VA_LOG_LEVEL_VERBOSE;
oConfig[ "debug" ] = oSectionDebug;
CVAStruct oSectionDriver;
......@@ -80,8 +84,8 @@ CVAStruct CreateOfflineSimulationVirtualDeviceConfig()
// Default user-triggered settings
oSectionDriver[ "Device" ] = "Trigger";
oSectionDriver[ "BufferSize" ] = 128;
oSectionDriver[ "SampleRate" ] = 44100.0f;
oSectionDriver[ "BufferSize" ] = g_iBlockLength;
oSectionDriver[ "SampleRate" ] = g_dSampleRate;
oSectionDriver[ "OutputChannels" ] = 2;
// Timeout settings
......@@ -121,11 +125,11 @@ void TriggerVirtualAudioDeviceBlockIncrement()
CVAStruct oAnswer = pCore->CallModule( "VirtualAudioDevice", oTriggerMessage );
}
void TriggerVirtualAudioDeviceBlockIncrement( const float fNewCoreClockTimeSeconds )
void ManualCoreClockUpdate( const double dNewCoreClockTimeSeconds )
{
CVAStruct opCoreClockIncrement;
opCoreClockIncrement[ "clock" ] = fNewCoreClockTimeSeconds;
CVAStruct oAnswer = pCore->CallModule( "core", opCoreClockIncrement );
CVAStruct oCoreClockIncrement;
oCoreClockIncrement[ "time" ] = dNewCoreClockTimeSeconds;
CVAStruct oAnswer = pCore->CallModule( "manualclock", oCoreClockIncrement );
}
int main()
......@@ -139,7 +143,11 @@ int main()
pCore->AddSearchPath( "../data" );
TestOfflineSimulationVirtualAudioDevice();
pCore->Finalize();
CVAStruct oManualReset;
oManualReset[ "prepare_manual_reset" ] = true;
pCore->SetRenderingModuleParameters( "BFF_OfflineSimulationTest", oManualReset );
pCore->Finalize(); // Executes reset, which results in deadlock of no audio streaming thread active
}
catch( CVAException& e )
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment