diff --git a/CMakeLists.txt b/CMakeLists.txt index 3367c4d381b46b659815d27793133cedd867b9c1..15fc69891fffae89ff662cd897d73211666e903c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,6 @@ endif () # ---External libs--- add_subdirectory (external_libs) - # Library ihta_add_library ( NAME ${PROJECT_NAME} @@ -40,6 +39,7 @@ ihta_add_library ( include/ITApropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.h include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/DumbReflection.h + include/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h include/ITApropagationModels/PropagationParameterEngine/PropagationModules/DiffractionModules/DumbDiffraction.h include/ITApropagationModels/PropagationParameterEngine/PropagationModules/SpreadingLossModules/DumbSpreadingLoss.h include/ITApropagationModels/PropagationParameterEngine/PropagationModules/AirAttenuationModules/DumbAirAttenuation.h @@ -56,6 +56,7 @@ ihta_add_library ( src/ITApropagationModels/PropagationParameterEngine/PropagationConfig.cpp src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.cpp src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/DumbReflection.cpp + src/ITApropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp src/ITApropagationModels/PropagationParameterEngine/PropagationModules/DiffractionModules/DumbDiffraction.cpp src/ITApropagationModels/PropagationParameterEngine/PropagationModules/SpreadingLossModules/DumbSpreadingLoss.cpp src/ITApropagationModels/PropagationParameterEngine/PropagationModules/AirAttenuationModules/DumbAirAttenuation.cpp @@ -63,6 +64,7 @@ ihta_add_library ( src/ITApropagationModels/PropagationParameterEngine/PropagationModules/PropagationDelayModules/DumbPropagationDelay.cpp src/ITAPropagationModels/PropagationParameterEngine/UtilsPPE.cpp src/ITAPropagationModels/PropagationParameterEngine/PropagationParameters/FrequencySpectrum.cpp + NAMESPACE ${PROJECT_NAME} IDE_FOLDER "ITAGeometricalAcoustics" OUT_LIB LIB_TARGET @@ -71,6 +73,7 @@ ihta_add_library ( tests/UnitTest/test_definitions.h tests/UnitTest/test_PPE.cpp tests/UnitTest/test_HomogeneousPropagationDelay.cpp + tests/UnitTest/test_ReflectionFactor.cpp ADD_UNIT_TEST ${ITA_PROPAGATION_MODELS_WITH_TESTS} ) @@ -89,14 +92,14 @@ endif () # Linking for UnitTests target_link_libraries( - ${TEST_TARGET} PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list + ${TEST_TARGET} PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list tinysplinecxx ) # Linking target_link_libraries ( ${LIB_TARGET} PUBLIC ITABase::ITABase ITAGeo::ITAGeo ITAPropagationPathSim::ITAPropagationPathSim - PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list + PRIVATE ITAFFT::ITAFFT Spline::spline glm::glm au::au IHTA::propagation_path_list tinysplinecxx ) # because of au::au header-only we have large obj files diff --git a/external_libs/CMakeLists.txt b/external_libs/CMakeLists.txt index e69a598d3303f87f970ba5e43da6b67c688384f8..72cd4817b89e8a6630e28e22ebe989c1af4283f0 100644 --- a/external_libs/CMakeLists.txt +++ b/external_libs/CMakeLists.txt @@ -29,3 +29,11 @@ if (EXISTS ${CMAKE_CURRENT_BINARY_DIR}/_external/au/include/au.hh set_property (TARGET au PROPERTY FOLDER "external_libs") endif() + +CPMAddPackage ( + NAME tinySpline + GITHUB_REPOSITORY msteinbeck/tinyspline + VERSION 0.6.0 + OPTIONS "TINYSPLINE_BUILD_EXAMPLES OFF" "TINYSPLINE_BUILD_TESTS OFF" "TINYSPLINE_BUILD_DOCS OFF" +) +set_property (TARGET tinyspline tinysplinecxx PROPERTY FOLDER "external_libs/tinyspline") diff --git a/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h new file mode 100644 index 0000000000000000000000000000000000000000..559dd8b34433c95f4318a8bba2dd2a4055f15ed7 --- /dev/null +++ b/include/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h @@ -0,0 +1,45 @@ +#pragma once + +#include <../../../ITAGeometricalAcoustics/ITAGeo/include/ITAGeo/Material/Material.h> +#include <ITAPropagationModels/Definitions.h> +#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/BaseModule.h> +#include <glm/glm.hpp> +#include <tinysplinecxx.h> + +namespace ITAPropagationModels +{ + namespace PropagationParameterEngine + { + namespace PropagationModules + { + //! @brief Simple reflection class. Scales the frequency response by the given percent or, if no scale is provided, by 1 (nothing happens). + class ITA_PROPAGATION_MODELS_API CBasicReflection : public CBaseModules + { + private: + float m_scale { 1.0f }; + //! @brief self register to factory + static bool registered; + + public: + CBasicReflection( ) = default; + //! @param scale between 0 and 1 + //! @throws std::invalid argument if scale out of range + CBasicReflection( const float scale ); + ~CBasicReflection( ) = default; + + std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>> + compute( const propagation_path_list::PropagationPathList& ppl ) override; + [[no_discard]] EModuleIdentifier get_identifier( ) const override { return EModuleIdentifier::REFLECTION; }; + + std::vector<std::complex<double>> compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_anchor, + std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_anchor, + std::shared_ptr<propagation_path_list::MaterialBase> material_type ); + std::vector<std::complex<double>> interpolate_scalar_material_reflection_factor( int number_of_bins, double scalar_reflection_factor ); + std::vector<std::complex<double>> interpolate_third_octave_material_reflecton_factor( int bins, double sampling_rate, std::array<double, 31> reflection_factor_real, std::array<double, 31> reflection_factor_image ); + double compute_reflection_factor_impedance( double impedance, double theta ); + double compute_reflection_factor_absorption( double absorption ) ; + double calculate_incident_angle( const propagation_path_list::Vector& incident_vector, const propagation_path_list::Vector& face_normal) ; + }; + } // namespace PropagationModules + } // namespace PropagationParameterEngine +} // namespace ITAPropagationModels diff --git a/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp b/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp index e6515c5bab1de89a3046867bd0036f2b1dfe522b..f5d7723036eef9a1e2a1b8cc52ab70f4a28eb412 100644 --- a/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp +++ b/include/ITAPropagationModels/PropagationParameterEngine/ppe_config.hpp @@ -125,6 +125,15 @@ namespace ITAPropagationModels::PropagationParameterEngine } }; + struct BasicReflectionConfig : public ReflectionConfig + { + template<class Archive> + void serialize( Archive& t_archive ) + { + cereal::base_class<ReflectionConfig>( this ).base_ptr->serialize( t_archive ); + } + }; + /// /// \brief Base air attenuation module config /// diff --git a/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp new file mode 100644 index 0000000000000000000000000000000000000000..386dae2ebb5d8dd0ee854f07206d13b58eef0a60 --- /dev/null +++ b/src/ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.cpp @@ -0,0 +1,236 @@ +#include <ITAPropagationModels/PropagationParameterEngine/PropagationConfig.h> +#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ModuleFactory.h> +#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h> +#include <ITAPropagationModels/PropagationParameterEngine/PropagationParameters/FrequencySpectrum.h> +#include <ITAPropagationModels/PropagationParameterEngine/UtilsPPE.h> +#include <exception> +#include <memory> + +using namespace ITAPropagationModels::PropagationParameterEngine; + +//! @brief register to factory +bool PropagationModules::CBasicReflection::registered = CFactory::registerModule<BasicReflectionConfig, CBasicReflection>( ); + +PropagationModules::CBasicReflection::CBasicReflection( const float scale ) +{ + if( scale > 1.0f || scale < 0.0f ) + throw std::invalid_argument( "scale has to be between 0 and 1." ); + + this->m_scale = scale; +} + +std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBasePropagationParameter>> PropagationModules::CBasicReflection::compute( + const propagation_path_list::PropagationPathList& ppl ) +{ + // Get config parameters for sampling_rate, air density, etc. + const CPropagationConfig* const config = CPropagationConfig::get_instance( ); + float sampling_rate_value = config->sampling_rate.in(au::hertz); + int number_of_bins = config->bins; + + std::unordered_map<std::string, std::unique_ptr<ITAPropagationModels::PropagationParameterEngine::PropagationParameters::CBasePropagationParameter>> + module_output ; + std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_pointer; + std::shared_ptr<propagation_path_list::PropagationAnchorBase> reflection_anchor; + + // A list of the reflection_factors which are vectors of double for scalar materials or vectors of std::complex<double> for ThirdOctacveMaterials. + std::vector<PropagationParameters::CFrequencySpectrum> reflection_factor_list; + + for( const propagation_path_list::PropagationPath& path: ppl.propagation_paths ) + { + std::valarray<std::complex<float>> path_reflection_factor_array(number_of_bins, 1.0); + for( auto&& anchor: path.propagation_anchors ) + { + if( auto reflection_pointer = std::dynamic_pointer_cast<const propagation_path_list::SpecularReflection>( anchor ) ) + { + // Reflection factor spectrum + auto material_type = ppl.material_database.find( reflection_pointer->material_id ); + if( material_type != ppl.material_database.end( ) ) + { + // The material ID exists in the database, get the shared_ptr + //std::shared_ptr<propagation_path_list::MaterialBase> material_type = material_type; + + std::vector<std::complex<double>> path_reflection_factor_vector = compute_anchor_reflection_factor( reflection_pointer, previous_pointer, material_type->second); + std::valarray<std::complex<float>> valarr(path_reflection_factor_vector.size()); + for (size_t i = 0; i < path_reflection_factor_vector.size(); ++i) { + valarr[i] = static_cast<std::complex<float>>(path_reflection_factor_vector[i]); + } + + path_reflection_factor_array = path_reflection_factor_array * valarr; + } + else + { + // Handle the case where the material ID is not found in the database + std::cerr << "Material not found in the database!" << std::endl; + } + } + else + { + previous_pointer = anchor; + } + } + + // Resize the spectrum to the length of config->bins and initializing with std::complex<float>(1.0f, 0.0f). + PropagationParameters::CFrequencySpectrum path_spectrum( 1.0f ); + path_spectrum.set_frequency_spectrum( path_reflection_factor_array); + + module_output[path.identifier] = std::make_unique<PropagationParameters::CFrequencySpectrum>( path_spectrum ); + } + + return module_output; +} + +std::vector<std::complex<double>> PropagationModules::CBasicReflection::compute_anchor_reflection_factor( std::shared_ptr<const propagation_path_list::SpecularReflection> reflection_pointer, + std::shared_ptr<const propagation_path_list::PropagationAnchorBase> previous_pointer, + std::shared_ptr<propagation_path_list::MaterialBase> material_type ) +{ + const CPropagationConfig* const config = CPropagationConfig::get_instance( ); + float sampling_rate_value = config->sampling_rate.in(au::hertz); + int number_of_bins = config->bins; + + std::vector<std::complex<double>> reflection_factor_complex; + + const propagation_path_list::Vector face_normal( reflection_pointer->face_normal ); + const propagation_path_list::Vector incident_vector{ previous_pointer->interaction_point[0] - reflection_pointer->interaction_point[0], + previous_pointer->interaction_point[1] - reflection_pointer->interaction_point[1], + previous_pointer->interaction_point[2] - reflection_pointer->interaction_point[2] }; + double theta = calculate_incident_angle(incident_vector, face_normal); + + if( auto ScalarMaterial = std::dynamic_pointer_cast<propagation_path_list::ScalarMaterial>( material_type ) ) + { + // only one constant absorption in double is available for scalar materials + double reflection_factor_scalar = compute_reflection_factor_absorption( ScalarMaterial->absorption ); + reflection_factor_complex = interpolate_scalar_material_reflection_factor( number_of_bins, reflection_factor_scalar); + } + + if( auto ThirdOctaveMaterial = std::dynamic_pointer_cast<propagation_path_list::ThirdOctaveMaterial>( material_type ) ) + { + propagation_path_list::MagnitudeSpectra spectra_real = ThirdOctaveMaterial->impedance_real; + propagation_path_list::MagnitudeSpectra spectra_image = ThirdOctaveMaterial->impedance_imag; + std::array<double, 31> reflection_factor_real; + std::array<double, 31> reflection_factor_image; + double theta = calculate_incident_angle(incident_vector, face_normal); + + // if impedence is available, get reflection factor with impedence + // Something like if (ThirdOctaveMaterial->impedance_real != NULL) ? + bool impedance_real_null = std::all_of(spectra_real.begin(), spectra_real.end(), [](double i){ return i <= 1.1e-5; }) ; + if( !impedance_real_null ) // ** IMPORTANT TO UPDATE ** Fill in if condition (impedance exists) + { + for( auto freq = 0; freq < 31; freq++ ) + { + reflection_factor_real[freq] = compute_reflection_factor_impedance( spectra_real[freq], theta ); + reflection_factor_image[freq] = compute_reflection_factor_impedance( spectra_image[freq], theta ); + } + reflection_factor_complex = interpolate_third_octave_material_reflecton_factor( number_of_bins, double(sampling_rate_value), reflection_factor_real, reflection_factor_image ); + } + else // Only absorption is available + { + for( auto freq = 0; freq < 31; freq++ ) + { + reflection_factor_real[freq] = compute_reflection_factor_absorption( ThirdOctaveMaterial->absorption[freq] ); + reflection_factor_image[freq] = compute_reflection_factor_absorption( 1.0 ); // Set image part as 1.0 to return 0.0 for image part of reflection factor. + } + reflection_factor_complex = interpolate_third_octave_material_reflecton_factor( number_of_bins, sampling_rate_value, reflection_factor_real, reflection_factor_image ); + } + } + + return reflection_factor_complex; +} + +std::vector<std::complex<double>> PropagationModules::CBasicReflection::interpolate_scalar_material_reflection_factor( int number_of_bins, double scalar_reflection_factor ) +{ + std::vector<std::complex<double>> scalar_reflection_factor_spectrum; + + for (size_t i = 0; i < number_of_bins; i++) + { + std::complex<double> t_complex(scalar_reflection_factor, 0.0); + scalar_reflection_factor_spectrum.push_back(t_complex); + } + + return scalar_reflection_factor_spectrum; +} + +std::vector<std::complex<double>> PropagationModules::CBasicReflection::interpolate_third_octave_material_reflecton_factor( int bins, double sampling_rate, std::array<double, 31> reflection_factor_real, std::array<double, 31> reflection_factor_image ) +{ + // cubic spline + double start_frequency = 20.0; + double end_frequency = sampling_rate / 2.0; + // ** To Update ** interpolating_rate was not used. Now the returned vector only contains the reflection factor values, without the corresponding frequency values. + double interpolating_rate = (end_frequency - start_frequency) / (bins - 1); + + std::vector<std::complex<double>> full_reflection_factor_spectrum; + + int control_point_count = 31; + tinyspline::BSpline spline_real(control_point_count, 1, 3); + tinyspline::BSpline spline_image(control_point_count, 1, 3); + std::vector<tinyspline::real> ctrlp_real = spline_real.controlPoints(); + std::vector<tinyspline::real> ctrlp_image = spline_image.controlPoints(); + for (size_t i = 0; i < control_point_count; ++i) + { + ctrlp_real[i] = reflection_factor_real[i]; + ctrlp_image[i] = reflection_factor_image[i]; + } + spline_real.setControlPoints(ctrlp_real); + spline_image.setControlPoints(ctrlp_image); + + for (double i = 0; i < bins; i++) + { + double t = i / (bins - 1); + + std::complex<double> result(spline_real.eval(t).result()[0], spline_image.eval(t).result()[0]); + full_reflection_factor_spectrum.push_back(result); + } + + return full_reflection_factor_spectrum; // ** Return single value to be more flexible? Return whole spectrum might have high memory complexity. ** + +} + +double PropagationModules::CBasicReflection::compute_reflection_factor_impedance( double impedance, double theta ) +{ + // function 3.3 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 32. + // To calculate single reflection factor with (double)impedance + const CPropagationConfig* const config = CPropagationConfig::get_instance( ); + decltype( au::velocity( float( ) ) ) speed_of_sound = config->speed_of_sound; + decltype( au::density( float( ) ) ) air_density = config->air_density; + + auto Z0 = air_density * speed_of_sound; + decltype(au::velocity( float() ) * au::density( float() )) Z = au::velocity( float(impedance) ) * au::density( 1.f ); + + auto R = ( Z * au::unos(cos(theta)) - Z0 ) / ( Z * au::unos(cos(theta)) + Z0 ); + + return R; +} + +double PropagationModules::CBasicReflection::compute_reflection_factor_absorption( double absorption ) +{ + // function 11.39 in the book Auralization, Fundamentals of Acoustics, Modelling, Simulation, Algorithms and Acoustic Virtual Reality, second edition, page 198. + + if (absorption < 0 || absorption > 1) + { + std::cerr << "Error: Absorption coefficient must be between 0 and 1." << std::endl; // ** use std::cerr or ...? ** + return -100.0; + } + + // Calculate the reflection factor |R| + double abs_reflection_factor = std::sqrt(1 - absorption); + + return abs_reflection_factor; +} + +double PropagationModules::CBasicReflection::calculate_incident_angle(const propagation_path_list::Vector& incident_vector, const propagation_path_list::Vector& face_normal) +{ + double dot_product = incident_vector[0] * face_normal[0] + + incident_vector[1] * face_normal[1] + + incident_vector[2] * face_normal[2]; + + double incident_magnitude = std::sqrt(incident_vector[0] * incident_vector[0] + + incident_vector[1] * incident_vector[1] + + incident_vector[2] * incident_vector[2]); + + double normal_magnitude = std::sqrt(face_normal[0] * face_normal[0] + + face_normal[1] * face_normal[1] + + face_normal[2] * face_normal[2]); + double cos_angle = dot_product / (incident_magnitude * normal_magnitude); + double theta = std::acos(cos_angle); + + return theta; +} diff --git a/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json b/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json index a2271d33342d2baf8cd2bdf5cc4b5a9a5313c95f..fb854baa86796e13f44ecdefbc993f4bb3e63620 100644 --- a/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json +++ b/tests/UnitTest/resources/Rigid_pigeon30to30_dae.json @@ -88,6 +88,110 @@ ] } ] + }, + { + "identifier": "Reflection_On_Softwall", + "propagation_anchors": [ + { + "type": "Source", + "interaction_point": [ + 2.9019999504089357, + 1.5, + -2.984999895095825 + ], + "name": "E30deg", + "directivity_id": "Loudspeaker_Genelec8020c_1x1", + "orientation": [ + 0.6830127239227295, + 0.6830127239227295, + 0.1830126941204071, + -0.1830126941204071 + ] + }, + { + "type": "SpecularReflection", + "interaction_point": [ + 5.5, + 0.0, + -2.984999895095825 + ], + "polygon_id": 0, + "material_id": "Test_Material_Soft_Wall", + "face_normal": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "type": "Receiver", + "interaction_point": [ + 8.097999572753907, + 1.5, + -2.984999895095825 + ], + "name": "S30deg", + "directivity_id": "Omnidirectional", + "orientation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ] + } + ] + }, + { + "identifier": "Reflection_On_Hardwall", + "propagation_anchors": [ + { + "type": "Source", + "interaction_point": [ + 2.9019999504089357, + 1.5, + -2.984999895095825 + ], + "name": "E30deg", + "directivity_id": "Loudspeaker_Genelec8020c_1x1", + "orientation": [ + 0.6830127239227295, + 0.6830127239227295, + 0.1830126941204071, + -0.1830126941204071 + ] + }, + { + "type": "SpecularReflection", + "interaction_point": [ + 5.5, + 0.0, + -2.984999895095825 + ], + "polygon_id": 0, + "material_id": "Test_Material_Hard_Wall", + "face_normal": [ + 0.0, + 1.0, + 0.0 + ] + }, + { + "type": "Receiver", + "interaction_point": [ + 8.097999572753907, + 1.5, + -2.984999895095825 + ], + "name": "S30deg", + "directivity_id": "Omnidirectional", + "orientation": [ + 0.0, + 0.0, + 0.0, + 1.0 + ] + } + ] } ], "material_database": { @@ -225,6 +329,411 @@ -7795.98291015625, -6621.1396484375 ] + }, + "Test_Material_Soft_Wall": { + "type": "ThirdOctaveMaterial", + "absorption": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "scattering": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "impedance_real": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "impedance_imag": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "Test_Material_Hard_Wall": { + "type": "ThirdOctaveMaterial", + "absorption": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "scattering": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "impedance_real": [ + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10, + 8.88e10 + ], + "impedance_imag": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + }, + "Test_Material_Matched_Wall_SeaLevel_25Degrees": { + "type":"ThirdOctaveMaterial", + "absorption":[ + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0, + 1.0 + ], + "scattering":[ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + "impedance_real":[ + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664, + 409.664 + ], + "impedance_imag": [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] } } } \ No newline at end of file diff --git a/tests/UnitTest/test_ReflectionFactor.cpp b/tests/UnitTest/test_ReflectionFactor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c72579db4bf7964bf68c9798f4e9bf11015c26ac --- /dev/null +++ b/tests/UnitTest/test_ReflectionFactor.cpp @@ -0,0 +1,40 @@ +#include "test_definitions.h" +#include <ITAPropagationModels/PropagationParameterEngine/PropagationModules/ReflectionModules/BasicReflection.h> +#include <au.hh> +#include <fstream> +#include <memory> + +using namespace ITAPropagationModels::PropagationParameterEngine; + +TEST_CASE( "ITAPropagationModels::PPE::PropModules::ReflectionFactor", "[ReflectionFactor]" ) +{ + // Load PPl + propagation_path_list::PropagationPathList ppl; + const std::string input_ppl = ITA_PROPAGATION_MODELS_TEST_RESOURCE_DIR "/Rigid_pigeon30to30_dae.json"; + std::ifstream input_stream( input_ppl ); + if( input_stream.is_open( ) ) + { + cereal::JSONInputArchive archive( input_stream ); + ppl.serialize( archive ); + } + REQUIRE( !ppl.propagation_paths.empty( ) ); + + PropagationModules::CBasicReflection reflection_factor; + std::unordered_map<std::string, std::unique_ptr<PropagationParameters::CBasePropagationParameter>> reflection_factor_map ; + + SECTION( "Compute" ) + { + REQUIRE_NOTHROW( reflection_factor_map = reflection_factor.compute( ppl ) ); + + // Test paths and test material examples from page 33, section 3.2.1, book "Auralization: Fundamentals of Acoustics, Modelling... (Michael Vorlaender, second edition) " + // Hard wall: Z = infinate; R = 1; alpha = 0 + std::unique_ptr<PropagationParameters::CBasePropagationParameter>& reflection_factor_Hardwall = reflection_factor_map["Reflection_On_Hardwall"]; + + // Soft wall: Z = 0; R = -1; alpha = 0 + std::unique_ptr<PropagationParameters::CBasePropagationParameter>& reflection_factor_Softwall = reflection_factor_map["Reflection_On_Softwall"]; + } + + // TODO: The results above are dependend on the air speed set in the PropagationConfig. This test case has to be adapted + // once the config class is reworked + REQUIRE( false ); +}