Improving propagation models and extending filter engine with material manager

parent 31f3d4d4
......@@ -20,14 +20,12 @@ set( ITAPropagationModelsHeader
"include/ITAPropagationModels/Definitions.h"
"include/ITAPropagationModels/DiffractionFilter.h"
"include/ITAPropagationModels/FilterEngine.h"
"include/ITAPropagationModels/FilterGenerator.h"
"include/ITAPropagationModels/Maekawa.h"
"include/ITAPropagationModels/Svensson.h"
"include/ITAPropagationModels/UTD.h"
)
set( ITAPropagationModelsSources
"src/ITAPropagationModels/FilterEngine.cpp"
"src/ITAPropagationModels/FilterGenerator.cpp"
"src/ITAPropagationModels/Maekawa.cpp"
"src/ITAPropagationModels/Svensson.cpp"
"src/ITAPropagationModels/UTD.cpp"
......
......@@ -25,17 +25,18 @@
// ITA includes
#include <ITAGeo/Base.h>
#include <ITAGeo/Material//Manager.h>
#include <ITAHDFTSpectra.h>
#include <ITAHDFTSpectrum.h>
// STL includes
#include <vector>
namespace ITAPropagationModels
{
using namespace std;
//! Transfer function filter generator for propagation paths
/**
* Generates transfer functions in the frequency-domain that
......@@ -98,7 +99,7 @@ namespace ITAPropagationModels
void ApplyTransmissionModel( ITAGeo::CPropagationPathList& oPathList, int iModel = -1 ); // @todo
//! Generate multi-channel propagation path (for multi-channel receiver directivitiy)
//! Generate multi-channel propagation path (for multi-channel receiver directivity)
/**
* @todo AER
*/
......@@ -112,6 +113,12 @@ namespace ITAPropagationModels
Generate( oPathList, oTF );
};
//! Sets a connection to the material manager
void SetMaterialManager( const ITAGeo::CMaterialManager* pMaterialManager );
// Returns pointer to material manager or null
const ITAGeo::CMaterialManager* GetMaterialManager() const;
private:
unique_ptr<ITABase::CHDFTSpectra> m_pAccumulatedSpectra; //!< Gathered propagation paths from list
......@@ -128,7 +135,7 @@ namespace ITAPropagationModels
};
const ITAGeo::CMaterialManager* m_pMaterialManager;
const double m_dHumidity = 80.0;
const double m_dTemperature = 20.0;
......
/*
* ----------------------------------------------------------------
*
* ITA geometrical acoustics
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2018
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_FILTER_GENERATOR
#define INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_FILTER_GENERATOR
#include "Base.h"
#include "Definitions.h"
#include "DiffractionFilter.h"
// ITA includes
#include <ITAGeo/Base.h>
#include <ITAHDFTSpectra.h>
#include <ITAHDFTSpectrum.h>
// STL includes
#include <vector>
namespace ITAPropagationModels
{
//! Transfer function filter generator for propagation paths
/**
* Generates transfer functions in the frequency-domain that
* can be used as filters, e.g. for auralization.
*/
class ITA_PROPAGATION_MODELS_API CTFGenerator
{
public:
//! Construct a generator with predetermined output channels, e.g. for binaural or SH filters
/**
* @param[in] iNumOutputChannels Number of output channels
* @param[in] iDFTSize Length of the DFT used to construct and combine filter components
* @param[in] fSamplingRate Filer sampling rate
*/
CTFGenerator( const int iNumOutputChannels, const int iDFTSize = 128, const float fSamplingRate = 44100.0f );
//! Cunstruct a generator with matching properties of a target spectrum
inline CTFGenerator( const ITABase::CHDFTSpectrum& pTransferFunction )
: CTFGenerator( 1, pTransferFunction.GetDFTSize(), pTransferFunction.GetSampleRate() )
{
};
//! Cunstruct a generator with matching properties of multi-channel target spectra
CTFGenerator( const ITABase::CHDFTSpectra& pTransferFunctions )
: CTFGenerator( pTransferFunctions.GetNumChannels(), pTransferFunctions.GetDFTSize(), pTransferFunctions.GetSampleRate() )
{
};
//! Generate a single-channel transfer function
inline void GenerateTF( ITABase::CHDFTSpectrum& pTransferFunction )
{
const std::vector< ITABase::CHDFTSpectrum* > vpSpectra = { &( pTransferFunction ) };
ITABase::CHDFTSpectra oTF( vpSpectra );
GenerateTF( oTF );
};
//! Generate a multi-channel transfer function
inline void GenerateTF( ITABase::CHDFTSpectra& pTransferFunctions );
private:
};
}
#endif // INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_FILTER_GENERATOR
#include <ITAPropagationModels/FilterGenerator.h>
#include <ITAPropagationModels/FilterEngine.h>
// ITA includes
#include <ITAException.h>
......@@ -13,7 +13,6 @@
// STL includes
#include <assert.h>
#include <stdio.h>
#include "..\..\include\ITAPropagationModels\FilterEngine.h"
//Spline
......@@ -23,6 +22,7 @@
using namespace ITAPropagationModels;
CFilterEngine::CFilterEngine()
:m_pMaterialManager( nullptr )
{
}
......@@ -30,31 +30,31 @@ CFilterEngine::~CFilterEngine()
{
}
int CFilterEngine::GetNumSensorChannels(const ITAGeo::CPropagationPathList& oPathList)
int CFilterEngine::GetNumSensorChannels( const ITAGeo::CPropagationPathList& oPathList )
{
//Check for correct structur of oPathList
if(!HasSameSensorAnchor(oPathList))
ITA_EXCEPT1(INVALID_PARAMETER, "The propagation path list has multiple sensor anchors or last anchor of paths is not a sensor.");
if( !HasSameSensorAnchor( oPathList ) )
ITA_EXCEPT1( INVALID_PARAMETER, "The propagation path list has multiple sensor anchors or last anchor of paths is not a sensor." );
//Cast the sensor that is always the last propagation anchor of a path
auto pSensor = std::dynamic_pointer_cast<ITAGeo::CSensor>(oPathList[0][oPathList[0].size() - 1]);
auto pSensor = std::dynamic_pointer_cast< ITAGeo::CSensor >( oPathList[ 0 ][ oPathList[ 0 ].size() - 1 ] );
return pSensor->iNumChannels;
}
bool CFilterEngine::HasSameSensorAnchor(const ITAGeo::CPropagationPathList& oPathList)
bool CFilterEngine::HasSameSensorAnchor( const ITAGeo::CPropagationPathList& oPathList )
{
shared_ptr<ITAGeo::CSensor> pSensor = nullptr;
//Last anchor of the paths must be a sensor and always the same sensor
for (auto& oPath : oPathList)
for( auto& oPath : oPathList )
{
if (oPath[oPath.size() - 1]->iAnchorType == ITAGeo::CPropagationAnchor::ACOUSTIC_SENSOR)
if( oPath[ oPath.size() - 1 ]->iAnchorType == ITAGeo::CPropagationAnchor::ACOUSTIC_SENSOR )
{
if (pSensor == nullptr)
pSensor = std::dynamic_pointer_cast<ITAGeo::CSensor>(oPath[oPath.size() - 1]);
else if (pSensor != oPath[oPath.size() - 1])
if( pSensor == nullptr )
pSensor = std::dynamic_pointer_cast< ITAGeo::CSensor >( oPath[ oPath.size() - 1 ] );
else if( pSensor != oPath[ oPath.size() - 1 ] )
return false; // not the same sensor
}
else
......@@ -67,68 +67,65 @@ bool CFilterEngine::HasSameSensorAnchor(const ITAGeo::CPropagationPathList& oPat
return true;
}
void CFilterEngine::ApplyAcousticModels(ITAGeo::CPropagationPathList & oPathList)
void CFilterEngine::ApplyAcousticModels( ITAGeo::CPropagationPathList & oPathList )
{
//Apply emitter model
ApplyEmitterModel(oPathList);
ApplyEmitterModel( oPathList );
//Apply reflection model
ApplyReflectionModel(oPathList);
ApplyReflectionModel( oPathList );
//Apply diffraction model
ApplyDiffractionModel(oPathList);
ApplyDiffractionModel( oPathList );
//Apply sensor model
ApplySensorModel(oPathList);
ApplySensorModel( oPathList );
}
void CFilterEngine::ApplyDiffractionModel(ITAGeo::CPropagationPathList & oPathList, int iModel)
void CFilterEngine::ApplyDiffractionModel( ITAGeo::CPropagationPathList & oPathList, int iModel )
{
int iDiffractionModel;
if (iModel == -1)
iDiffractionModel = m_DefaultValues::iDiffractionModel;
int iDiffractionModelResolution;
if( iModel == -1 )
iDiffractionModelResolution = m_DefaultValues::iDiffractionModel;
else
iDiffractionModel = iModel;
iDiffractionModelResolution = iModel;
for (auto& oPath : oPathList)
for( auto& oPath : oPathList )
{
//Iterate over all anchors except the first and last anchor
for (size_t i = 1; i <= oPath.size() - 2; i++)
for( size_t i = 1; i <= oPath.size() - 2; i++ )
{
auto& pLastAnchor = oPath[i - 1];
auto& pCurrentAnchor = oPath[i];
auto& pNextAnchor = oPath[i + 1];
auto& pLastAnchor = oPath[ i - 1 ];
auto& pCurrentAnchor = oPath[ i ];
auto& pNextAnchor = oPath[ i + 1 ];
//If the anchor is a diffraction and the acoustic material is not set yet, set it to default values
if ((pCurrentAnchor->iAnchorType == ITAGeo::CPropagationAnchor::DIFFRACTION_OUTER_APEX ||
if( ( pCurrentAnchor->iAnchorType == ITAGeo::CPropagationAnchor::DIFFRACTION_OUTER_APEX ||
pCurrentAnchor->iAnchorType == ITAGeo::CPropagationAnchor::DIFFRACTION_INNER_APEX ) && ( pCurrentAnchor->pAcousticMaterial == NULL ) )
{
auto pApex = std::dynamic_pointer_cast<ITAGeo::CITADiffractionWedgeApertureBase>(pCurrentAnchor);
auto pApex = std::dynamic_pointer_cast< ITAGeo::CITADiffractionWedgeApertureBase >( pCurrentAnchor );
if (iDiffractionModel == ITAGeo::IAcousticMaterial::THIRD_OCTAVE)
if( iDiffractionModelResolution == ITAGeo::IAcousticMaterial::THIRD_OCTAVE )
{
auto pAcousticMaterial = make_shared<ITAGeo::CThirdOctaveMaterial>();
auto vfFrequencies = pAcousticMaterial->oAbsorptionCoefficients.GetCenterFrequencies();
vector<float> vfAbsorptionCoeffs;
for (auto fFrequency : vfFrequencies)
for( size_t i = 0; i < vfFrequencies.size(); i++ )
{
double dDiffractionFactor;
auto fFrequency = vfFrequencies[ i ];
//TODO:Change diffraction calculation, just for testing
// TODO: Change diffraction calculation, just for testing
double dDirectLength, dDetourLength;
Maekawa::GetDirectLengthAndDetourLength(pLastAnchor->v3InteractionPoint, pNextAnchor->v3InteractionPoint, pApex, dDirectLength, dDetourLength);
dDiffractionFactor = Maekawa::CalculateDiffractionFactor(dDirectLength, dDetourLength, fFrequency, ITAConstants::SPEED_OF_SOUND_F);
Maekawa::GetDirectLengthAndDetourLength( pLastAnchor->v3InteractionPoint, pNextAnchor->v3InteractionPoint, pApex, dDirectLength, dDetourLength );
const double dDiffractionFactor = Maekawa::CalculateDiffractionFactor( dDirectLength, dDetourLength, fFrequency, ITAConstants::SPEED_OF_SOUND_F );
//Absorption coefficient alpha = 1 - |D|^2
vfAbsorptionCoeffs.push_back(1.0f - pow(dDiffractionFactor,2));
// Absorption coefficient alpha = 1 - |D|^2
const float fAlpha = float( 1.0f - pow( dDiffractionFactor, 2 ) );
pAcousticMaterial->oAbsorptionCoefficients.SetValue( i, fAlpha );
}
pAcousticMaterial->oAbsorptionCoefficients.SetMagnitudes(vfAbsorptionCoeffs);
pApex->pAcousticMaterial = pAcousticMaterial;
}
else
......@@ -140,22 +137,22 @@ void CFilterEngine::ApplyDiffractionModel(ITAGeo::CPropagationPathList & oPathLi
}
}
void CFilterEngine::ApplyReflectionModel(ITAGeo::CPropagationPathList & oPathList, int iModel)
void CFilterEngine::ApplyReflectionModel( ITAGeo::CPropagationPathList & oPathList, int iModel )
{
int iReflectionModel;
if (iModel == -1)
if( iModel == -1 )
iReflectionModel = m_DefaultValues::iReflectionModel;
else
iReflectionModel = iModel;
for (auto& oPath : oPathList)
for( auto& oPath : oPathList )
{
for (auto& pAnchor : oPath)
for( auto& pAnchor : oPath )
{
//If the anchor is a reflection and the acoustic material is not set yet, set it to default values
if ((pAnchor->iAnchorType == ITAGeo::CPropagationAnchor::SPECULAR_REFLECTION) && (pAnchor->pAcousticMaterial == NULL))
if( ( pAnchor->iAnchorType == ITAGeo::CPropagationAnchor::SPECULAR_REFLECTION ) && ( pAnchor->pAcousticMaterial == NULL ) )
{
if (iReflectionModel == ITAGeo::IAcousticMaterial::SCALAR)
if( iReflectionModel == ITAGeo::IAcousticMaterial::SCALAR )
{
//Set material with default values(current reflection factor: 0.7. See constructor of CScalarMaterial)
pAnchor->pAcousticMaterial = make_shared<ITAGeo::CScalarMaterial>();
......@@ -169,30 +166,30 @@ void CFilterEngine::ApplyReflectionModel(ITAGeo::CPropagationPathList & oPathLis
}
}
void ITAPropagationModels::CFilterEngine::ApplyEmitterModel(ITAGeo::CPropagationPathList & oPathList, int iModel)
void ITAPropagationModels::CFilterEngine::ApplyEmitterModel( ITAGeo::CPropagationPathList & oPathList, int iModel )
{
int iEmitterModel;
if (iModel == -1)
if( iModel == -1 )
iEmitterModel = m_DefaultValues::iEmitterModel;
else
iEmitterModel = iModel;
//Apply the emitter acoustic material. The emitter is always the first anchor of the propagation paths.
for (auto& oPath : oPathList)
for( auto& oPath : oPathList )
{
//If the anchor is a reflection and the acoustic material is not set yet, set it to default values
if (oPath[0]->iAnchorType == ITAGeo::CPropagationAnchor::ACOUSTIC_EMITTER)
if( oPath[ 0 ]->iAnchorType == ITAGeo::CPropagationAnchor::ACOUSTIC_EMITTER )
{
if (oPath[0]->pAcousticMaterial == NULL)
if( oPath[ 0 ]->pAcousticMaterial == NULL )
{
if (iEmitterModel == ITAGeo::IAcousticMaterial::SCALAR)
if( iEmitterModel == ITAGeo::IAcousticMaterial::SCALAR )
{
//Set material with factor 1.0
auto pAcousticMaterial = make_shared<ITAGeo::CScalarMaterial>();
pAcousticMaterial->cdTransmissionFactor = 1.0f;
pAcousticMaterial->cdReflectionFactor = 0.0f;
oPath[0]->pAcousticMaterial = pAcousticMaterial;
oPath[ 0 ]->pAcousticMaterial = pAcousticMaterial;
}
else //TODO: add cases like if (m_DefaultValues::iEmitterModel == ITAGeo::IAcousticMaterial::THIRD_OCTAVE)
{
......@@ -202,7 +199,7 @@ void ITAPropagationModels::CFilterEngine::ApplyEmitterModel(ITAGeo::CPropagation
}
else
{
ITA_EXCEPT1(INVALID_PARAMETER, "The propagation paths must always start with an emitter anchor.");
ITA_EXCEPT1( INVALID_PARAMETER, "The propagation paths must always start with an emitter anchor." );
}
}
......@@ -210,34 +207,34 @@ void ITAPropagationModels::CFilterEngine::ApplyEmitterModel(ITAGeo::CPropagation
}
void ITAPropagationModels::CFilterEngine::ApplySensorModel(ITAGeo::CPropagationPathList & oPathList, int iModel)
void ITAPropagationModels::CFilterEngine::ApplySensorModel( ITAGeo::CPropagationPathList & oPathList, int iModel )
{
//Check for correct structur of oPathList
if (!HasSameSensorAnchor(oPathList))
ITA_EXCEPT1(INVALID_PARAMETER, "The propagation path list has multiple sensor anchors or last anchor of paths is not a sensor.");
if( !HasSameSensorAnchor( oPathList ) )
ITA_EXCEPT1( INVALID_PARAMETER, "The propagation path list has multiple sensor anchors or last anchor of paths is not a sensor." );
int iSensorModel;
if (iModel == -1)
if( iModel == -1 )
iSensorModel = m_DefaultValues::iSensorModel;
else
iSensorModel = iModel;
//Because, the sensor is always the same anchor, only the first reference must be checked and eventually set
auto& oPath = oPathList[0];
auto& oPath = oPathList[ 0 ];
//Apply the sensor acoustic material. The sensor is always the last anchor of the propagation paths
if (oPath[oPath.size() - 1]->pAcousticMaterial == NULL)
if( oPath[ oPath.size() - 1 ]->pAcousticMaterial == NULL )
{
if (iSensorModel == ITAGeo::IAcousticMaterial::SCALAR)
if( iSensorModel == ITAGeo::IAcousticMaterial::SCALAR )
{
//Set material with factor 1.0
auto pAcousticMaterial = make_shared<ITAGeo::CScalarMaterial>();
pAcousticMaterial->cdTransmissionFactor = 1.0f;
pAcousticMaterial->cdReflectionFactor = 0.0f;
oPath[oPath.size() - 1]->pAcousticMaterial = pAcousticMaterial;
oPath[ oPath.size() - 1 ]->pAcousticMaterial = pAcousticMaterial;
}
else //TODO: add cases like if (m_DefaultValues::iSensorModel == ITAGeo::IAcousticMaterial::THIRD_OCTAVE)
{
......@@ -246,10 +243,20 @@ void ITAPropagationModels::CFilterEngine::ApplySensorModel(ITAGeo::CPropagationP
}
}
void ITAPropagationModels::CFilterEngine::SetMaterialManager( const ITAGeo::CMaterialManager* pMaterialManager )
{
m_pMaterialManager = pMaterialManager;
}
const ITAGeo::CMaterialManager* ITAPropagationModels::CFilterEngine::GetMaterialManager() const
{
return m_pMaterialManager;
}
//TODO: delete pragma warning after implementation of function
#pragma warning( push )
#pragma warning( disable : 4100)
void CFilterEngine::ApplyTransmissionModel(ITAGeo::CPropagationPathList & oPathList, int iModel)
void CFilterEngine::ApplyTransmissionModel( ITAGeo::CPropagationPathList & oPathList, int iModel )
{
ITA_EXCEPT_NOT_IMPLEMENTED;
}
......@@ -257,20 +264,20 @@ void CFilterEngine::ApplyTransmissionModel(ITAGeo::CPropagationPathList & oPathL
#pragma warning( pop )
void CFilterEngine::Generate(const ITAGeo::CPropagationPathList & oPathList, ITABase::CHDFTSpectra & oHDFTSpectra)
void CFilterEngine::Generate( const ITAGeo::CPropagationPathList & oPathList, ITABase::CHDFTSpectra & oHDFTSpectra )
{
//Check for correct structur of oPathList
if (!HasSameSensorAnchor(oPathList))
ITA_EXCEPT1(INVALID_PARAMETER, "The propagation path list has more than multiple sensor anchors or last anchor of paths is not a sensor.");
if( !HasSameSensorAnchor( oPathList ) )
ITA_EXCEPT1( INVALID_PARAMETER, "The propagation path list has more than multiple sensor anchors or last anchor of paths is not a sensor." );
//Initialize the path spectra
m_pTempPropPathSpectra = make_unique<ITABase::CHDFTSpectra>((float)oHDFTSpectra.GetSampleRate(), oHDFTSpectra.GetNumChannels(), oHDFTSpectra.GetDFTSize(), true);
m_pAccumulatedSpectra = make_unique<ITABase::CHDFTSpectra>((float)oHDFTSpectra.GetSampleRate(), oHDFTSpectra.GetNumChannels(), oHDFTSpectra.GetDFTSize(), true);
m_pTempPropPathSpectra = make_unique<ITABase::CHDFTSpectra>( ( float ) oHDFTSpectra.GetSampleRate(), oHDFTSpectra.GetNumChannels(), oHDFTSpectra.GetDFTSize(), true );
m_pAccumulatedSpectra = make_unique<ITABase::CHDFTSpectra>( ( float ) oHDFTSpectra.GetSampleRate(), oHDFTSpectra.GetNumChannels(), oHDFTSpectra.GetDFTSize(), true );
for (auto& oPath : oPathList)
for( auto& oPath : oPathList )
{
//Path length
float fPathLength = (float)oPath.GetLength();
float fPathLength = ( float ) oPath.GetLength();
//For the combination of all scalar filter components
float fScalarMagnitude = 1.0f;
......@@ -284,37 +291,37 @@ void CFilterEngine::Generate(const ITAGeo::CPropagationPathList & oPathList, ITA
//Air attenuation according to ISO9613-1
ITABase::CThirdOctaveFactorMagnitudeSpectrum oThirdOctAbsorption;
ITABase::ISO9613::AtmosphericAbsorption(oThirdOctAbsorption, fPathLength, m_dTemperature, m_dHumidity);
ITABase::ISO9613::AtmosphericAbsorption( oThirdOctAbsorption, fPathLength, m_dTemperature, m_dHumidity );
//Multiply the transmissionfactor of the air attenuation alpha: sqrt(1-|alpha|)
for (int iFrequencyIndex = 0; iFrequencyIndex < oThirdOctFactors.GetNumBands(); iFrequencyIndex++)
for( int iFrequencyIndex = 0; iFrequencyIndex < oThirdOctFactors.GetNumBands(); iFrequencyIndex++ )
{
oThirdOctFactors[iFrequencyIndex] *= sqrt(1 - abs(oThirdOctAbsorption[iFrequencyIndex]));
oThirdOctFactors[ iFrequencyIndex ] *= sqrt( 1 - abs( oThirdOctAbsorption[ iFrequencyIndex ] ) );
}
//Set scalar and third octave filter components of the propagation anchors
for (auto& pAnchor : oPath)
for( auto& pAnchor : oPath )
{
if (pAnchor->pAcousticMaterial->GetType() == ITAGeo::IAcousticMaterial::SCALAR)
if( pAnchor->pAcousticMaterial->GetType() == ITAGeo::IAcousticMaterial::SCALAR )
{
//Type cast of the acoustic material
auto pScalarMaterial = dynamic_pointer_cast<ITAGeo::CScalarMaterial>(pAnchor->pAcousticMaterial);
auto pScalarMaterial = dynamic_pointer_cast< ITAGeo::CScalarMaterial >( pAnchor->pAcousticMaterial );
if(pAnchor->iAnchorType == ITAGeo::CPropagationAnchor::SPECULAR_REFLECTION)
fScalarMagnitude *= (float) abs(pScalarMaterial->cdReflectionFactor);
if( pAnchor->iAnchorType == ITAGeo::CPropagationAnchor::SPECULAR_REFLECTION )
fScalarMagnitude *= ( float ) abs( pScalarMaterial->cdReflectionFactor );
else
fScalarMagnitude *= (float) abs(pScalarMaterial->cdTransmissionFactor);
fScalarMagnitude *= ( float ) abs( pScalarMaterial->cdTransmissionFactor );
}
if (pAnchor->pAcousticMaterial->GetType() == ITAGeo::IAcousticMaterial::THIRD_OCTAVE)
if( pAnchor->pAcousticMaterial->GetType() == ITAGeo::IAcousticMaterial::THIRD_OCTAVE )
{
//Type cast of the acoustic material
auto pThirdOctaveMaterial = dynamic_pointer_cast<ITAGeo::CThirdOctaveMaterial>(pAnchor->pAcousticMaterial);
auto pThirdOctaveMaterial = dynamic_pointer_cast< ITAGeo::CThirdOctaveMaterial >( pAnchor->pAcousticMaterial );
//Multiply the scale values of the respective bands
for (int i = 0; i < pThirdOctaveMaterial->GetNumBands(); i++)
for( int i = 0; i < pThirdOctaveMaterial->GetNumBands(); i++ )
{
oThirdOctFactors[i] *= pThirdOctaveMaterial->GetTransmissionFactor(i);
oThirdOctFactors[ i ] *= pThirdOctaveMaterial->GetTransmissionFactor( i );
}
}
}
......@@ -324,36 +331,38 @@ void CFilterEngine::Generate(const ITAGeo::CPropagationPathList & oPathList, ITA
//DFT coordinates for the respective frequencies
vector<float> vfDFTCoordinatesIn;
int iHDFTSize = (*m_pTempPropPathSpectra)[0]->GetSize();
int iHDFTSize = ( *m_pTempPropPathSpectra )[ 0 ]->GetSize();
//Get the corresponding DFT coordinates from the third octave coordinates
for (auto& fFreq : ITABase::CThirdOctaveGainMagnitudeSpectrum::GetCenterFrequencies())
for( auto& fFreq : ITABase::CThirdOctaveGainMagnitudeSpectrum::GetCenterFrequencies() )
{
vfDFTCoordinatesIn.push_back(fFreq*(iHDFTSize - 1) / ( (float) oHDFTSpectra.GetSampleRate() / 2));
vfDFTCoordinatesIn.push_back( fFreq*( iHDFTSize - 1 ) / ( ( float ) oHDFTSpectra.GetSampleRate() / 2 ) );
}
//Combine all magnitudes without the eventually existent directivity of the emitter/sensor
for (int iChannel = 0; iChannel < m_pTempPropPathSpectra->GetNumChannels(); iChannel++)
for( int iChannel = 0; iChannel < m_pTempPropPathSpectra->GetNumChannels(); iChannel++ )
{
if (iChannel == 0)
if( iChannel == 0 )
{
//Interpolate third octaves and multiply calculated values with third octave and scalar factors and add delay due to sound propagation
for (int i = 0; i < iHDFTSize; i++)
for( int i = 0; i < iHDFTSize; i++ )
{
const float fDFTSpectrum = spline_b_val( (int)vfDFTCoordinatesIn.size(), &vfDFTCoordinatesIn[0], &oThirdOctFactors[0], (float) i);
// @todo JST/AER: I think this is not correctly using the spline interp, especially tval should be a base value of given frequency, not integer/index
const float fDFTSpectrum = spline_b_val( ( int ) vfDFTCoordinatesIn.size(), &vfDFTCoordinatesIn[ 0 ], &oThirdOctFactors[ 0 ], ( float ) i );
const complex<float> fSpectrumData((*m_pTempPropPathSpectra)[0]->GetData()[2*i], (*m_pTempPropPathSpectra)[0]->GetData()[2*i+1]);
// @todo: m_pTempPropPathSpectra is untouched -> unity until here ...
const complex<float> fSpectrumData( ( *m_pTempPropPathSpectra )[ 0 ]->GetData()[ 2 * i ], ( *m_pTempPropPathSpectra )[ 0 ]->GetData()[ 2 * i + 1 ] );
complex<float> cfMultipliedSpectra = fSpectrumData * fDFTSpectrum * fScalarMagnitude;
(*m_pTempPropPathSpectra)[iChannel]->SetCoeff(i, cfMultipliedSpectra);
( *m_pTempPropPathSpectra )[ 0 ]->SetCoeff( i, cfMultipliedSpectra );
//Get the delay [samples] and calculate the phase shift according to the shift theorem
// DFT(x(k-Delta)) = exp(-j * omega_k * delta) * X(k) , with omega_k = 2 * pi * k / N
float fDelaySamples = fPathLength / m_fSpeedOfSound * (float)oHDFTSpectra.GetSampleRate();
float fDelaySamples = fPathLength / m_fSpeedOfSound * ( float ) oHDFTSpectra.GetSampleRate();
float fDelayPhase = -fDelaySamples* ITAConstants::TWO_PI_F * i / oHDFTSpectra.GetDFTSize();
(*m_pTempPropPathSpectra)[iChannel]->SetPhasePreserveMagnitude(i, fDelayPhase);
( *m_pTempPropPathSpectra )[ 0 ]->SetPhasePreserveMagnitude( i, fDelayPhase );
}
......@@ -361,15 +370,15 @@ void CFilterEngine::Generate(const ITAGeo::CPropagationPathList & oPathList, ITA
else
{
//Copy first channel to other channels
(*m_pTempPropPathSpectra)[iChannel]->Copy((*m_pTempPropPathSpectra)[0]);
( *m_pTempPropPathSpectra )[ iChannel ]->Copy( ( *m_pTempPropPathSpectra )[ 0 ] );
}
}
//Add current spectra to accumulated spectra
m_pAccumulatedSpectra->add(m_pTempPropPathSpectra.get());
m_pAccumulatedSpectra->add( m_pTempPropPathSpectra.get() );
}
oHDFTSpectra.CopyFrom(m_pAccumulatedSpectra.get());
oHDFTSpectra.CopyFrom( m_pAccumulatedSpectra.get() );
}
#include <ITAPropagationModels/FilterGenerator.h>
// ITA includes
#include <ITAException.h>
#include <ITAGeo/Halfedge/MeshModel.h>
// Vista includes
#include <VistaMath/VistaGeometries.h>
// STL includes
#include <assert.h>
#include <stdio.h>
using namespace ITAGeo;
using namespace ITAPropagationModels;
ITAPropagationModels::CTFGenerator::CTFGenerator( const int iNumOutputChannels, const int iDFTSize /*= 128 */, const float fSamplingRate )
{
}
void ITAPropagationModels::CTFGenerator::GenerateTF( ITABase::CHDFTSpectra& pTransferFunctions )
{
}
......@@ -18,7 +18,10 @@
#include <ITAPropagationModels/FilterEngine.h>
#include <ITAGeo/Base.h>
#include <ITAGeo/Material/Manager.h>
#include <ITAFFTUtils.h>
#include <ITAISO9613.h>
......@@ -28,80 +31,66 @@ using namespace ITAConstants;
using namespace ITAGeo;
using namespace ITAPropagationModels;
int main(int, char**)
int main( int, char** )
{
/*
|___x___|
/\
s \ r
\ /
___x___
|______|
// _______
// |___x___|
// / \
// s r
// \ /
// x______
// |______|
auto pSender = make_shared< CEmitter >(VistaVector3D(-2.0f, 0.0f, 0.0f));
auto pReceiver = make_shared< CSensor >(VistaVector3D(2.0f, 0.0f, 0.0f));
*/
auto pReflection = make_shared< CSpecularReflection >(VistaVector3D(0.0f, 2.0f, 0.0f));
auto pSender = make_shared< CEmitter >( VistaVector3D( -2.0f, 0.0f, 0.0f ) );
auto pReceiver = make_shared< CSensor >( VistaVector3D( 2.0f, 0.0f, 0.0f ) );
auto pDiffraction = make_shared< CITADiffractionOuterWedgeAperture >();