diff --git a/CMakeLists.txt b/CMakeLists.txt index fe85078c00e596db0cbba423c56617659c5a1a14..52bbd3805eec869c6d72554675018eda7c420a74 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,12 +22,14 @@ set( ITAPropagationModelsHeader "include/ITAPropagationModels/Maekawa.h" "include/ITAPropagationModels/Svensson.h" "include/ITAPropagationModels/UTD.h" + "include/ITAPropagationModels/Utils.h" ) set( ITAPropagationModelsSources "src/ITAPropagationModels/FilterEngine.cpp" "src/ITAPropagationModels/Maekawa.cpp" "src/ITAPropagationModels/Svensson.cpp" "src/ITAPropagationModels/UTD.cpp" + "src/ITAPropagationModels/Utils.cpp" ) diff --git a/include/ITAPropagationModels/Utils.h b/include/ITAPropagationModels/Utils.h new file mode 100644 index 0000000000000000000000000000000000000000..a26cd3f3965a50c8ba026b79be05fc0ccf038ae8 --- /dev/null +++ b/include/ITAPropagationModels/Utils.h @@ -0,0 +1,39 @@ +/* + * ---------------------------------------------------------------- + * + * ITA geometrical acoustics + * (c) Copyright Institute of Technical Acoustics (ITA) + * RWTH Aachen University, Germany, 2015-2018 + * + * ---------------------------------------------------------------- + * ____ __________ _______ + * // / //__ ___/ // _ | + * // / // / // /_| | + * // / // / // ___ | + * //__/ //__/ //__/ |__| + * + * ---------------------------------------------------------------- + * + */ + +#ifndef INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_UTILS +#define INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_UTILS + +#include "Definitions.h" + +#include <ITAConstants.h> +#include <ITAGeo/Base.h> + +namespace ITAPropagationModels +{ + namespace Utils + { + //! Estimates the required filter length on a best guess approach and by using path length and directivities / meterials into account + /** + * @note Set the minimum at least to the block length of your audio stream + */ + ITA_PROPAGATION_MODELS_API float EstimateFilterLengthSamples(const ITAGeo::CPropagationPath& oPath, const float fSampleRate, const float fMinimumSamples = 64, const float fSpeedOfSound = ITAConstants::DEFAULT_SPEED_OF_SOUND_F); + } +} + +#endif // INCLUDE_WATCHER_ITA_PROPAGATION_MODELS_UTILS diff --git a/src/ITAPropagationModels/Utils.cpp b/src/ITAPropagationModels/Utils.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8cf411fdeaaf9779da2ec262c29a3360c5d8b8ae --- /dev/null +++ b/src/ITAPropagationModels/Utils.cpp @@ -0,0 +1,45 @@ +#include <ITAPropagationModels/Utils.h> + +#include <ITAGeo/Base.h> +#include <ITAGeo/Material/Utils.h> +#include <ITAGeo/Directivity/Utils.h> +#include <ITAConstants.h> +#include <ITAException.h> + +#include <cassert> + +float ITAPropagationModels::Utils::EstimateFilterLengthSamples(const ITAGeo::CPropagationPath & oPath, const float fSampleRate, const float fMinimumSamples, const float fSpeedOfSound ) +{ + float fEstimatedFilterLengthSamples = fSampleRate * (float)oPath.GetLength(); + for (auto a : oPath) + { + switch (a->iAnchorType) + { + case ITAGeo::CPropagationAnchor::ACOUSTIC_EMITTER: + { + auto p = std::dynamic_pointer_cast<const ITAGeo::CEmitter>(a); + if (p->pDirectivity) + fEstimatedFilterLengthSamples += ITAGeo::Directivity::Utils::EstimateFilterLengthSamples(p->pDirectivity, fSampleRate, fSpeedOfSound); + } + case ITAGeo::CPropagationAnchor::ACOUSTIC_SENSOR: + { + auto p = std::dynamic_pointer_cast<const ITAGeo::CSensor>(a); + if (p->pDirectivity) + fEstimatedFilterLengthSamples += ITAGeo::Directivity::Utils::EstimateFilterLengthSamples(p->pDirectivity, fSampleRate, fSpeedOfSound); + } + case ITAGeo::CPropagationAnchor::SPECULAR_REFLECTION: + { + auto p = std::dynamic_pointer_cast<const ITAGeo::CSpecularReflection>(a); + if (p->pAcousticMaterial) + fEstimatedFilterLengthSamples += ITAGeo::Material::Utils::EstimateFilterLengthSamples(p->pAcousticMaterial, fSampleRate, fSpeedOfSound); + } + default: + { + if (fEstimatedFilterLengthSamples < fMinimumSamples) + fEstimatedFilterLengthSamples = fMinimumSamples; + } + } + } + + return fEstimatedFilterLengthSamples; +} diff --git a/tests/ReceiverDirectivityTest/ReceiverDirectivityTest.cpp b/tests/ReceiverDirectivityTest/ReceiverDirectivityTest.cpp index 33c2f23f173d5ebd97ac42fa647eadf730cba652..e3cd90c4790484cda91bfa5b0ebc64deb693fa7f 100644 --- a/tests/ReceiverDirectivityTest/ReceiverDirectivityTest.cpp +++ b/tests/ReceiverDirectivityTest/ReceiverDirectivityTest.cpp @@ -18,6 +18,7 @@ #include <ITAPropagationModels/FilterEngine.h> +#include <ITAPropagationModels/Utils.h> #include <ITAGeo/Base.h> #include <ITAGeo/Directivity/Base.h> @@ -30,6 +31,8 @@ using namespace ITAConstants; using namespace ITAGeo; using namespace ITAPropagationModels; +const float fSampleRate = 44.1e3f; + int main( int, char** ) { auto pSenderLeft = make_shared< CEmitter >(VistaVector3D(-2.0f, 0.0f, 0.0f)); @@ -51,13 +54,8 @@ int main( int, char** ) CFilterEngine oFilterEngine; - // Set filter length according to the maximum path length - const float fSpeedOfSound = DEFAULT_SPEED_OF_SOUND_F; // Approximation of speed of sound at ~20�C - const float fSampleRate = 44.1e3f; - int iFilterLengthSamples = (int)(oPathFromLeft.GetLength() / fSpeedOfSound * fSampleRate); - iFilterLengthSamples = int(iFilterLengthSamples + 4096); - - ITABase::CHDFTSpectra oTransmissionFilterLeft(fSampleRate, pReceiver->GetNumChannels(), iFilterLengthSamples); + int iFilterLengthSamples = (int) ceil(Utils::EstimateFilterLengthSamples(oPathFromLeft, fSampleRate)); + ITABase::CHDFTSpectra oTransmissionFilterLeft(fSampleRate, pReceiver->GetNumChannels(), iFilterLengthSamples ); bool bDFTDegreeTooSmallFlag; oFilterEngine.Generate(oPathFromLeft, oTransmissionFilterLeft, &bDFTDegreeTooSmallFlag); @@ -67,9 +65,6 @@ int main( int, char** ) ITAFFTUtils::Export(&oTransmissionFilterLeft, "SourceFromLeft.wav"); // Exports in time domain as impulse response (IR) - iFilterLengthSamples = (int)(oPathFromRight.GetLength() / fSpeedOfSound * fSampleRate); - iFilterLengthSamples = int(iFilterLengthSamples + 4096); - ITABase::CHDFTSpectra oTransmissionFilterRight(fSampleRate, pReceiver->GetNumChannels(), iFilterLengthSamples); oFilterEngine.Generate(oPathFromRight, oTransmissionFilterRight, &bDFTDegreeTooSmallFlag);