diff --git a/libtascar/include/acousticmodel.h b/libtascar/include/acousticmodel.h index 8aa2c3fe..e7753753 100644 --- a/libtascar/include/acousticmodel.h +++ b/libtascar/include/acousticmodel.h @@ -173,6 +173,7 @@ namespace TASCAR { uint32_t layers; float maxdist; float minlevel; + float nearfieldlimit; uint32_t sincorder; gainmodel_t gainmodel; bool airabsorption; @@ -211,7 +212,7 @@ namespace TASCAR { void update_refpoint(const pos_t& psrc_physical, const pos_t& psrc_virtual, pos_t& prel, float& distance, float& gain, bool b_img, - gainmodel_t gainmodel); + gainmodel_t gainmodel, float& nearfieldlimit); void set_next_gain(float gain); void set_fade(float targetgain, float duration, float start = -1); void apply_gain(); diff --git a/libtascar/src/acousticmodel.cc b/libtascar/src/acousticmodel.cc index 1fc871f3..52e621e1 100644 --- a/libtascar/src/acousticmodel.cc +++ b/libtascar/src/acousticmodel.cc @@ -120,7 +120,7 @@ acoustic_model_t::acoustic_model_t(float c,float fs,uint32_t chunksize, ismorder(getorder()) { pos_t prel; - receiver_->update_refpoint(src_->position,src_->position,prel,distance,gain,false,src_->gainmodel); + receiver_->update_refpoint(src_->position,src_->position,prel,distance,gain,false,src_->gainmodel, src_->nearfieldlimit); gain = 1.0; vstate.resize(obstacles_.size()); if(receiver_->layers & src_->layers) @@ -196,7 +196,7 @@ uint32_t acoustic_model_t::process(const TASCAR::transport_t& tp) // end obstacles receiver_->update_refpoint(primary->position, position, prel, nextdistance, nextgain, ismorder > 0, - src_->gainmodel); + src_->gainmodel, src_->nearfieldlimit); if(nextdistance > src_->maxdist) return 0; nextgain *= srcgainmod; @@ -474,7 +474,8 @@ diffuse_acoustic_model_t::diffuse_acoustic_model_t(float fs,uint32_t chunksize,d pos_t prel; float d(1.0); float gain; - receiver_->update_refpoint(src_->center,src_->center,prel,d,gain,false,GAIN_INVR); + float nflimit(0.1); + receiver_->update_refpoint(src_->center,src_->center,prel,d,gain,false,GAIN_INVR,nflimit); } diffuse_acoustic_model_t::~diffuse_acoustic_model_t() @@ -491,9 +492,10 @@ uint32_t diffuse_acoustic_model_t::process(const TASCAR::transport_t&) pos_t prel; float d(0.0); float nextgain(1.0); + float nflimit(0.1); // calculate relative geometry between source and receiver: receiver_->update_refpoint(src_->center, src_->center, prel, d, nextgain, - false, GAIN_INVR); + false, GAIN_INVR, nflimit); shoebox_t box(*src_); // box.size = src_->size; box.center = pos_t(); @@ -692,7 +694,7 @@ void receiver_t::add_diffuse_sound_field_rec(const amb1wave_t& chunk, receivermo void receiver_t::update_refpoint(const pos_t& psrc_physical, const pos_t& psrc_virtual, pos_t& prel, float& distance, float& gain, bool b_img, - gainmodel_t gainmodel) + gainmodel_t gainmodel, float& nearfieldlimit) { if(volumetric.has_volume()) { @@ -705,7 +707,7 @@ void receiver_t::update_refpoint(const pos_t& psrc_physical, float d(box.nextpoint(prel).normf()); if(falloff > 0) gain = (0.5f + 0.5f * cosf(TASCAR_PIf * std::min(1.0f, d / falloff))) / - std::max(0.1f, avgdist); + std::max(nearfieldlimit, avgdist); else { switch(gainmodel) { case GAIN_INVR: @@ -723,7 +725,7 @@ void receiver_t::update_refpoint(const pos_t& psrc_physical, distance = prel.normf(); switch(gainmodel) { case GAIN_INVR: - gain = 1.0f / std::max(0.1f, distance); + gain = 1.0f / std::max(nearfieldlimit, distance); break; case GAIN_UNITY: gain = 1.0f; @@ -856,7 +858,7 @@ source_t::source_t(tsccfg::node_t xmlsrc, const std::string& name, const std::string& parentname) : sourcemod_t(xmlsrc), licensed_component_t(typeid(*this).name()), ismmin(0), ismmax(2147483647), layers(0xffffffff), maxdist(3700), - minlevel(0), sincorder(0), gainmodel(GAIN_INVR), airabsorption(true), + minlevel(0), nearfieldlimit(0.1), sincorder(0), gainmodel(GAIN_INVR), airabsorption(true), delayline(true), size(0), active(true), // is_prepared(false), plugins(xmlsrc, name, parentname) @@ -866,6 +868,8 @@ source_t::source_t(tsccfg::node_t xmlsrc, const std::string& name, "physical size of sound source (effect depends on rendering method)"); GET_ATTRIBUTE(maxdist, "m", "maximum distance to be used in delay lines"); GET_ATTRIBUTE_DBSPL(minlevel, "Level threshold for rendering"); + GET_ATTRIBUTE(nearfieldlimit, "m", + "distance arond 1/r source where the gain is constant"); GET_ATTRIBUTE_BOOL(airabsorption, "apply air absorption filter"); GET_ATTRIBUTE_BOOL(delayline, "use delayline"); std::string gr("1/r");