diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index bdec17bd8d..f67c54239e 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -743,7 +743,7 @@ void AudioMixer::parseSettingsObject(const QJsonObject& settingsObject) { float coefficient = coefficientObject.value(COEFFICIENT).toString().toFloat(&ok); - if (ok && coefficient >= 0.0f && coefficient <= 1.0f && + if (ok && coefficient <= 1.0f && itSource != end(_audioZones) && itListener != end(_audioZones)) { diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index 681d822e11..a920b45161 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -770,13 +770,29 @@ float computeGain(float masterListenerGain, const AvatarAudioStream& listeningNo break; } } - // translate the zone setting to gain per log2(distance) - float g = glm::clamp(1.0f - attenuationPerDoublingInDistance, EPSILON, 1.0f); - // calculate the attenuation using the distance to this node - // reference attenuation of 0dB at distance = 1.0m - gain *= fastExp2f(fastLog2f(g) * fastLog2f(std::max(distance, HRTF_NEARFIELD_MIN))); - gain = std::min(gain, 1.0f / HRTF_NEARFIELD_MIN); + if (attenuationPerDoublingInDistance < 0.0f) { + // translate a negative zone setting to distance limit + const float MIN_DISTANCE_LIMIT = ATTN_DISTANCE_REF + 1.0f; // silent after 1m + float distanceLimit = std::max(-attenuationPerDoublingInDistance, MIN_DISTANCE_LIMIT); + + // calculate the LINEAR attenuation using the distance to this node + // reference attenuation of 0dB at distance = ATTN_DISTANCE_REF + float d = distance - ATTN_DISTANCE_REF; + gain *= std::max(1.0f - d / (distanceLimit - ATTN_DISTANCE_REF), 0.0f); + gain = std::min(gain, ATTN_GAIN_MAX); + + } else { + // translate a positive zone setting to gain per log2(distance) + const float MIN_ATTENUATION_COEFFICIENT = 0.001f; // -60dB per log2(distance) + float g = glm::clamp(1.0f - attenuationPerDoublingInDistance, MIN_ATTENUATION_COEFFICIENT, 1.0f); + + // calculate the LOGARITHMIC attenuation using the distance to this node + // reference attenuation of 0dB at distance = ATTN_DISTANCE_REF + float d = (1.0f / ATTN_DISTANCE_REF) * std::max(distance, HRTF_NEARFIELD_MIN); + gain *= fastExp2f(fastLog2f(g) * fastLog2f(d)); + gain = std::min(gain, ATTN_GAIN_MAX); + } return gain; } diff --git a/libraries/audio-client/src/AudioClient.cpp b/libraries/audio-client/src/AudioClient.cpp index 338074ba3b..b2cba2351f 100644 --- a/libraries/audio-client/src/AudioClient.cpp +++ b/libraries/audio-client/src/AudioClient.cpp @@ -1979,8 +1979,10 @@ float AudioClient::azimuthForSource(const glm::vec3& relativePosition) { float AudioClient::gainForSource(float distance, float volume) { // attenuation = -6dB * log2(distance) - // reference attenuation of 0dB at distance = 1.0m - float gain = volume / std::max(distance, HRTF_NEARFIELD_MIN); + // reference attenuation of 0dB at distance = ATTN_DISTANCE_REF + float d = (1.0f / ATTN_DISTANCE_REF) * std::max(distance, HRTF_NEARFIELD_MIN); + float gain = volume / d; + gain = std::min(gain, ATTN_GAIN_MAX); return gain; } diff --git a/libraries/audio/src/AudioHRTF.h b/libraries/audio/src/AudioHRTF.h index eeef66e10c..7d23f4825a 100644 --- a/libraries/audio/src/AudioHRTF.h +++ b/libraries/audio/src/AudioHRTF.h @@ -30,6 +30,10 @@ static const float HRTF_NEARFIELD_MAX = 1.0f; // distance in meters static const float HRTF_NEARFIELD_MIN = 0.125f; // distance in meters static const float HRTF_HEAD_RADIUS = 0.0875f; // average human head in meters +// Distance attenuation +static const float ATTN_DISTANCE_REF = 2.0f; // distance where attn is 0dB +static const float ATTN_GAIN_MAX = 16.0f; // max gain allowed by distance attn (+24dB) + class AudioHRTF { public: diff --git a/libraries/shared/src/AudioHelpers.h b/libraries/shared/src/AudioHelpers.h index 1dcc11af0c..8f7f5f7f33 100644 --- a/libraries/shared/src/AudioHelpers.h +++ b/libraries/shared/src/AudioHelpers.h @@ -43,8 +43,9 @@ static inline float fastLog2f(float x) { } // -// for -127 <= x < 128, returns exp2(x) -// otherwise, returns undefined +// for -126 <= x < 128, returns exp2(x) +// for x < -126, returns 0 +// for x >= 128, returns undefined // // rel |error| < 9e-6, smooth (exact for x=N) // @@ -60,6 +61,7 @@ static inline float fastExp2f(float x) { x -= xi.i; // construct exp2(xi) as a float + xi.i &= ~(xi.i >> 31); // MAX(xi.i, 0) xi.i <<= IEEE754_MANT_BITS; // polynomial for exp2(x) over x=[0,1]