diff --git a/package-lock.json b/package-lock.json
index 73533345..d4d74243 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
 {
   "name": "hifi-spatial-audio",
-  "version": "2.0.0",
+  "version": "2.1.0",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
diff --git a/package.json b/package.json
index 408293cc..390020eb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "hifi-spatial-audio",
-  "version": "2.0.0",
+  "version": "2.1.0",
   "description": "The High Fidelity Audio Client Library allows developers to integrate High Fidelity's spatial audio technology into their projects.",
   "main": "./dist/index.js",
   "types": "./dist/index.d.ts",
diff --git a/src/classes/HiFiAudioAPIData.ts b/src/classes/HiFiAudioAPIData.ts
index b9a60781..d387b0b0 100644
--- a/src/classes/HiFiAudioAPIData.ts
+++ b/src/classes/HiFiAudioAPIData.ts
@@ -44,6 +44,17 @@ export class HiFiAudioAPIData {
      * A volume level below this value is considered background noise and will be smoothly gated off.
      * The floating point value is specified in dBFS (decibels relative to full scale) with values between -96 dB (indicating no gating)
      * and 0 dB (effectively muting the input from this user). It is in the same decibel units as the VolumeDecibels component of UserDataSubscription.
+     * Setting this value to `NaN` will cause the volume threshold from the space to be used instead.
+     * 
+     * **COMPATIBILITY WARNING:** Currently, setting `volumeThreshold` to `null` will also reset its value to the space default volume threshold.
+     * In the future, the value of `volumeThreshold` will only be reset if it is set to `NaN`.
+     * A `volumeThreshold` set to `null` will in the future will be treated as if `volumeThreshold` is not supplied.
+     * If your spatial audio client application is currently resetting `volumeThreshold` by setting it to `null`, please change
+     * it to set `volumeThreshold` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
+     *
+     * If you don't supply a `volumeThreshold` when constructing instantiations of this class, the previous value of `volumeThreshold` will
+     * be used. If `volumeThreshold` has never been supplied, the volume threshold of the space will be used instead.
      */
     volumeThreshold: number;
     /**
@@ -61,23 +72,29 @@ export class HiFiAudioAPIData {
      * This value affects how far a user's sound will travel in 3D space, without affecting the user's loudness.
      * By default, there is a global attenuation value (set for a given space) that applies to all users in a space. This default space
      * attenuation is usually 0.5, which represents a reasonable approximation of a real-world fall-off in sound over distance.
-     * Lower numbers represent less attenuation (i.e. sound travels farther); higher numbers represent more attenuation (i.e. sound drops
-     * off more quickly).
      * 
      * When setting this value for an individual user, the following holds:
-     *   - Positive numbers should be between 0 and 1, and they represent a logarithmic attenuation. This range is recommended, as it is
+     *   - A value of `NaN` causes the user to inherit the global attenuation for a space, or, if zones are defined for the space,
+     * the attenuation settings at the user's position. **COMPATIBILITY WARNING:** Currently, setting `userAttenuation` to 0 will
+     * also reset its value to the space/zone default attenuation.
+     * In the future, the value of `userAttenuation` will only be reset if it is set to `NaN`.
+     * A `userAttenuation` set to 0 will in the future be treated as a "broadcast mode", making
+     * the user audible throughout the entire space.
+     * If your spatial audio client application is currently resetting `userAttenuation` by setting it to 0, please change
+     * it to set `userAttenuation` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
+     *   - Positive numbers between 0 and 1 (excluding 0) represent logarithmic attenuation. This range is recommended, as it is
      * more natural sounding.  Smaller numbers represent less attenuation, so a number such as 0.2 can be used to make a particular 
-     * user's audio travel farther than other users', for instance in "amplified" concert type settings. Similarly, an extremely 
-     * small non-zero number (e.g. 0.00001) can be used to effectively turn off attenuation for a given user within a reasonably 
-     * sized space, resulting in a "broadcast mode" where the user can be heard throughout most of the space regardless of their location
-     * relative to other users. (Note: The actual value "0" is used internally to represent the default; for setting minimal attenuation, 
-     * small non-zero numbers should be used instead. See also "userRolloff" below.)
+     * user's audio travel farther than other users', for instance in "amplified" concert type settings. A number such as 0.02 will
+     * make the user's audio travel even farther.
+     *  - A value of near 0, such as 0.001, will greatly reduce attenuation for a given user, resulting effectively in a "broadcast mode" where the user can be
+     * heard throughout the entire space regardless of their location relative to other users.
      *   - Negative attenuation numbers are used to represent linear attenuation, and are a somewhat artificial, non-real-world concept. However,
      * this setting can be used as a blunt tool to easily test attenuation, and tune it aggressively in extreme circumstances. When using linear 
      * attenuation, the setting is the distance in meters at which the audio becomes totally inaudible.
      *
-     * If you don't supply an `userAttenuation` when constructing instantiations of this class, `userAttenuation` will be `null` and the
-     * default will be used.
+     * If you don't supply a `userAttenuation` when constructing instantiations of this class, the previous value of `userAttenuation` will
+     * be used. If `userAttenuation` has never been supplied, the attenuation of the space will be used instead.
      * 
      * ✔ The client sends `userAttenuation` data to the server when `_transmitHiFiAudioAPIDataToServer()` is called.
      * 
@@ -93,7 +110,19 @@ export class HiFiAudioAPIData {
      * extremely high values (e.g. 99999) should be used in combination with "broadcast mode"-style userAttenuation settings to cause the
      * broadcasted voice to sound crisp and "up close" even at very large distances.
      *
-     * If you don't supply an `userRolloff` when constructing instantiations of this class, `userRolloff` will be `null`.
+     * A `userRolloff` of `NaN` will cause the user to inherit the global frequency rolloff for the space, or, if zones are defined
+     * for the space, the frequency rolloff settings at the user's position.
+     * 
+     * **COMPATIBILITY WARNING:** Currently, setting `userRolloff` to 0 will also reset its value to the space/zone default rolloff
+     * In the future, the value of `userRolloff` will only be reset if it is set to `NaN`
+     * A `userRolloff` set to 0 will in the future be treated as a valid frequency rolloff value,
+     * which will cause the user's sound to become muffled over a short distance.
+     * If your spatial audio client application is currently resetting `userRolloff` by setting it to 0, please change
+     * it to set `userRolloff` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
+     *
+     * If you don't supply a `userRolloff` when constructing instantiations of this class, the previous value of `userRolloff` will
+     * be used. If `userRolloff` has never been supplied, the frequency rolloff of the space will be used instead.
      * 
      * ✔ The client sends `userRolloff` data to the server when `_transmitHiFiAudioAPIDataToServer()` is called.
      * 
diff --git a/src/classes/HiFiCommunicator.ts b/src/classes/HiFiCommunicator.ts
index 9bdc3a2f..e5dd686c 100644
--- a/src/classes/HiFiCommunicator.ts
+++ b/src/classes/HiFiCommunicator.ts
@@ -979,15 +979,42 @@ export class HiFiCommunicator {
      * @param __namedParameters
      * @param position - The new position of the user.
      * @param orientation - The new orientation of the user (in Quaternion form)
-     * @param volumeThreshold - The new volumeThreshold of the user.  Setting this to null will use the space default volume threshold.
+     * @param volumeThreshold - The new volumeThreshold of the user.  Setting this to `NaN` will reset its value to the space default volume threshold.
+     * 
+     * **COMPATIBILITY WARNING:** Currently, setting `volumeThreshold` to `null` will also reset its value to the space default volume threshold.
+     * In the future, the value of `volumeThreshold` will only be reset if it is set to `NaN`.
+     * A `volumeThreshold` set to `null` will in the future will be treated as if `volumeThreshold` is not supplied.
+     * If your spatial audio client application is currently resetting `volumeThreshold` by setting it to `null`, please change
+     * it to set `volumeThreshold` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
      * @param hiFiGain - This value affects how loud User A will sound to User B at a given distance in 3D space.
      * This value also affects the distance at which User A can be heard in 3D space.
      * Higher values for User A means that User A will sound louder to other users around User A, and it also means that User A will be audible from a greater distance.
      * The new hiFiGain of the user.
+     * 
      * @param userAttenuation - This value affects how far a user's voice will travel in 3D space.
-     * The new attenuation value for the user.
+     * Setting this to `NaN` will use the space default attenuation, or, if zones are defined for the space,
+     * the attenuation settings at the user's position.
+     * 
+     * **COMPATIBILITY WARNING:** Currently, setting `userAttenuation` to 0 will also reset its value to the space/zone default attenuation.
+     * In the future, the value of `userAttenuation` will only be reset if it is set to `NaN`.
+     * A `userAttenuation` set to 0 will in the future be treated as a "broadcast mode", making
+     * the user audible throughout the entire space.
+     * If your spatial audio client application is currently resetting `userAttenuation` by setting it to 0, please change
+     * it to set `userAttenuation` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
+     * 
      * @param userRolloff - This value affects the frequency rolloff for a given user.
-     * The new rolloff value for the user.
+     * Setting this to `NaN` or 0 will use the space default rolloff, or, if zones are defined for the space,
+     * the frequency rolloff settings at the user's position.
+     * 
+     * **COMPATIBILITY WARNING:** Currently, setting `userRolloff` to 0 will also reset its value to the space/zone default rolloff
+     * In the future, the value of `userRolloff` will only be reset if it is set to `NaN`
+     * A `userRolloff` set to 0 will in the future be treated as a valid frequency rolloff value,
+     * which will cause the user's sound to become muffled over a short distance.
+     * If your spatial audio client application is currently resetting `userRolloff` by setting it to 0, please change
+     * it to set `userRolloff` to `NaN` instead, in order for it to continue working with future versions of
+     * High Fidelity's Spatial Audio API.
      */
     private _updateUserData({ position, orientation, volumeThreshold, hiFiGain, userAttenuation, userRolloff }: { position?: Point3D, orientation?: Quaternion, volumeThreshold?: number, hiFiGain?: number, userAttenuation?: number, userRolloff?: number } = {}): void {
         if (position) {
@@ -1011,17 +1038,17 @@ export class HiFiCommunicator {
             this._currentHiFiAudioAPIData.orientation.z = orientation.z ?? this._currentHiFiAudioAPIData.orientation.z;
         }
 
-        if (typeof (volumeThreshold) === "number" ||
+        if (typeof (volumeThreshold) === "number" || // May be NaN
             volumeThreshold === null) {
             this._currentHiFiAudioAPIData.volumeThreshold = volumeThreshold;
         }
         if (typeof (hiFiGain) === "number") {
             this._currentHiFiAudioAPIData.hiFiGain = Math.max(0, hiFiGain);
         }
-        if (typeof (userAttenuation) === "number") {
+        if (typeof (userAttenuation) === "number") { // May be NaN
             this._currentHiFiAudioAPIData.userAttenuation = userAttenuation;
         }
-        if (typeof (userRolloff) === "number") {
+        if (typeof (userRolloff) === "number") { // May be NaN
             this._currentHiFiAudioAPIData.userRolloff = Math.max(0, userRolloff);
         }
     }
@@ -1067,7 +1094,7 @@ export class HiFiCommunicator {
             this._lastTransmittedHiFiAudioAPIData.orientation.z = dataJustTransmitted.orientation.z ?? this._lastTransmittedHiFiAudioAPIData.orientation.z;
         }
 
-        if (typeof (dataJustTransmitted.volumeThreshold) === "number" ||
+        if (typeof (dataJustTransmitted.volumeThreshold) === "number" || // May be NaN
             dataJustTransmitted.volumeThreshold === null) {
             this._lastTransmittedHiFiAudioAPIData["volumeThreshold"] = dataJustTransmitted.volumeThreshold;
         }
@@ -1075,10 +1102,10 @@ export class HiFiCommunicator {
         if (typeof (dataJustTransmitted.hiFiGain) === "number") {
             this._lastTransmittedHiFiAudioAPIData["hiFiGain"] = dataJustTransmitted.hiFiGain;
         }
-        if (typeof (dataJustTransmitted.userAttenuation) === "number") {
+        if (typeof (dataJustTransmitted.userAttenuation) === "number") { // May be NaN
             this._lastTransmittedHiFiAudioAPIData["userAttenuation"] = dataJustTransmitted.userAttenuation;
         }
-        if (typeof (dataJustTransmitted.userRolloff) === "number") {
+        if (typeof (dataJustTransmitted.userRolloff) === "number") { // May be NaN
             this._lastTransmittedHiFiAudioAPIData["userRolloff"] = dataJustTransmitted.userRolloff;
         }
         if (typeof (dataJustTransmitted._otherUserGainQueue) === "object") {
@@ -1172,6 +1199,7 @@ export class HiFiCommunicator {
 
     /**
      * A simple function that calls {@link _updateUserData}, followed by {@link _transmitHiFiAudioAPIDataToServer}.
+     * See {@link HiFiAudioAPIData} for what data can be sent to the High Fidelity Audio API Server.
      * Developers can call this function as often as they want. This function will update the internal data store of the user's
      * position, orientation, etc. No matter how often developers call this function, the internal data store transmission is rate-limited
      * and will only be sent to the server once every `transmitRateLimitTimeoutMS` milliseconds. When the internal data store is transmitted,
diff --git a/src/classes/HiFiMixerSession.ts b/src/classes/HiFiMixerSession.ts
index 21cd3469..0fd48f72 100644
--- a/src/classes/HiFiMixerSession.ts
+++ b/src/classes/HiFiMixerSession.ts
@@ -1,6 +1,9 @@
 /**
- * Code in this module is used internally by the [[HiFiCommunicator]] object to manage the connection between client and server.
- * Developers do not need to and should not consider this module when writing their applications.
+ * Code in this module is used by [[HiFiCommunicator]] object to manage the connection between client and server.
+ * This module is also home to some types used to manage client volume state, for example
+ * {@link OnMuteChangedCallback}.
+ * The class HiFiMixerSession is an internal class. Developers do not need to and should not consider it
+ * when writing their applications.
  * @packageDocumentation
  */
 
@@ -32,17 +35,33 @@ const PERSONAL_VOLUME_ADJUST_TIMEOUT_MS = 5000;
 
 type ConnectionStateChangeHandler = (state: HiFiConnectionStates, result: HiFiConnectionAttemptResult) => void;
 
+/** @internal */
 interface AudionetSetOtherUserGainsForThisConnectionResponse {
     success: boolean,
     reason?: string
 }
 
+/**
+ * The result of calling {@link HiFiCommunicator.setOtherUserGainsForThisConnection}, which adjusts the
+ * gain of one or more users for the communicator's current connection only.
+ */
 export interface SetOtherUserGainsForThisConnectionResponse {
+    /**
+     * `true` if the gains of other users were adjusted, `false` otherwise
+     */
     success: boolean,
+    /**
+     * if {@link success} is `false`, then a message explaining why the gains of other users could not be adjusted
+     */
     error?: string,
+    /** @internal */
     audionetSetOtherUserGainsForThisConnectionResponse?: AudionetSetOtherUserGainsForThisConnectionResponse
 }
 
+/**
+ * The result of calling {@link HiFiCommunicator.setOtherUserGainForThisConnection}, which adjusts the
+ * gain of another user for the communicator's current connection only.
+ */
 export type SetOtherUserGainForThisConnectionResponse = SetOtherUserGainsForThisConnectionResponse;
 
 /**
@@ -114,6 +133,7 @@ export type OnMuteChangedCallback = (muteChangedEvent: MuteChangedEvent) => void
 /**
  * Instantiations of this class contain data about a connection between a client and a mixer.
  * Client library users shouldn't have to care at all about the variables and methods contained in this class.
+ * @internal
  */
 export class HiFiMixerSession {
     /**
@@ -1207,7 +1227,7 @@ export class HiFiMixerSession {
             }
         }
 
-        if (typeof (currentHifiAudioAPIData.volumeThreshold) === "number" ||
+        if (typeof (currentHifiAudioAPIData.volumeThreshold) === "number" || // May be NaN
             currentHifiAudioAPIData.volumeThreshold === null) {
             dataForMixer["T"] = currentHifiAudioAPIData.volumeThreshold;
         }
@@ -1216,11 +1236,11 @@ export class HiFiMixerSession {
             dataForMixer["g"] = Math.max(0, currentHifiAudioAPIData.hiFiGain);
         }
 
-        if (typeof (currentHifiAudioAPIData.userAttenuation) === "number") {
+        if (typeof (currentHifiAudioAPIData.userAttenuation) === "number") { // May be NaN
             dataForMixer["a"] = currentHifiAudioAPIData.userAttenuation;
         }
 
-        if (typeof (currentHifiAudioAPIData.userRolloff) === "number") {
+        if (typeof (currentHifiAudioAPIData.userRolloff) === "number") { // May be NaN
             dataForMixer["r"] = Math.max(0, currentHifiAudioAPIData.userRolloff);
         }
 
@@ -1272,6 +1292,7 @@ export class HiFiMixerSession {
             let commandController = this._raviSession.getCommandController();
 
             if (commandController) {
+                // Stringified NaN values get converted to null, which the mixer interprets as unset
                 let stringifiedDataForMixer = JSON.stringify(dataForMixer);
                 commandController.sendInput(stringifiedDataForMixer);
                 return {
diff --git a/src/index.ts b/src/index.ts
index 9b80e0ce..4472d7c2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -21,6 +21,7 @@ export { apiVersion };
 // Scroll down to check out those shorter synonyms.
 export { HiFiAudioAPIData, ReceivedHiFiAudioAPIData, Point3D, Quaternion } from "./classes/HiFiAudioAPIData";
 export { HiFiCommunicator, HiFiConnectionStates, HiFiUserDataStreamingScopes } from "./classes/HiFiCommunicator";
+export { SetOtherUserGainForThisConnectionResponse, SetOtherUserGainsForThisConnectionResponse, MuteReason, MuteChangedEvent, OnMuteChangedCallback } from "./classes/HiFiMixerSession";
 export { WebRTCSessionParams } from "./libravi/RaviSession";
 export { AvailableUserDataSubscriptionComponents, UserDataSubscription } from "./classes/HiFiUserDataSubscription";
 export { HiFiLogLevel, HiFiLogger } from "./utilities/HiFiLogger";
diff --git a/src/utilities/HiFiMath.ts b/src/utilities/HiFiMath.ts
index b4863b68..5e5b1e66 100644
--- a/src/utilities/HiFiMath.ts
+++ b/src/utilities/HiFiMath.ts
@@ -132,7 +132,7 @@ export class Quaternion {
             axis.x = this.x / imaginaryLength;
             axis.y = this.y / imaginaryLength;
             axis.z = this.z / imaginaryLength;
-            let wholeLength = Math.sqrt(imaginaryLength + this.w * this.w);
+            let wholeLength = Math.sqrt(imaginaryLength2 + this.w * this.w);
             let angle = 2.0 * Math.acos(this.w / wholeLength);
             if (angle < 0.0) {
                 // we choose the axis that corresponds to positive angle
diff --git a/tsconfig.json b/tsconfig.json
index 1992e486..2316b2c9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -17,12 +17,13 @@
             "src/classes/HiFiAudioAPIData.ts",
             "src/classes/HiFiAxisConfiguration.ts",
             "src/classes/HiFiCommunicator.ts",
+            "src/classes/HiFiMixerSession.ts",
             "src/classes/HiFiUserDataSubscription.ts",
             "src/controls/HiFiControls.ts",
             "src/constants/HiFiConstants.ts",
             "src/libravi/RaviSession.ts",
             "src/utilities/HiFiLogger.ts",
-            "src/utilities/HiFiUtilities.ts",
+            "src/utilities/HiFiUtilities.ts"
         ],
         "out": "docs",
         "readme": "./tsdocIndexPage.md",
@@ -33,4 +34,4 @@
         "excludeInternal": true,
         "exclude": ["dist"]
     }
-}
\ No newline at end of file
+}