#include "VABinauralRealTimeRenderer.h" // VA Includes #include #include #include "../../../VACoreImpl.h" #include "../../../Utils/VAUtils.h" // VA Core Includes #include "../../../Scene/VAScene.h" // ITA includes #include #include #include #include // Utils #include "./Utils/BinauralListener/VABinauralListenerPoolFactory.h" #include "./Utils/BinauralSoundSource/VABinauralSoundSourcePoolFactory.h" VABinauralRealTimeRenderer::VABinauralRealTimeRenderer( const CVAAudioRendererInitParams& params ) : ITADatasourceRealization(2, params.pCore->GetCoreConfig()->oAudioDriverConfig.dSampleRate, params.pCore->GetCoreConfig()->oAudioDriverConfig.iBuffersize), _params(params), _core(params.pCore), _newSceneState(NULL), _curSceneState(NULL), _indicateReset(false), _resetAck(false), _clusterEngine() { init(*_params.pConfig); IVAPoolObjectFactory* listenerFactory = new VABinauralListenerPoolFactory(_core, _defaultListenerConf); _listenerPool = IVAObjectPool::Create(16, 2, listenerFactory, true); IVAPoolObjectFactory* sourceFactory = new VABinauralSoundSourcePoolFactory(_defaultSourceConf); _sourcePool = IVAObjectPool::Create(16, 2, sourceFactory, true); } VABinauralRealTimeRenderer::~VABinauralRealTimeRenderer() { } void VABinauralRealTimeRenderer::init( const CVAStruct& oArgs ) { CVAConfigInterpreter conf(oArgs); // set interpolation algorithm std::string vldInterpolationAlgorithm; conf.OptString("SwitchingAlgorithm", vldInterpolationAlgorithm, "linear"); vldInterpolationAlgorithm = toLowercase(vldInterpolationAlgorithm); if (vldInterpolationAlgorithm == "switch") _defaultVDLSwitchingAlgorithm = CITAVariableDelayLine::SWITCH; else if (vldInterpolationAlgorithm == "crossfade") _defaultVDLSwitchingAlgorithm = CITAVariableDelayLine::CROSSFADE; else if (vldInterpolationAlgorithm == "linear") _defaultVDLSwitchingAlgorithm = CITAVariableDelayLine::LINEAR_INTERPOLATION; else if (vldInterpolationAlgorithm == "cubicspline") _defaultVDLSwitchingAlgorithm = CITAVariableDelayLine::CUBIC_SPLINE_INTERPOLATION; else if (vldInterpolationAlgorithm == "windowedsinc") _defaultVDLSwitchingAlgorithm = CITAVariableDelayLine::WINDOWED_SINC_INTERPOLATION; else ITA_EXCEPT1(INVALID_PARAMETER, "Unrecognized interpolation algorithm '" + vldInterpolationAlgorithm + "' in BinauralFreefieldAudioRendererConfig"); // HRTF filter length conf.OptInteger("HRIRFilterLength", _hrirFilterLength, 256); // additional static delay conf.OptNumber("AdditionalStaticDelaySeconds", _additionalStaticDelaySeconds, 0.0f); // default listener config conf.OptInteger("MotionModelNumHistoryKeys", _defaultListenerConf.motionModelNumHistoryKeys, 1000); if (_defaultListenerConf.motionModelNumHistoryKeys < 1) VA_EXCEPT2(INVALID_PARAMETER, "Basic motion model history needs to be greater than zero"); conf.OptNumber("MotionModelWindowSize", _defaultListenerConf.motionModelWindowSize, 0.1f); conf.OptNumber("MotionModelWindowDelay", _defaultListenerConf.motionModelWindowDelay, 0.1f); if ((_defaultListenerConf.motionModelWindowSize <= 0) || (_defaultListenerConf.motionModelWindowDelay < 0)) VA_EXCEPT2(INVALID_PARAMETER, "Basic motion model window parameters parse error (zero or negative?)"); // default source config conf.OptInteger("MotionModelNumHistoryKeys", _defaultSourceConf.motionModelNumHistoryKeys, 1000); if (_defaultSourceConf.motionModelNumHistoryKeys < 1) VA_EXCEPT2(INVALID_PARAMETER, "Basic motion model history needs to be greater than zero"); conf.OptNumber("MotionModelWindowSize", _defaultSourceConf.motionModelWindowSize, 0.1f); conf.OptNumber("MotionModelWindowDelay", _defaultSourceConf.motionModelWindowDelay, 0.1f); if ((_defaultSourceConf.motionModelWindowSize <= 0) || (_defaultSourceConf.motionModelWindowDelay < 0)) VA_EXCEPT2(INVALID_PARAMETER, "Basic motion model window parameters parse error (zero or negative?)"); _defaultSourceConf.blockLength = GetBlocklength(); _defaultSourceConf.sampleRate = GetSampleRate(); } void VABinauralRealTimeRenderer::processStream(const ITAStreamInfo* streamInfo) { ITASampleFrame* output; float* outputChL = GetWritePointer(0); float* outputChR = GetWritePointer(1); fm_zero(outputChL, GetBlocklength()); fm_zero(outputChR, GetBlocklength()); const CVAAudiostreamState* streamState = dynamic_cast< const CVAAudiostreamState* >(streamInfo); double dListenerTime = streamState->dSysTime; // -- create output for every listener std::map< int, VABinauralListener* >::const_iterator it; for (it = _listeners.begin(); it != _listeners.end(); ++it) { VABinauralClustering* clustering = _clusterEngine.getClustering(it->first); output = clustering->getOutput(); fm_copy(outputChL, (*output)[0].data(), m_uiBlocklength); fm_copy(outputChR, (*output)[1].data(), m_uiBlocklength); } IncrementWritePointer(); return; } void VABinauralRealTimeRenderer::updateScene(CVASceneState* newSceneState) { assert(newSceneState); _newSceneState = newSceneState; if (_newSceneState == _curSceneState) return; // get reference to new scene _newSceneState->AddReference(); // get difference between old scene state and current scene state CVASceneStateDiff diff; _newSceneState->Diff(_curSceneState, &diff); // update listeners updateListeners(&diff); // update sources updateSources(&diff); } /* ITADatasource* VABinauralRealTimeRenderer::GetOutputDatasource() { return this; } */ void VABinauralRealTimeRenderer::updateSources( CVASceneStateDiff* diff ) { typedef std::vector< int >::const_iterator icit_t; // Delete sources for (icit_t it = diff->viDelSoundSourceIDs.begin(); it != diff->viDelSoundSourceIDs.end(); ++it) { const int& iID(*it++); deleteSource(iID); } // Add sources for (icit_t it = diff->viNewSoundSourceIDs.begin(); it != diff->viNewSoundSourceIDs.end(); ++it) { const int& iID(*it++); createSource(iID, _newSceneState->GetSoundSourceState(iID)); } // update source trajectories std::map< int, VABinauralSoundSource* >::iterator it; for (it = _sources.begin(); it != _sources.end(); ++it) { int sourceID = it->first; VABinauralSoundSource* source = it->second; CVASoundSourceState* sourceCur = (_curSceneState ? _curSceneState->GetSoundSourceState(sourceID) : nullptr); CVASoundSourceState* sourceNew = (_newSceneState ? _curSceneState->GetSoundSourceState(sourceID) : nullptr); const CVAMotionState* motionCur = (sourceCur ? sourceCur->GetMotionState() : nullptr); const CVAMotionState* motionNew = (sourceNew ? sourceNew->GetMotionState() : nullptr); if (motionNew && (motionNew != motionCur)) { source->motionModel->InputMotionKey(motionNew); } } _clusterEngine.update(); } void VABinauralRealTimeRenderer::updateListeners( CVASceneStateDiff* diff ) { typedef std::vector< int >::const_iterator icit_t; // Delete listeners for (icit_t it = diff->viDelReceiverIDs.begin(); it != diff->viDelReceiverIDs.end(); ++it) { const int& iID(*it++); deleteListener(iID); } // Add listeners for (icit_t it = diff->viNewReceiverIDs.begin(); it != diff->viNewReceiverIDs.end(); ++it) { const int& iID(*it++); createListener(iID, _newSceneState->GetReceiverState(iID)); } // update listener trajectories for (std::map< int, VABinauralListener* >::iterator it = _listeners.begin(); it != _listeners.end(); ++it) { int iListenerID = it->first; VABinauralListener* listener = it->second; CVAReceiverState* listenerCur = (_curSceneState ? _curSceneState->GetReceiverState(iListenerID) : nullptr); CVAReceiverState* listenerNew = (_newSceneState ? _newSceneState->GetReceiverState(iListenerID) : nullptr); const CVAMotionState* motionCur = (listenerCur ? listenerCur->GetMotionState() : nullptr); const CVAMotionState* motionNew = (listenerNew ? listenerNew->GetMotionState() : nullptr); if (motionNew && (motionNew != motionCur)) { listener->motionModel->InputMotionKey(motionNew); } } } void VABinauralRealTimeRenderer::createSource( const int sourceID, const CVASoundSourceState* sourceState ) { VABinauralSoundSource* source = dynamic_cast< VABinauralSoundSource* >(_sourcePool->RequestObject()); // Reference = 1 // set internal data source->data = _core->GetSceneManager()->GetSoundSourceDesc(sourceID); source->data->AddReference(); // set motion model CVABasicMotionModel* motionInstance = dynamic_cast< CVABasicMotionModel* >(source->motionModel->GetInstance()); motionInstance->SetName(std::string("bfrend_mm_source_" + source->data->sName)); motionInstance->Reset(); // add local reference _sources.insert(std::pair< int, VABinauralSoundSource* >(sourceID, source)); // add source to clustering _clusterEngine.addSource(sourceID, source); } void VABinauralRealTimeRenderer::deleteSource(int sourceID) { // remove local source reference std::map< int, VABinauralSoundSource* >::iterator it = _sources.find(sourceID); VABinauralSoundSource* source = it->second; _sources.erase(it); //listener->bDeleted = true; //listener->pData->RemoveReference(); source->RemoveReference(); // remove listener reference from clustering _clusterEngine.removeListener(sourceID); } void VABinauralRealTimeRenderer::createListener(int listenerID, const CVAReceiverState* recevierState) { VABinauralListener* listener = dynamic_cast< VABinauralListener* >(_listenerPool->RequestObject()); // Reference = 1 // set internal data listener->data = _core->GetSceneManager()->GetListenerDesc(listenerID); listener->data->AddReference(); // set motion model CVABasicMotionModel* motionInstance = dynamic_cast< CVABasicMotionModel* >(listener->motionModel->GetInstance()); motionInstance->SetName(std::string("bfrend_mm_listener_" + listener->data->sName)); motionInstance->Reset(); // add local reference _listeners.insert(std::pair< int, VABinauralListener* >(listenerID, listener)); // add listener to clustering VABinauralClusterEngine::clusterConfig_t config = { /*numClusters=*/ 9 }; _clusterEngine.addListener(listenerID, listener, config); } void VABinauralRealTimeRenderer::deleteListener(int listenerID) { // remove local listener reference std::map< int, VABinauralListener* >::iterator it = _listeners.find(listenerID); VABinauralListener* listener = it->second; _listeners.erase(it); //listener->bDeleted = true; //listener->pData->RemoveReference(); listener->RemoveReference(); // remove listener reference from clustering _clusterEngine.removeListener(listenerID); }