Commit 1a394b3e authored by Michael Kohnen's avatar Michael Kohnen
Browse files

Merge branch 'features/ambisonics' into develop

merging ambisonics features
parents 3bff4dd3 58adedd8
......@@ -46,6 +46,7 @@ vista_use_package( ITACTC REQUIRED FIND_DEPENDENCIES )
vista_use_package( ITASampler REQUIRED FIND_DEPENDENCIES )
vista_use_package( OpenDAFF REQUIRED )
vista_use_package( SPLINE REQUIRED )
vista_use_package( Eigen REQUIRED )
# Optional packages
vista_find_package( RavenNet QUIET )
......
......@@ -69,11 +69,11 @@ ProjectName = MyVirtualAcousticsProject
[Debug]
# Record device input and store to hard drive (will record every input channel)
OutputRecordEnabled = false
OutputRecordFilePath = $(ProjectName)_in.wav
InputRecordEnabled = false
InputRecordFilePath = $(ProjectName)_in.wav
# Record device output and store to hard drive (will record every output channel)
InputRecordEnabled = false
OutputRecordEnabled = false
OutputRecordFilePath = $(ProjectName)_out.wav
# Set log level: 0 = quiet; 1 = errors; 2 = warnings (default); 3 = info; 4 = verbose; 5 = trace;
......
......@@ -5,7 +5,7 @@
[Output:VRLAB_LS_ALL]
Description = ITA VRLab setup using all available broadband loudspeaker (O300 & O110)
Enabled = false
Enabled = true
Devices = LS_FL, LS_FR, LS_RR, LS_RL, LS_TF, LS_TR, LS_TB, LS_TL, LS_BF, LS_BR, LS_BB, LS_BL
[Output:VRLAB_VLS_ALL]
......
......@@ -100,28 +100,7 @@ public:
return ( bBothEnabled && bSameRecordIndex && bSameData );
};
};
/*
class CHRIRState
{
public:
CHRIRState()
: pData(NULL)
, iRecord(-1)
, fDistance(1.0f) {}
IVAHRIRDataset* pData; //!< HRIR data, may be NULL
int iRecord; //!< HRIR index
float fDistance; //!< HRIR dataset distance
bool operator!=(const CHRIRState& rhs) const
{
if (pData != rhs.pData) return true;
if (fDistance != rhs.fDistance) return true;
if (iRecord != rhs.iRecord) return true;
return false;
}
};
*/
CVAAmbisonicsFreeFieldAudioRenderer::CVAAFFSource* pSource;
CVAAmbisonicsFreeFieldAudioRenderer::CVAAFFListener* pListener;
......@@ -134,8 +113,7 @@ public:
CITAThirdOctaveFilterbank* pThirdOctaveFilterBank;
CITAVariableDelayLine* pVariableDelayLineCh;
//ITAUPConvolver* pFIRConvolverCh;
inline void PreRequest()
{
......
......@@ -30,7 +30,7 @@ CVAAmbisonicsReproduction::CVAAmbisonicsReproduction( const CVAAudioReproduction
{
CVAConfigInterpreter conf( *(m_oParams.pConfig) );
conf.ReqInteger( "AmbisonicsTruncationOrder", m_iAmbisonicsTruncationOrder );
conf.ReqInteger( "TruncationOrder", m_iAmbisonicsTruncationOrder );
double dSampleRate = m_oParams.pCore->GetCoreConfig()->oAudioDriverConfig.dSampleRate;
int iBlockLength = oParams.pCore->GetCoreConfig()->oAudioDriverConfig.iBuffersize;
......@@ -52,8 +52,9 @@ CVAAmbisonicsReproduction::CVAAmbisonicsReproduction( const CVAAudioReproduction
{
//Mittelpunkt aus der ersten LS Configuration berechnen
m_vpTargetOutputs[0];
VA_EXCEPT2(NOT_IMPLEMENTED, "Automatic reproduction center calculation not implemented, please provide 3-dim vector with key 'ReproductionCenterPos' in reproduction configuration");
m_v3ReproductionCenterPos.Set(0, 0, 0);
// VA_EXCEPT2(NOT_IMPLEMENTED, "Automatic reproduction center calculation not implemented, please provide 3-dim vector with key 'ReproductionCenterPos' in reproduction configuration");
VA_WARN(this, "Reproduction center set to 0,0,0");
}
else
{
......@@ -61,7 +62,7 @@ CVAAmbisonicsReproduction::CVAAmbisonicsReproduction( const CVAAudioReproduction
assert( vsPosComponents.size() == 3 );
m_v3ReproductionCenterPos.Set( StringToFloat( vsPosComponents[0] ), StringToFloat( vsPosComponents[1] ), StringToFloat( vsPosComponents[2] ) );
}
return;
}
......@@ -73,6 +74,8 @@ CVAAmbisonicsReproduction::~CVAAmbisonicsReproduction()
void CVAAmbisonicsReproduction::SetInputDatasource( ITADatasource* p )
{
CVAConfigInterpreter conf(*(m_oParams.pConfig));
m_pDecoderMatrixPatchBay->AddInput( p );
int iNumConfiguredAmbisonicsChannels = ( m_iAmbisonicsTruncationOrder + 1 ) * ( m_iAmbisonicsTruncationOrder + 1 );
......@@ -81,19 +84,39 @@ void CVAAmbisonicsReproduction::SetInputDatasource( ITADatasource* p )
int iMaxPossibleAmbisonicsChannelNumber = min( int( p->GetNumberOfChannels() ), iNumConfiguredAmbisonicsChannels );
// Determine matrix (temp)
double dYInv[9][12] =
std::string sOutput;
conf.ReqString("Outputs", sOutput);
m_pOutput = m_oParams.pCore->GetCoreConfig()->oHardwareSetup.GetOutput(sOutput);
Eigen::MatrixXd matY(m_pOutput->vpDevices.size(), (m_iAmbisonicsTruncationOrder + 1)*(m_iAmbisonicsTruncationOrder + 1));
double dAzimuth, dElevation;
// TODO Center Position aus Config?
VAVec3 va3Origin(0, 0, 0);
VAVec3 va3View(0, 0, -1);
VAVec3 va3Up(0, 1, 0);
std::vector<double> vdYParts;
// Gather matrix with loudspeaker position as (N_LS x 3);
for (int k = 0; k < m_pOutput->vpDevices.size(); k++)
{
{ -1.2641, -1.2641, -1.2641, -1.2641, 1.0191, 1.0191, 1.0191 , 1.0191 , 1.1312 , 1.1312 , 1.1312 , 1.1312 },
{ 0.2659 , -0.2659 , -0.2659 , 0.2659 , -0.0000 , -0.3333 , 0.0000 , 0.3333 , -0.0000 , -0.3638 , 0.0000 , 0.3638 },
{ 0.1441 , 0.1441 , 0.1441 , 0.1441 , 0.6210 , 0.6210 , 0.6210 , 0.6210 , -0.7651 , -0.7651 , -0.7651 , -0.7651 },
{ 0.2659 , 0.2659 , -0.2659 , -0.2659 , 0.3333 , 0.0000 , -0.3333 , 0.0000 , 0.3638 , -0.0000 , -0.3638 , 0.0000 },
{ -0.4576, 0.4576, -0.4576, 0.4576, 0.0000, -0.0000, -0.0000 , -0.0000 , 0.0000 , 0.0000 , -0.0000 , -0.0000 },
{ -0.0113, 0.0113, 0.0113, -0.0113, 0.0000, -0.6780, -0.0000 , 0.6780 , 0.0000 , 0.6496 , -0.0000 , -0.6496 },
{ -1.9233, -1.9233, -1.9233, -1.9233, 0.9115, 0.9115, 0.9115 , 0.9115 , 1.0118 , 1.0118 , 1.0118 , 1.0118 },
{ -0.0113, -0.0113, 0.0113, 0.0113, 0.6780, 0.0000, -0.6780 , 0.0000 , -0.6496 , 0.0000 , 0.6496 , -0.0000 },
{ 0.0000 , 0.0000 , 0.0000 , -0.0000 , 0.2610 , -0.2610 , 0.2610 ,-0.2610 , 0.2698 , -0.2698 , 0.2698 , -0.2698 },
};
const CVAHardwareDevice* pDevice = m_pOutput->vpDevices[k];
dAzimuth = GetAzimuthOnTarget_DEG(va3Origin, va3View, va3Up, pDevice->vPos) / 180 * ITAConstants::PI_D;
dElevation = GetElevationOnTarget_DEG(va3Origin, va3View, va3Up, pDevice->vPos) / 180 * ITAConstants::PI_D;
vdYParts = SHRealvaluedBasefunctions(ITAConstants::PI_D / 2 - dElevation, dAzimuth, m_iAmbisonicsTruncationOrder);
for (int l = 0; l < vdYParts.size(); l++)
{
matY(k, l) = vdYParts[l];
}
}
Eigen::MatrixXd matYinv = CalculatePseudoInverse(matY);
std::vector<double> vdRemaxWeights = HOARemaxWeights(m_iAmbisonicsTruncationOrder);
// Ambisonics outputs
for( size_t i=0; i<m_vpTargetOutputs.size(); i++ )
......@@ -104,6 +127,7 @@ void CVAAmbisonicsReproduction::SetInputDatasource( ITADatasource* p )
// Apply matrix as weighting gains of in/out patch bay (truncate higher orders if necessary)
for( int j=0; j < iMaxPossibleAmbisonicsChannelNumber; j++ )
{
int iCurrentOrder = floor(sqrt(j));
for( size_t k=0; k < pTargetOutput->GetPhysicalOutputChannels().size(); k++ )
{
const VAVec3& v3LSPos( pTargetOutput->vpDevices[k]->vPos );
......@@ -115,14 +139,11 @@ void CVAAmbisonicsReproduction::SetInputDatasource( ITADatasource* p )
// todo calculate gain @mko
if ( j==0 && k==0 )
VA_WARN("AmbisonicsReproduction", "No dynamic HOA matrix calculation based on LS configuration available, using pre-calculated matrix for ITA VR lab");
double dGain = dYInv[j][k]; // TEMP use static gain from matrix
double dGain = matYinv(i, j)*vdRemaxWeights[iCurrentOrder];
m_pDecoderMatrixPatchBay->ConnectChannels( 0, int( j ), 0, int( k ), dGain );
}
}
}
}
ITADatasource* CVAAmbisonicsReproduction::GetOutputDatasource()
......@@ -143,4 +164,33 @@ void CVAAmbisonicsReproduction::UpdateScene( CVASceneState* )
return;
}
#endif // VACORE_WITH_REPRODUCTION_AMBISONICS_BINAURAL_MIXDOWN
Eigen::MatrixXd CVAAmbisonicsReproduction::CalculatePseudoInverse(Eigen::MatrixXd ematIn)
{
Eigen::JacobiSVD<Eigen::MatrixXd> svd(ematIn, Eigen::ComputeFullU | Eigen::ComputeFullV);
double pinvtoler = 1.e-6; // choose your tolerance wisely!
Eigen::MatrixXd singularValues = svd.singularValues();
Eigen::MatrixXd singularValues_inv;
singularValues_inv = singularValues_inv.Zero(ematIn.cols(), ematIn.rows());
for (int i = 0; i<singularValues.size(); ++i) {
if (singularValues(i) > pinvtoler)
singularValues_inv(i, i) = 1.0 / singularValues(i);
else singularValues_inv(i, i) = 0;
}
Eigen::MatrixXd V = svd.matrixV();
Eigen::MatrixXd U = svd.matrixU();
Eigen::MatrixXd Diag = singularValues_inv;
Eigen::MatrixXd S1 = V*Diag;
Eigen::MatrixXd UTrans = U.transpose();
Eigen::MatrixXd S2 = S1*UTrans;
return S2;
}
#endif // VACORE_WITH_REPRODUCTION_AMBISONICS
\ No newline at end of file
......@@ -19,8 +19,14 @@
#include "../VAAudioReproductionModule.h"
#include "../VAAudioReproductionModuleRegistry.h"
#include "../../VACoreImpl.h"
#include <ITASampleFrame.h>
#include <ITANumericUtils.h>
#include <ITAConstants.h>
#include "Eigen\Dense"
#include "Eigen\SVD"
#include "Eigen\Jacobi"
#include "Eigen\Core"
#include "Eigen\Eigen"
class ITAStreamPatchbay;
......@@ -35,6 +41,9 @@ public:
int GetNumInputChannels() const;
int GetAmbisonicsTruncationOrder() const;
void UpdateScene( CVASceneState* pNewState );
/*bool Inverse(Eigen::MatrixXd vmIn, Eigen::MatrixXd vmOut);
bool SwapLine(Eigen::MatrixXd vmIn, int, int);*/
Eigen::MatrixXd CalculatePseudoInverse(Eigen::MatrixXd);
private:
......@@ -44,6 +53,7 @@ private:
std::vector< const CVAHardwareOutput* > m_vpTargetOutputs;
ITAStreamPatchbay* m_pDecoderMatrixPatchBay;
VAVec3 m_v3ReproductionCenterPos;
const CVAHardwareOutput* m_pOutput;
};
#endif // ( VACORE_WITH_REPRODUCTION_AMBISONICS == 1 )
......
......@@ -29,6 +29,7 @@
#include <ITADataSourceRealization.h>
#include <ITANumericUtils.h>
#include <ITAStreamPatchbay.h>
#include <ITAConstants.h>
#include <VistaBase/VistaQuaternion.h>
#include <VistaBase/VistaTransformMatrix.h>
......@@ -85,6 +86,9 @@ CVAAmbisonicsBinauralMixdownReproduction::CVAAmbisonicsBinauralMixdownReproducti
std::string sVirtualOutput;
conf.ReqString( "VirtualOutput", sVirtualOutput );
m_pVirtualOutput = m_oParams.pCore->GetCoreConfig()->oHardwareSetup.GetOutput( sVirtualOutput );
if( m_pVirtualOutput == nullptr )
VA_EXCEPT2( INVALID_PARAMETER, "Unrecognized virtual output '"+sVirtualOutput+"' for binaural mixdown reproduction" );
......@@ -97,78 +101,43 @@ CVAAmbisonicsBinauralMixdownReproduction::CVAAmbisonicsBinauralMixdownReproducti
m_pdsStreamFilter = new CMixdownStreamFilter( GetNumVirtualLoudspeaker(), dSampleRate, iBlockLength, m_iHRIRFilterLength );
m_pdsStreamFilter->pdsInput = m_pDecoderMatrixPatchBay->GetOutputDatasource( 0 );
double dYInv[9][25] =
{
{ 0.141479, 0.141920, 0.141646, 0.141830, 0.142275, 0.141479, 0.141526, 0.141477, 0.141646, 0.141477, 0.141994, 0.142275, 0.142275, 0.141994, 0.141526, 0.141646, 0.141830, 0.141526, 0.141994, 0.141479, 0.141477, 0.141920, 0.142466, 0.141830, 0.141920 },
{ 0.005941, 0.000089, 0.086866, -0.289171, -0.218760, 0.132279, -0.048748, 0.071201, -0.185809, -0.181762, 0.034672, -0.097372, -0.227303, 0.268540, -0.043764, -0.167073, -0.026226, 0.231909, 0.143544, -0.214299, 0.160602, 0.253240, 0.208520, -0.056470, 0.159354 },
{ 0.290269, -0.120293, 0.057773, 0.017307, 0.127976, -0.149033, -0.246478, -0.271526, 0.204262, 0.037630, 0.059254, 0.035368, -0.077298, 0.084189, 0.205663, -0.219915, 0.224294, 0.018744, -0.214181, -0.129190, 0.225973, -0.132183, -0.033016, -0.182721, 0.187134 },
{ -0.010309, 0.259113, -0.259466, 0.048463, -0.121716, -0.211398, 0.104138, -0.083419, 0.044248, 0.226498, 0.275812, -0.261374, -0.146311, 0.039797, 0.172511, -0.043928, -0.187809, -0.140852, 0.119610, 0.147593, -0.094330, -0.002682, 0.203135, -0.222917, 0.145594 },
{ 0.003282, -0.006696, -0.269060, -0.131720, 0.296452, -0.310102, -0.063386, -0.049882, -0.103034, -0.428107, 0.094691, 0.284039, 0.372584, 0.114170, -0.092901, 0.073076, 0.056890, -0.381878, 0.184781, -0.325510, -0.157803, -0.006838, 0.444594, 0.142130, 0.260228 },
{ 0.006189, -0.003088, 0.059091, -0.061678, -0.317678, -0.218363, 0.141425, -0.209619, -0.439036, -0.085531, 0.030327, -0.038565, 0.201335, 0.253543, -0.105321, 0.428546, -0.068044, 0.051366, -0.347849, 0.314950, 0.398489, -0.373260, -0.072262, 0.118783, 0.336251 },
{ 0.519905, -0.128956, -0.222463, -0.253086, -0.095566, -0.071242, 0.363030, 0.423903, 0.166847, -0.253144, -0.231166, -0.242859, -0.197860, -0.179531, 0.179474, 0.223870, 0.180918, -0.239684, 0.189199, -0.092858, 0.186994, -0.092435, -0.250168, 0.034298, 0.082579 },
{ -0.009086, -0.352444, -0.165782, 0.007717, -0.177053, 0.316863, -0.292659, 0.226190, 0.099659, 0.096699, 0.185697, -0.105388, 0.131534, 0.030299, 0.408122, 0.113469, -0.438948, -0.030252, -0.278323, -0.207655, -0.222219, 0.016649, -0.070396, 0.420575, 0.296734 },
{ -0.012261, 0.367459, 0.351366, -0.428608, -0.189546, 0.145810, 0.047338, -0.002382, -0.187556, 0.115177, 0.413844, 0.336094, -0.171487, -0.398253, 0.158751, -0.155985, 0.188937, -0.192006, -0.025891, -0.117003, -0.096159, -0.357402, -0.011634, 0.237909, -0.016513 },
};
//if (m_iAmbisonicsTruncationOrder == 3)
//{
/* { double dYInv[16][12] =
{
{ 0.1935, 0.1935, 0.1935, 0.1935, 0.2222, 0.2222, 0.2222, 0.2222, 0.2386, 0.2386, 0.2386, 0.2386 },
{ 0.5226, -0.5226, -0.5226, 0.5226, -0.0000, -0.6052, 0.0000, 0.6052, -0.0000, -0.6203, 0.0000, 0.6203 },
{ -0.0083, -0.0083, -0.0083, -0.0083, 0.6265, 0.6265, 0.6265, 0.6265, -0.5964, -0.5964, -0.5964, -0.5964 },
{ 0.5226, 0.5226, -0.5226, -0.5226, 0.6052, -0.0000, -0.6052, -0.0000, 0.6203, 0.0000, -0.6203, -0.0000 },
{ 1.3985, -1.3985, 1.3985, -1.3985, 0.0000, -0.0000, -0.0000, 0.0000, -0.0000, -0.0000, -0.0000, -0.0000 },
{ 0.0072, -0.0072, -0.0072, 0.0072, -0.0000, -2.0462, 0.0000, 2.0462, 0.0000, 2.0034, 0.0000, -2.0034 },
{ -0.4886, -0.4886, -0.4886, -0.4886, -0.1783, -0.1783, -0.1783, -0.1783, -0.1914, -0.1914, -0.1914, -0.1914 },
{ 0.0072, 0.0072, -0.0072, -0.0072, 2.0462, 0.0000, -2.0462, 0.0000, -2.0034, 0.0000, 2.0034, -0.0000 },
{ -0.0000, 0.0000, 0.0000, -0.0000, 0.7820, -0.7820, 0.7820, -0.7820, 0.8396, -0.8396, 0.8396, -0.8396 },
{ 1.5412, -1.5412, -1.5412, 1.5412, -0.0000, 1.1505, 0.0000, -1.1505, -0.0000, 1.3099, 0.0000, -1.3099 },
{ 0.0000, 0.0000, 0.0000, -0.0000, -0.0000, 0.0000, -0.0000, 0.0000, -0.0000, -0.0000, 0.0000, 0.0000 },
{ -0.5516, 0.5516, 0.5516, -0.5516, 0.0000, -0.3022, 0.0000, 0.3022, -0.0000, -0.1409, -0.0000, 0.1409 },
{ 0.0004, 0.0004, 0.0004, 0.0004, -1.1248, -1.1248, -1.1248, -1.1248, 1.0876, 1.0876, 1.0876, 1.0876 },
{ -0.5516, -0.5516, 0.5516, 0.5516, 0.3022, 0.0000, -0.3022, 0.0000, 0.1409, -0.0000, -0.1409, 0.0000 },
{ -0.0000, 0.0000, 0.0000, 0.0000, 1.4519, -1.4519, 1.4519, -1.4519, -1.4043, 1.4043, -1.4043, 1.4043 },
{ -1.5412, -1.5412, 1.5412, 1.5412, 1.1505, 0.0000, -1.1505, -0.0000, 1.3099, -0.0000, -1.3099, 0.0000 },
};
}
else if (m_iAmbisonicsTruncationOrder == 2)
Eigen::MatrixXd matY(m_pVirtualOutput->vpDevices.size(), (m_iAmbisonicsTruncationOrder + 1)*(m_iAmbisonicsTruncationOrder + 1));
double dAzimuth, dElevation;
// TODO Center Position aus Config?
VAVec3 va3Origin(0, 0, 0);
VAVec3 va3View(0, 0, -1);
VAVec3 va3Up(0, 1, 0);
std::vector<double> vdYParts;
// Gather matrix with loudspeaker position as (N_LS x 3);
for (int k = 0; k < m_pVirtualOutput->vpDevices.size(); k++)
{
double dYInv[9][12] =
const CVAHardwareDevice* pDevice = m_pVirtualOutput->vpDevices[k];
dAzimuth = GetAzimuthOnTarget_DEG(va3Origin, va3View, va3Up, pDevice->vPos) / 180 * ITAConstants::PI_D;
dElevation = GetElevationOnTarget_DEG(va3Origin, va3View, va3Up, pDevice->vPos) / 180 * ITAConstants::PI_D;
vdYParts = SHRealvaluedBasefunctions(ITAConstants::PI_D/2-dElevation, dAzimuth, m_iAmbisonicsTruncationOrder);
for (int l = 0; l < vdYParts.size(); l++)
{
{ 0.1935, 0.1935, 0.1935, 0.1935, 0.2287, 0.2287, 0.2287, 0.2287, 0.2323, 0.2323, 0.2323, 0.2323 },
{ 0.5348, -0.5348, -0.5348, 0.5348, 0.0000, -0.6703, -0.0000, 0.6703, -0.0000, -0.7317, 0.0000, 0.7317 },
{ -0.0087, -0.0087, -0.0087, -0.0087, 0.5053, 0.5053, 0.5053, 0.5053, -0.4788, -0.4788, -0.4788, -0.4788 },
{ 0.5348, 0.5348, -0.5348, -0.5348, 0.6703, 0.0000, -0.6703, -0.0000, 0.7317, -0.0000, -0.7317, -0.0000 },
{ 1.6712, -1.6712, 1.6712, -1.6712, -0.0000, 0.0000, -0.0000, 0.0000, 0.0000, -0.0000, -0.0000, -0.0000 },
{ -0.0414, 0.0414, 0.0414, -0.0414, 0.0000, -2.4757, 0.0000, 2.4757, 0.0000, 2.3722, 0.0000, -2.3722 },
{ -0.5839, -0.5839, -0.5839, -0.5839, -0.1921, -0.1921, -0.1921, -0.1921, -0.2490, -0.2490, -0.2490, -0.2490 },
{ -0.0414, -0.0414, 0.0414, 0.0414, 2.4757, -0.0000, -2.4757, 0.0000, -2.3722, -0.0000, 2.3722, -0.0000 },
{ 0.0000, -0.0000, 0.0000, -0.0000, 0.9531, -0.9531, 0.9531, -0.9531, 0.9854, -0.9854, 0.9854, -0.9854 },
};
matY(k,l)=vdYParts[l];
}
}
else if (m_iAmbisonicsTruncationOrder == 1)
{
double dYInv[4][12] =
{
{ 0.2533, 0.2533, 0.2533, 0.2533, 0.2484, 0.2484, 0.2484, 0.2484, 0.2578, 0.2578, 0.2578, 0.2578 },
{ 0.5940, -0.5940, -0.5940, 0.5940, -0.0000, -0.7734, 0.0000, 0.7734, -0.0000, -0.7864, 0.0000, 0.7864 },
{ -0.0163, -0.0163, -0.0163, -0.0163, 0.5596, 0.5596, 0.5596, 0.5596, -0.5351, -0.5351, -0.5351, -0.5351 },
{ 0.5940, 0.5940, -0.5940, -0.5940, 0.7734, 0.0000, -0.7734, 0.0000, 0.7864, -0.0000, -0.7864, -0.0000 },
};
Eigen::MatrixXd matYinv = CalculatePseudoInverse(matY);
std::vector<double> vdRemaxWeights = HOARemaxWeights(m_iAmbisonicsTruncationOrder);
}
else
{
VA_EXCEPT1("Ambisonics truncation order unknown - ATM only 1,2,3 is supported");
} */
// Matrix
for( int i=0; i < GetNumInputChannels(); i++ )
{
int iCurrentOrder = floor(sqrt(i));
for( int j=0; j < GetNumVirtualLoudspeaker(); j++ )
{
double dGain = dYInv[i][j]; // todo calculate from LS setup @mko
double dGain = matYinv(i, j)*vdRemaxWeights[iCurrentOrder];
m_pDecoderMatrixPatchBay->ConnectChannels( 0, i, 0, j, dGain );
}
}
......@@ -282,6 +251,35 @@ void CVAAmbisonicsBinauralMixdownReproduction::UpdateScene( CVASceneState* pNewS
return;
}
Eigen::MatrixXd CVAAmbisonicsBinauralMixdownReproduction::CalculatePseudoInverse(Eigen::MatrixXd ematIn)
{
Eigen::JacobiSVD<Eigen::MatrixXd> svd(ematIn, Eigen::ComputeFullU | Eigen::ComputeFullV);
double pinvtoler = 1.e-6; // choose your tolerance wisely!
Eigen::MatrixXd singularValues = svd.singularValues();
Eigen::MatrixXd singularValues_inv;
singularValues_inv = singularValues_inv.Zero(ematIn.cols(), ematIn.rows());
for (int i = 0; i<singularValues.size(); ++i) {
if (singularValues(i) > pinvtoler)
singularValues_inv(i, i) = 1.0 / singularValues(i);
else singularValues_inv(i, i) = 0;
}
Eigen::MatrixXd V = svd.matrixV();
Eigen::MatrixXd U = svd.matrixU();
Eigen::MatrixXd Diag = singularValues_inv;
Eigen::MatrixXd S1 = V*Diag;
Eigen::MatrixXd UTrans = U.transpose();
Eigen::MatrixXd S2 = S1*UTrans;
return S2;
}
// --= Stream filter =--
CMixdownStreamFilter::CMixdownStreamFilter( int iNumLoudspeaker, double dSampleRate, int iBlockLength, int iMaxFilterLength ) : ITADatasourceRealization( 2, dSampleRate, iBlockLength )
......
......@@ -19,6 +19,9 @@
#include "../VAAudioReproductionModule.h"
#include "../VAAudioReproductionModuleRegistry.h"
#include "../../VACoreImpl.h"
#include "Eigen\dense"
#include "Eigen\SVD"
#include "Eigen\Jacobi"
#include <ITASampleFrame.h>
......@@ -47,7 +50,7 @@ public:
* for binaural downmix with related HRIR.
*/
void SetTrackedListener( const int iListenerID );
Eigen::MatrixXd CalculatePseudoInverse(Eigen::MatrixXd);
void UpdateScene( CVASceneState* pNewState );
private:
......
......@@ -66,7 +66,7 @@ void CVAAudioReproductionModuleRegistry::RegisterInternalCoreFactoryMethods()
// Ambisonics
#if( VACORE_WITH_REPRODUCTION_AMBISONICS == 1 )
RegisterReproductionDefaultFactory< CVAAmbisonicsReproduction>( "Ambisonics" );
RegisterReproductionDefaultFactory< CVAAmbisonicsReproduction>( "AmbisonicsReproduction" );
#endif // ( VACORE_WITH_REPRODUCTION_AMBISONICS == 1 )
// Binaural
......
#include "VAEigenUtils.h"
#include "VistaMath/VistaMathTools.h"
void VAEigenUtils::VAVec32Eigen(const VAVec3 vaIn, Eigen::Vector3d &eigenOut)
{
eigenOut(0) = vaIn.x;
eigenOut(1) = vaIn.y;
eigenOut(2) = vaIn.z;
}
void VAEigenUtils::Eigen2VAVec3(const Eigen::Vector3d eigenIn, VAVec3 &vaOut)
{
vaOut.y = eigenIn(0);
vaOut.z = eigenIn(1);
vaOut.x = eigenIn(2);
}
double VAEigenUtils::Eigen2AzimuthRAD(const Eigen::Vector3d eigenIn)
{
return std::acos(eigenIn(2) / eigenIn(0));
}
double VAEigenUtils::Eigen2AzimuthDEG(const Eigen::Vector3d eigenIn)
{
return std::acos(eigenIn(2) / eigenIn(0))/3.14159265359*180;
}
double VAEigenUtils::Eigen2ElevationDEG(const Eigen::Vector3d eigenIn)
{
return 0;
}
\ No newline at end of file
#pragma once
/*
* --------------------------------------------------------------------------------------------
*
* 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-2017
* VVVVVV AAA Institute of Technical Acoustics (ITA)
* VVVV AAA RWTH Aachen University
*
* --------------------------------------------------------------------------------------------
*/
/*#ifndef IW_VACORE_EIGENUTILS
#define IW_VACORE_EIGENUTILS
*/
#include <VACoreEvent.h>
#include <VAException.h>
#include <VAStruct.h>
#include <ITAException.h>
#include <ITAStringUtils.h>
#include <VistaBase/VistaExceptionBase.h>
#include <cassert>
#include <string>
#include <map>
#include "Eigen/Dense"
namespace VAEigenUtils
{
void VAVec32Eigen(const VAVec3 vaIn, Eigen::Vector3d &eigenOut);
void Eigen2VAVec3(const Eigen::Vector3d eigenIn, VAVec3 &vaOut);
double Eigen2AzimuthRAD(const Eigen::Vector3d eigenIn);
double Eigen2AzimuthDEG(const Eigen::Vector3d eigenIn);
double Eigen2ElevationDEG(const Eigen::Vector3d eigenIn);
};
......@@ -554,6 +554,7 @@ void CVACoreImpl::Initialize() {
*/
// Create output peak detector that uses patch bay output stream
m_pOutputStreamDetector = new ITAStreamDetector( m_pOutputPatchbay->GetOutputDatasource( iPhysicalHardwareOutput ) );
......
......@@ -381,7 +381,7 @@ private:
};
std::vector< CVAAudioRendererDesc > m_voRenderers;
class CVAAudioReproductionModuleDesc : public CVAAudioRendererInfo
class CVAAudioReproductionModuleDesc : public CVAAudioReproductionInfo
{
public:
IVAAudioReproductionModule* pInstance;
......@@ -407,7 +407,6 @@ private:
delete pInstance;
delete pInputDetector;
delete pOutputDetector;
pInputRecorder->GetFilePath();
delete pInputRecorder;
delete pOutputRecorder;
};
......
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