Skip to content
Snippets Groups Projects
Commit 40ce52b5 authored by Jonas Stienen's avatar Jonas Stienen
Browse files

Moving room compensation code to branch feature/room_compensation (Erik's...

Moving room compensation code to branch feature/room_compensation (Erik's code). This master branch is now back to initial state.
parent b41415fb
Branches
Tags
No related merge requests found
......@@ -22,6 +22,7 @@
#include <ITACTCDefinitions.h>
#include <atomic>
#include <string>
#include <vector>
......@@ -95,23 +96,6 @@ public:
};
//! Data class that describes a single wall
/**
* A Wall is described by four vertices (VistaVector3D), one for each
* corner of the wall and a VistaPlane.
*/
class ITA_CTC_API Wall
{
public:
Wall(const int ivertind1,const int ivertind2,const int ivertind3,const int ivertind4,const VistaVector3D& voNormVector, const std::vector<VistaVector3D*>& voCaveVertices);
~Wall();
bool calculateIntersection(const VistaRay& ray, VistaVector3D& intersectionPoint);
//VistaPlane m_oWallPlane;
VistaVector3D m_norm;
std::vector<VistaVector3D*> m_voCornerVertices;
};
//! NCTC configuration data class
/**
* This static configuration data has to be passed
......@@ -125,19 +109,12 @@ public:
{
public:
enum
{
OPTIMIZATION_NONE = 0, //!< No optimization
OPTIMIZATION_AIXCAVE_FULLY_CLOSED, //!< aixCAVE early reflection compensation (closed door)
OPTIMIZATION_AIXCAVE_PARTIALLY_OPEN, //!< aixCAVE early reflection compensation (partially opened door)
OPTIMIZATION_AIXCAVE_OPEN, //!< aixCAVE early reflection compensation (opened door)
};
int N; //!< Number of loudspeakers
int iCTCFilterLength; //!< CTC filter taps, i.e. 4096
double dSampleRate; //!< Sampling rate
float fSpeedOfSound; //!< Speed of sound, m/s
int iOptimization; //!< Optimizartion, i.e. aixCAVE early reflection compensation, see optimization enumeration above
int iOptimization; //!< Optimization algorithm (future work, see features/room_compensation)
class ITA_CTC_API Loudspeaker
{
......@@ -149,17 +126,6 @@ public:
};
std::vector< Loudspeaker > voLoudspeaker; //!< Loudspeaker of this setup
class ImageSource:public Loudspeaker
{
public:
ImageSource();
ImageSource(const Pose& oStaticPose, int order);
ImageSource(int order);
int m_order; //!< Order of Reflection of this VS
int m_iReflectedWallIdx; //!< index of wall this VS was reflected on
const ImageSource* m_oParentVS; //!< pointer to parent VS
};
};
//! Constructor
......@@ -289,22 +255,19 @@ public:
bool CalculateFilter( std::vector< ITAHDFTSpectra* >& vpSpectra );
//! Calculate the Wiener-Hopf factorization
void WienerHopfFactorization(ITAHDFTSpectrum* voSpecIn, ITAHDFTSpectrum* voSpecOutPlus, ITAHDFTSpectrum* voSpecOutMinus);
void WienerHopfFactorization( ITAHDFTSpectrum* voSpecIn, ITAHDFTSpectrum* voSpecOutPlus, ITAHDFTSpectrum* voSpecOutMinus );
protected:
private:
const Config m_oConfig; //!< CTC Configuration
ITAAtomicFloat m_fBeta; //!< Beta parameter (regularization)
std::atomic< float > m_fBeta; //!< Beta parameter (regularization)
std::vector< float > m_vfDelayTime; //!< Add a delay [seconds] to the resulting CTC filter (individual channels)
ITAAtomicInt m_iOptimization; //!< Optimization (see Config enum)
std::atomic <int > m_iOptimization; //!< Optimization (see Config enum)
const DAFFContentIR* m_pHRIR; //!< HRIR dataset pointer
Pose m_oHeadPose; //!< Current head Pose data
std::vector< std::vector< Config::ImageSource* >* > m_voImageSources; //!< Image Source Data
std::vector< Wall* > m_oCaveWalls; //!< CAVE walls data
std::vector< VistaVector3D* > m_voCaveVertices; //!< contains all corner indices of all CAVE walls
ITAFFT m_fft, m_ifft; //!< Internal FFT and IFFT transformations
ITASampleFrame m_sfCTC_temp; //!< Internal CTC helper
......@@ -317,17 +280,13 @@ private:
//! Adds a HRIR into the target filter
/**
* @param oLoudspeakerPose Pose of loudspeaker (or virtual source)
* @param bOutOfRange Indicator if the HRIR data for the required position is out of range
* @param sfTargetIR Target impulse response, where the HRIR will be placed by mul-adding with given gain
*
* @return True, if samples from HRIR could be copied into target filter, false, if target filter is too short
*/
* @param oLoudspeakerPose Pose of loudspeaker (or virtual source)
* @param bOutOfRange Indicator if the HRIR data for the required position is out of range
* @param sfTargetIR Target impulse response, where the HRIR will be placed by mul-adding with given gain
*
* @return True, if samples from HRIR could be copied into target filter, false, if target filter is too short
*/
bool AddHRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfTargetIR, bool& bOutOfRange, double dGain = 1.0f ) const;
void CalculateBRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfBRIR, bool& bOutOfRange, const int loudspeakerID ) const;
void GenerateImageSources(); //!< Calculate all image sources for a fixed geometry
void propagateVS(const Config::ImageSource* parent, std::vector<Config::ImageSource*>* thisSpeakersVS); //!< recursiv helper function for function "GenerateImageSources()"
void DetermineVisibleImageSources(const Pose& oHeadPose ,std::vector<Config::ImageSource*>* thisSpeakersVS,std::vector<Config::ImageSource*>* visibleVS ) const; //!< Determine which image sources are visibile for a given user position
friend class ITACTCStreamFilter;
};
......
......@@ -49,11 +49,6 @@ ITANCTC::ITANCTC( const Config& oNCTCConfig )
m_fft.plan( ITAFFT::FFT_R2C, l, m_sfCTC_temp[0].data(), (*m_vpHRTFs[0])[0]->data() );
m_ifft.plan( ITAFFT::IFFT_C2R, l, (*m_vpHRTFs[0])[0]->data(), m_sfCTC_temp[0].data() );
assert( m_oConfig.iOptimization >= 0 );
if( m_iOptimization > 0 )
{
GenerateImageSources();
}
}
ITANCTC::~ITANCTC()
......@@ -65,14 +60,7 @@ ITANCTC::~ITANCTC()
delete m_vpHelper2x2[i];
delete t, det;
for( size_t i = 0; i < m_voImageSources.size(); i++ )
for( size_t j = 0; j < m_voImageSources[ i ]->size(); j++ )
delete m_voImageSources[ i ]->at( j );
for( size_t i = 0; i < m_oCaveWalls.size(); i++ )
delete m_oCaveWalls[ i ];
return;
}
......@@ -150,137 +138,6 @@ bool ITANCTC::AddHRIR( const Pose& oDest, ITASampleFrame& sfDestHRIR, bool& bOut
return true;
}
void ITANCTC::CalculateBRIR( const Pose& oLoudspeakerPose, ITASampleFrame& sfBRIR, bool& bOutOfRange, const int loudspeakerID ) const
{
if( sfBRIR.channels() != 2 )
ITA_EXCEPT1( INVALID_PARAMETER, "Two channel BRIR expected" );
const int iOptimization = m_iOptimization; // Local copy of current optimization config
const int iCTCFilterLength = sfBRIR.length();
assert( m_voImageSources.size() > 0 && m_voImageSources[loudspeakerID-1]->size()>0);
// get vector of all VS of this speaker
std::vector<Config::ImageSource*>* thisSpeakersVS = m_voImageSources[loudspeakerID-1];
std::vector<Config::ImageSource*>* visibleVS = new std::vector<Config::ImageSource*>;
DetermineVisibleImageSources(this->GetHeadPose(),thisSpeakersVS,visibleVS );
// add original source hrtf
ITANCTC::AddHRIR(oLoudspeakerPose, sfBRIR, bOutOfRange, 1.00 );
// add VS hrtfs
for (int i = 0; i < visibleVS->size(); i++)
{
ITANCTC::AddHRIR(visibleVS->at(i)->oPose, sfBRIR, bOutOfRange, pow(0.97,visibleVS->at(i)->m_order) );
}
//m_pHRIR;
return;
}
void ITANCTC::GenerateImageSources()
{
// create list of all wall vertices
m_voCaveVertices.push_back(new VistaVector3D(-2.626f,0.0f,2.625f));
m_voCaveVertices.push_back(new VistaVector3D(2.626f,0.0f,2.625f));
m_voCaveVertices.push_back(new VistaVector3D(2.626f,0.0f,-2.625f));
m_voCaveVertices.push_back(new VistaVector3D(-2.626f,0.0f,-2.625f));
m_voCaveVertices.push_back(new VistaVector3D(-2.626f,3.3f,2.625f));
m_voCaveVertices.push_back(new VistaVector3D(2.626f,3.3f,2.625f));
m_voCaveVertices.push_back(new VistaVector3D(2.626f,3.3f,-2.625f));
m_voCaveVertices.push_back(new VistaVector3D(-2.626f,3.3f,-2.625f));
// right handed coordinate system!
m_oCaveWalls.push_back(new ITANCTC::Wall(0,1,2,3,VistaVector3D(0,1,0),m_voCaveVertices)); // ground
m_oCaveWalls.push_back(new ITANCTC::Wall(0,3,7,4,VistaVector3D(1,0,0),m_voCaveVertices)); // left wall
m_oCaveWalls.push_back(new ITANCTC::Wall(3,2,6,7,VistaVector3D(0,0,1),m_voCaveVertices)); // back wall
m_oCaveWalls.push_back(new ITANCTC::Wall(1,2,6,5,VistaVector3D(-1,0,0),m_voCaveVertices)); // right wall
m_oCaveWalls.push_back(new ITANCTC::Wall(0,1,5,4,VistaVector3D(0,0,-1),m_voCaveVertices)); // front wall
//TODO ebenen richtig setzen
// for each speaker
for( int n=0; n<GetN(); n++ )
{
m_voImageSources.push_back(new std::vector<Config::ImageSource*>);
const Pose& oLoudspeakerPose = GetLoudspeakerPose( n+1 );
Config::ImageSource source(oLoudspeakerPose,0);
std::vector<Config::ImageSource*>* thisSpeakersVS = m_voImageSources[n];
propagateVS(&source,thisSpeakersVS); // calculate all image sources of the given speaker
}
}
void ITANCTC::propagateVS(const Config::ImageSource* parent, std::vector<Config::ImageSource*>* thisSpeakersVS)
{
if (parent->m_order >= 2) // stop calculation if order would be higher than 2
return;
// for each wall
for (int w=0; w < m_oCaveWalls.size(); w++)
{
// vs = parent - 2*distance*wall_norm
//float distance = m_oCaveWalls[w]->m_oWallPlane.CalcDistance( parent->oPose.vPos);
//float distance = (parent->oPose.vPos - m_oCaveWalls[w]->m_oWallPlane.GetXDir()) * m_oCaveWalls[w]->m_oWallPlane.GetNormVector();
float distance = (parent->oPose.vPos - *(m_oCaveWalls[w]->m_voCornerVertices[0]) ) * m_oCaveWalls[w]->m_norm;
if (distance < 0)
{
continue; //discard invalid VS
}
VistaVector3D norm = m_oCaveWalls[w]->m_norm;//m_oWallPlane.GetNormVector();
Config::ImageSource* newSource = new Config::ImageSource(parent->oPose,parent->m_order+1);
newSource->oPose.vPos = parent->oPose.vPos - 2* distance* norm;
newSource->m_iReflectedWallIdx = w;
if (parent->m_oParentVS == NULL)
newSource->m_oParentVS = NULL;
else
newSource->m_oParentVS = parent;
// add new image source
thisSpeakersVS->push_back(newSource);
// propagate new VS
propagateVS(newSource,thisSpeakersVS);
// TODO mirror direction of speaker
}
}
void ITANCTC::DetermineVisibleImageSources( const Pose& oHeadPose, std::vector<Config::ImageSource*>* thisSpeakersVS,std::vector<Config::ImageSource*>* visibleVS ) const
{
const Config::ImageSource* oTmpVSPointer;
// check visibility for each of the speaker's VS
for (int i = 0; i < thisSpeakersVS->size(); i ++)
{
bool visible = true; // assumption: VS is visible
VistaVector3D oIntersectionPoint = oHeadPose.vPos;
oTmpVSPointer = thisSpeakersVS->at(i);
// check line of sight between headPose and VS
do
{
VistaRay oTmpRay(oTmpVSPointer->oPose.vPos, oIntersectionPoint-oTmpVSPointer->oPose.vPos);
if (m_oCaveWalls[oTmpVSPointer->m_iReflectedWallIdx]->calculateIntersection(oTmpRay,oIntersectionPoint))
{
if (oTmpVSPointer->m_oParentVS != NULL)
oTmpVSPointer = oTmpVSPointer->m_oParentVS; // check if parent VS is visible as well
}
else
{
visible = false;
break; // stop checking -> VS is not visible
}
}
while (oTmpVSPointer->m_oParentVS != NULL);
if (visible) // if assumption still holds
{
visibleVS->push_back( thisSpeakersVS->at(i));
}
}
}
const ITANCTC::Pose& ITANCTC::GetLoudspeakerPose( int iLoudspeakerID ) const
{
if( iLoudspeakerID > GetN() )
......@@ -301,12 +158,8 @@ bool ITANCTC::CalculateFilter( std::vector< ITAHDFTSpectra* >& vpCTCFilter )
switch( m_iOptimization )
{
case Config::OPTIMIZATION_AIXCAVE_FULLY_CLOSED:
case Config::OPTIMIZATION_AIXCAVE_PARTIALLY_OPEN:
case Config::OPTIMIZATION_AIXCAVE_OPEN:
CalculateBRIR( GetLoudspeakerPose( n+1 ), m_sfCTC_temp, bOutOfRange, n+1 );
break;
case Config::OPTIMIZATION_NONE:
// Here comes more if ready ... see feature/room_compensation branch
case 0:
default:
if( AddHRIR( GetLoudspeakerPose( n+1 ), m_sfCTC_temp, bOutOfRange ) == false )
return false;
......@@ -530,8 +383,6 @@ std::vector< float > ITANCTC::GetDelayTime()
void ITANCTC::SetOptimization( int iOptimization )
{
if( m_voImageSources.size() == 0 && iOptimization > 0 )
GenerateImageSources();
m_iOptimization = iOptimization;
}
......@@ -554,6 +405,7 @@ ITANCTC::Pose ITANCTC::GetHeadPose() const
return m_oHeadPose;
}
// --- Loudspeaker ---
ITANCTC::Config::Loudspeaker::Loudspeaker()
......@@ -567,30 +419,8 @@ ITANCTC::Config::Loudspeaker::Loudspeaker( const Pose& oStaticPose )
oPose = oStaticPose;
}
// --- ImageSource ---
ITANCTC::Config::ImageSource::ImageSource( )
{
m_order = -1; //invalid order
m_oParentVS = NULL; //no parent
m_iReflectedWallIdx = -1; //invalid wall id
}
ITANCTC::Config::ImageSource::ImageSource( int order )
{
m_order = order;
m_oParentVS = NULL; //no parent
m_iReflectedWallIdx = -1; //invalid wall id
}
ITANCTC::Config::ImageSource::ImageSource(const Pose& oStaticPose, int order)
{
oPose = oStaticPose;
m_order = order;
m_oParentVS = NULL; //no parent
m_iReflectedWallIdx = -1; //invalid wall id
}
// --= Pose =--
// --- Pose ---
ITANCTC::Pose& ITANCTC::Pose::operator=( const ITANCTC::Pose& oPoseRHS )
{
......@@ -617,50 +447,3 @@ void ITANCTC::Pose::SetOrientationYPRdeg( double fYaw, double fPitch, double fRo
return;
}
// --= Wall =--
ITANCTC::Wall::Wall( const int iWallind1,const int iWallind2,const int iWallind3,const int iWallind4,const VistaVector3D& voNormVector, const std::vector<VistaVector3D*>& voCaveVertices)
{
// ^ y
// |
// OpenGl Coordinates --> x
// /
// v z
// copy corner vertices
m_voCornerVertices.push_back(voCaveVertices[iWallind1]);
m_voCornerVertices.push_back(voCaveVertices[iWallind2]);
m_voCornerVertices.push_back(voCaveVertices[iWallind3]);
m_voCornerVertices.push_back(voCaveVertices[iWallind4]);
// create plane with given norm vector
// right handed coordinate system
//m_oWallPlane = VistaPlane(VistaVector3D(0.0,0.0,0.0),*m_voCornerVertices[0],*m_voCornerVertices[1],voNormVector);
//m_oWallPlane = VistaPlane(*m_voCornerVertices[0],((*m_voCornerVertices[1]) - (*m_voCornerVertices[0])).GetNormalized(),((*m_voCornerVertices[2]) - (*m_voCornerVertices[0])).GetNormalized(),voNormVector);
m_norm = voNormVector;
//m_oWallPlane = VistaPlane(*m_voCornerVertices[0],VistaVector3D(0.0,0.0,-1.0),VistaVector3D(1.0,0.0,0.0),voNormVector);
//float f = m_oWallPlane.CalcDistanceToZero();
}
ITANCTC::Wall::~Wall()
{
}
bool ITANCTC::Wall::calculateIntersection(const VistaRay& ray, VistaVector3D& intersectionPoint)
{
VistaVector3D po=intersectionPoint;
bool t1 =ray.IntersectionTriangle(*(this->m_voCornerVertices[0]),*(this->m_voCornerVertices[1]),*(this->m_voCornerVertices[2]),intersectionPoint);
bool t2 = ray.IntersectionTriangle(*(this->m_voCornerVertices[0]),*(this->m_voCornerVertices[2]),*(this->m_voCornerVertices[3]),po);
if (ray.IntersectionTriangle(*(this->m_voCornerVertices[0]),*(this->m_voCornerVertices[1]),*(this->m_voCornerVertices[2]),intersectionPoint) || ray.IntersectionTriangle(*(this->m_voCornerVertices[0]),*(this->m_voCornerVertices[2]),*(this->m_voCornerVertices[3]),intersectionPoint))
{
return true;
}
else
{
return false;
}
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ int main( int argc, char* argv[] )
oNCTCConfig.dSampleRate = 44.1e3;
oNCTCConfig.fSpeedOfSound = 344.0f;
//oNCTCConfig.iOptimization = ITANCTC::Config::OPTIMIZATION_NONE;
oNCTCConfig.iOptimization = ITANCTC::Config::OPTIMIZATION_AIXCAVE_FULLY_CLOSED;
//oNCTCConfig.iOptimization = ITANCTC::Config::OPTIMIZATION_AIXCAVE_FULLY_CLOSED;
// 4 loudspeaker configuration (square with LS in corners facing center point)
/*float fHeight = 3.2f; // meter
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment