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]