b=907986 handle zero front-right plane projection without NaNs r=padenot a=webaudio
authorKarl Tomlinson <karlt+@karlt.net>
Wed, 04 Sep 2013 21:20:59 +1200
changeset 153962 91da1184371ad82c97990d90e16801a522c96830
parent 153961 ea6aaf786efd10de39fceeae3b731292ecab56f0
child 153963 5397b6cbbfce4b2e7b2b9529dfda370c06c481eb
push id2859
push userakeybl@mozilla.com
push dateMon, 16 Sep 2013 19:14:59 +0000
treeherdermozilla-beta@87d3c51cd2bf [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspadenot, webaudio
bugs907986
milestone25.0a2
b=907986 handle zero front-right plane projection without NaNs r=padenot a=webaudio The azimuth calculation in the Web Audio spec becomes undefined in this situation as it requires normalizing a zero vector. The panning effect should not depend on azimuth when the source is directly above the listener (because position does not depend on azimuth), but the specified "equalpower" panning model does depend on azimuth even at this elevation. Setting azimuth to zero produces the same result as if the normalized projection were replaced with a zero vector.
content/media/webaudio/PannerNode.cpp
--- a/content/media/webaudio/PannerNode.cpp
+++ b/content/media/webaudio/PannerNode.cpp
@@ -390,18 +390,30 @@ PannerNodeEngine::ComputeAzimuthAndEleva
   sourceListener.Normalize();
 
   // Project the source-listener vector on the x-z plane.
   const ThreeDPoint& listenerFront = mListenerFrontVector;
   const ThreeDPoint& listenerRight = mListenerRightVector;
   ThreeDPoint up = listenerRight.CrossProduct(listenerFront);
 
   double upProjection = sourceListener.DotProduct(up);
+  aElevation = 90 - 180 * acos(upProjection) / M_PI;
+
+  if (aElevation > 90) {
+    aElevation = 180 - aElevation;
+  } else if (aElevation < -90) {
+    aElevation = -180 - aElevation;
+  }
 
   ThreeDPoint projectedSource = sourceListener - up * upProjection;
+  if (projectedSource.IsZero()) {
+    // source - listener direction is up or down.
+    aAzimuth = 0.0;
+    return;
+  }
   projectedSource.Normalize();
 
   // Actually compute the angle, and convert to degrees
   double projection = projectedSource.DotProduct(listenerRight);
   aAzimuth = 180 * acos(projection) / M_PI;
 
   // Compute whether the source is in front or behind the listener.
   double frontBack = projectedSource.DotProduct(listenerFront);
@@ -410,24 +422,16 @@ PannerNodeEngine::ComputeAzimuthAndEleva
   }
   // Rotate the azimuth so it is relative to the listener front vector instead
   // of the right vector.
   if ((aAzimuth >= 0) && (aAzimuth <= 270)) {
     aAzimuth = 90 - aAzimuth;
   } else {
     aAzimuth = 450 - aAzimuth;
   }
-
-  aElevation = 90 - 180 * acos(upProjection) / M_PI;
-
-  if (aElevation > 90) {
-    aElevation = 180 - aElevation;
-  } else if (aElevation < -90) {
-    aElevation = -180 - aElevation;
-  }
 }
 
 // This algorithm is described in the WebAudio spec.
 float
 PannerNodeEngine::ComputeConeGain()
 {
   // Omnidirectional source
   if (mOrientation.IsZero() || ((mConeInnerAngle == 360) && (mConeOuterAngle == 360))) {