Title: [287854] trunk
Revision
287854
Author
[email protected]
Date
2022-01-10 13:45:01 -0800 (Mon, 10 Jan 2022)

Log Message

https://brianpeiris.github.io/spatial-audio-test/?ramped stops playing after a few seconds
https://bugs.webkit.org/show_bug.cgi?id=234979

Reviewed by Eric Carlson.

Source/WebCore:

In ConeEffect::gain(), due to precision issues and with certain panner node parameters, it was possible for
`sourceToListener.dot(sourceOrientation)` to return a value that is very slightly outside the [-1.0, 1.0]
range. We would then call `acos()` on the dot product and it would thus return NaN.

To addresss this, we now make sure the clamp the dot product to the expected range before calling acos().

I also made the following stylistic changes:
- Drop unnecessary normalizedSourceOrientation local variable since the sourceOrientation paramter is not const
- Add missing curly brackets in if conditions with more than one lines (due to comments)
- Call rad2deg() for readability instead of duplicating its logic here

Test: webaudio/Panner/panner-cone-gain-nan.html

* platform/audio/Cone.cpp:
(WebCore::ConeEffect::gain const):

LayoutTests:

Add layout test coverage.

* webaudio/Panner/panner-cone-gain-nan-expected.txt: Added.
* webaudio/Panner/panner-cone-gain-nan.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (287853 => 287854)


--- trunk/LayoutTests/ChangeLog	2022-01-10 21:09:28 UTC (rev 287853)
+++ trunk/LayoutTests/ChangeLog	2022-01-10 21:45:01 UTC (rev 287854)
@@ -1,3 +1,15 @@
+2022-01-10  Chris Dumez  <[email protected]>
+
+        https://brianpeiris.github.io/spatial-audio-test/?ramped stops playing after a few seconds
+        https://bugs.webkit.org/show_bug.cgi?id=234979
+
+        Reviewed by Eric Carlson.
+
+        Add layout test coverage.
+
+        * webaudio/Panner/panner-cone-gain-nan-expected.txt: Added.
+        * webaudio/Panner/panner-cone-gain-nan.html: Added.
+
 2022-01-10  Cathie Chen  <[email protected]>
 
         ASSERTION FAILED in RenderLayer::updateClipRects

Added: trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan-expected.txt (0 => 287854)


--- trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan-expected.txt	2022-01-10 21:45:01 UTC (rev 287854)
@@ -0,0 +1,10 @@
+Tests that precision issues do not cause ConeEffect::gain() to return NaN
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS data.some(isNaN) is false
+PASS successfullyParsed is true
+
+TEST COMPLETE
+

Added: trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan.html (0 => 287854)


--- trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan.html	                        (rev 0)
+++ trunk/LayoutTests/webaudio/Panner/panner-cone-gain-nan.html	2022-01-10 21:45:01 UTC (rev 287854)
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+</head>
+<body>
+<script>
+description("Tests that precision issues do not cause ConeEffect::gain() to return NaN");
+jsTestIsAsync = true;
+
+function test() {
+    const audioContext = new OfflineAudioContext(1, 44100, 44100);
+
+    const panner = audioContext.createPanner();
+    panner.panningModel = "HRTF";
+    panner.refDistance = 50;
+    panner.coneInnerAngle = 0;
+    panner.coneOuterAngle = 180;
+    panner.coneOuterGain = 0.25;
+
+    const source = new ConstantSourceNode(audioContext);
+    source.connect(panner);
+    panner.connect(audioContext.destination);
+
+    audioContext.listener.setPosition(203.4781799316, 0, 200);
+    panner.setPosition(121.7528991699, 0, 137.7344207764);
+    panner.setOrientation(0.7954952121, 0, 0.6058534384);
+
+    source.start();
+    audioContext.startRendering().then((buffer) => {
+        data = ""
+        shouldBeFalse("data.some(isNaN)");
+        finishJSTest();
+  });
+}
+
+_onload_ = test;
+
+</script>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (287853 => 287854)


--- trunk/Source/WebCore/ChangeLog	2022-01-10 21:09:28 UTC (rev 287853)
+++ trunk/Source/WebCore/ChangeLog	2022-01-10 21:45:01 UTC (rev 287854)
@@ -1,3 +1,26 @@
+2022-01-10  Chris Dumez  <[email protected]>
+
+        https://brianpeiris.github.io/spatial-audio-test/?ramped stops playing after a few seconds
+        https://bugs.webkit.org/show_bug.cgi?id=234979
+
+        Reviewed by Eric Carlson.
+
+        In ConeEffect::gain(), due to precision issues and with certain panner node parameters, it was possible for
+        `sourceToListener.dot(sourceOrientation)` to return a value that is very slightly outside the [-1.0, 1.0]
+        range. We would then call `acos()` on the dot product and it would thus return NaN.
+
+        To addresss this, we now make sure the clamp the dot product to the expected range before calling acos().
+
+        I also made the following stylistic changes:
+        - Drop unnecessary normalizedSourceOrientation local variable since the sourceOrientation paramter is not const
+        - Add missing curly brackets in if conditions with more than one lines (due to comments)
+        - Call rad2deg() for readability instead of duplicating its logic here
+
+        Test: webaudio/Panner/panner-cone-gain-nan.html
+
+        * platform/audio/Cone.cpp:
+        (WebCore::ConeEffect::gain const):
+
 2022-01-10  Wenson Hsieh  <[email protected]>
 
         Modal container observer fails detection when rendered text is inserted after the container

Modified: trunk/Source/WebCore/platform/audio/Cone.cpp (287853 => 287854)


--- trunk/Source/WebCore/platform/audio/Cone.cpp	2022-01-10 21:09:28 UTC (rev 287853)
+++ trunk/Source/WebCore/platform/audio/Cone.cpp	2022-01-10 21:45:01 UTC (rev 287854)
@@ -46,12 +46,14 @@
     FloatPoint3D sourceToListener = listenerPosition - sourcePosition;
     sourceToListener.normalize();
 
-    FloatPoint3D normalizedSourceOrientation = sourceOrientation;
-    normalizedSourceOrientation.normalize();
+    sourceOrientation.normalize();
 
+    // Due to precision issues, the dot product may be very slightly outside the range [-1.0, 1.0], which would
+    // acos() to return NaN. For this reason, we have to make sure we clamp the dot product before calling acos().
+    auto dotProduct = clampTo(sourceToListener.dot(sourceOrientation), -1.0, 1.0);
+
     // Angle between the source orientation vector and the source-listener vector
-    double dotProduct = sourceToListener.dot(normalizedSourceOrientation);
-    double angle = 180.0 * acos(dotProduct) / piDouble;
+    double angle = rad2deg(acos(dotProduct));
     double absAngle = fabs(angle);
 
     // Divide by 2.0 here since API is entire angle (not half-angle)
@@ -59,13 +61,13 @@
     double absOuterAngle = fabs(m_outerAngle) / 2.0;
     double gain = 1.0;
 
-    if (absAngle <= absInnerAngle)
+    if (absAngle <= absInnerAngle) {
         // No attenuation
         gain = 1.0;
-    else if (absAngle >= absOuterAngle)
+    } else if (absAngle >= absOuterAngle) {
         // Max attenuation
         gain = m_outerGain;
-    else {
+    } else {
         // Between inner and outer cones
         // inner -> outer, x goes from 0 -> 1
         double x = (absAngle - absInnerAngle) / (absOuterAngle - absInnerAngle);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to