Title: [267443] trunk
Revision
267443
Author
[email protected]
Date
2020-09-22 15:52:42 -0700 (Tue, 22 Sep 2020)

Log Message

Merge AudioBufferSourceNode loop fixes from Blink
https://bugs.webkit.org/show_bug.cgi?id=216849

Reviewed by Eric Carlson.

Source/WebCore:

Merge AudioBufferSourceNode loop fixes from Blink, the following one in particular:
- https://codereview.chromium.org/723823002

This allows us to pass all the checks in:
webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html.

No new tests, rebaselined existing test.

* Modules/webaudio/AudioBufferSourceNode.cpp:
(WebCore::AudioBufferSourceNode::renderFromBuffer):
(WebCore::AudioBufferSourceNode::adjustGrainParameters):
Merge loop fixes from Blink.

* Modules/webaudio/AudioScheduledSourceNode.cpp:
(WebCore::AudioScheduledSourceNode::stopLater):
Stop throwing when m_endTime is already set. Our behavior did not match
Chrome and Firefox here. This was causing some existing tests to start
failing now that providing a grain duration when calling start() would
set m_endTime if loop() returns true.

LayoutTests:

* webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt:
Rebaseline test that is now passing.

* webaudio/Oscillator/oscillator-basic-expected.txt:
* webaudio/dom-exceptions-expected.txt:
Rebaseline tests because the exception message was improved.

* webaudio/audiobuffersource-exception-expected.txt:
* webaudio/audiobuffersource-exception.html:
Stop expecting an exception to be thrown when AudioBufferSourceNode.stop() gets called
more than once. I have verified that Chrome and Firefox do not throw in this case.

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (267442 => 267443)


--- trunk/LayoutTests/ChangeLog	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/ChangeLog	2020-09-22 22:52:42 UTC (rev 267443)
@@ -1,3 +1,22 @@
+2020-09-22  Chris Dumez  <[email protected]>
+
+        Merge AudioBufferSourceNode loop fixes from Blink
+        https://bugs.webkit.org/show_bug.cgi?id=216849
+
+        Reviewed by Eric Carlson.
+
+        * webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt:
+        Rebaseline test that is now passing.
+
+        * webaudio/Oscillator/oscillator-basic-expected.txt:
+        * webaudio/dom-exceptions-expected.txt:
+        Rebaseline tests because the exception message was improved.
+
+        * webaudio/audiobuffersource-exception-expected.txt:
+        * webaudio/audiobuffersource-exception.html:
+        Stop expecting an exception to be thrown when AudioBufferSourceNode.stop() gets called
+        more than once. I have verified that Chrome and Firefox do not throw in this case.
+
 2020-09-22  Hector Lopez  <[email protected]>
 
         [ macOS ] webgl/2.0.0/conformance/textures/misc/texture-upload-size.html is a flaky failure

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-basic-expected.txt (267442 => 267443)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-basic-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-basic-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -6,7 +6,7 @@
 PASS   start(NaN) threw TypeError: "The provided value is non-finite". 
 PASS   start(Infinity) threw TypeError: "The provided value is non-finite". 
 PASS   start(-Infinity) threw TypeError: "The provided value is non-finite". 
-PASS   Calling stop() before start() threw InvalidStateError: "The object is in an invalid state.". 
+PASS   Calling stop() before start() threw InvalidStateError: "cannot call stop without calling start first.". 
 PASS   start(-1) threw RangeError: "when value should be positive". 
 PASS   start(0,-1) threw RangeError: "offset value should be positive". 
 PASS   start(0,0,-1) threw RangeError: "duration value should be positive". 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic-expected.txt (267442 => 267443)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-constantsourcenode-interface/constant-source-basic-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -34,7 +34,7 @@
 PASS   start(NaN) threw TypeError: "The provided value is non-finite". 
 PASS   start(Infinity) threw TypeError: "The provided value is non-finite". 
 PASS   start(-Infinity) threw TypeError: "The provided value is non-finite". 
-PASS   Calling stop() before start() threw InvalidStateError: "The object is in an invalid state.". 
+PASS   Calling stop() before start() threw InvalidStateError: "cannot call stop without calling start first.". 
 PASS   start(-1) threw RangeError: "when value should be positive". 
 PASS   Calling start() twice threw InvalidStateError: "The object is in an invalid state.". 
 PASS   stop(-1) threw RangeError: "when value should be positive". 

Modified: trunk/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt (267442 => 267443)


--- trunk/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -20,13 +20,7 @@
 PASS   Case 6: loop from 4 -> 6 with playbackRate of 0.5: tail contains only the constant 0. 
 PASS   Case 7: loop from 4 -> 6 with playbackRate of 1.5 is identical to the array [0,1.5,3,4.5,4,5.5,5,4.5,4,5.5,5,4.5,4,5.5,5,4.5...]. 
 PASS   Case 7: loop from 4 -> 6 with playbackRate of 1.5: tail contains only the constant 0. 
-FAIL X Case 8: loop from 2 -> 5 with offset 6 expected to be equal to the array [2,3,4,2,3,4,2,3,4,2,3,4,2,3,4,2...] but differs in 16 places:
-	Index	Actual			Expected
-	[0]	3.0000000000000000e+0	2.0000000000000000e+0
-	[1]	4.0000000000000000e+0	3.0000000000000000e+0
-	[2]	2.0000000000000000e+0	4.0000000000000000e+0
-	[3]	3.0000000000000000e+0	2.0000000000000000e+0
-	...and 12 more errors. assert_true: expected true got false
+PASS   Case 8: loop from 2 -> 5 with offset 6 is identical to the array [2,3,4,2,3,4,2,3,4,2,3,4,2,3,4,2...]. 
 PASS   Case 8: loop from 2 -> 5 with offset 6: tail contains only the constant 0. 
 PASS   Case 9: loop from 3 -> 6 with offset 1 is identical to the array [1,2,3,4,5,3,4,5,3,4,5,3,4,5,3,4...]. 
 PASS   Case 9: loop from 3 -> 6 with offset 1: tail contains only the constant 0. 
@@ -42,39 +36,12 @@
 PASS   Case 14: illegal loop: loopStartFrame < 0: tail contains only the constant 0. 
 PASS   Case 15: illegal loop: loopEndFrame > bufferLength is identical to the array [0,1,2,3,4,5,6,7,0,1,2,3,4,5,6,7...]. 
 PASS   Case 15: illegal loop: loopEndFrame > bufferLength: tail contains only the constant 0. 
-FAIL X Case 16: loop from 3 -> 6 with offset 1 for 20 frames expected to be equal to the array [1,2,3,4,5,3,4,5,3,4,5,3,4,5,3,4...] but differs in 10 places:
-	Index	Actual			Expected
-	[20]	3.0000000000000000e+0	0.0000000000000000e+0
-	[21]	4.0000000000000000e+0	0.0000000000000000e+0
-	[22]	5.0000000000000000e+0	0.0000000000000000e+0
-	[23]	3.0000000000000000e+0	0.0000000000000000e+0
-	...and 6 more errors. assert_true: expected true got false
-FAIL X Case 16: loop from 3 -> 6 with offset 1 for 20 frames: tail: Expected 0 for all values but found 2 unexpected values: 
-	Index	Actual
-	[0]	4
-	[1]	5 assert_true: expected true got false
-FAIL X Case 17: loop from 3 -> 8 with offset 1 for 3 frames expected to be equal to the array [1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0...] but differs in 30 places:
-	Index	Actual			Expected
-	[0]	4.0000000000000000e+0	1.0000000000000000e+0
-	[1]	6.0000000000000000e+0	2.0000000000000000e+0
-	[2]	8.0000000000000000e+0	3.0000000000000000e+0
-	[3]	6.0000000000000000e+0	0.0000000000000000e+0
-	...and 26 more errors. assert_true: expected true got false
-FAIL X Case 17: loop from 3 -> 8 with offset 1 for 3 frames: tail: Expected 0 for all values but found 2 unexpected values: 
-	Index	Actual
-	[0]	6
-	[1]	7 assert_true: expected true got false
-FAIL X Case 18: loop from 3 -> 8 with offset 7 for 3 frames expected to be equal to the array [7,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0...] but differs in 30 places:
-	Index	Actual			Expected
-	[0]	1.5000000000000000e+1	7.0000000000000000e+0
-	[1]	9.0000000000000000e+0	3.0000000000000000e+0
-	[2]	1.1000000000000000e+1	4.0000000000000000e+0
-	[3]	1.3000000000000000e+1	0.0000000000000000e+0
-	...and 26 more errors. assert_true: expected true got false
-FAIL X Case 18: loop from 3 -> 8 with offset 7 for 3 frames: tail: Expected 0 for all values but found 2 unexpected values: 
-	Index	Actual
-	[0]	15
-	[1]	9 assert_true: expected true got false
-FAIL < [AudioBufferSource looping test] 7 out of 39 assertions were failed. assert_true: expected true got false
-FAIL # AUDIT TASK RUNNER FINISHED: 1 out of 1 tasks were failed. assert_true: expected true got false
+PASS   Case 16: loop from 3 -> 6 with offset 1 for 20 frames is identical to the array [1,2,3,4,5,3,4,5,3,4,5,3,4,5,3,4...]. 
+PASS   Case 16: loop from 3 -> 6 with offset 1 for 20 frames: tail contains only the constant 0. 
+PASS   Case 17: loop from 3 -> 8 with offset 1 for 3 frames is identical to the array [1,2,3,0,0,0,0,0,0,0,0,0,0,0,0,0...]. 
+PASS   Case 17: loop from 3 -> 8 with offset 1 for 3 frames: tail contains only the constant 0. 
+PASS   Case 18: loop from 3 -> 8 with offset 7 for 3 frames is identical to the array [7,3,4,0,0,0,0,0,0,0,0,0,0,0,0,0...]. 
+PASS   Case 18: loop from 3 -> 8 with offset 7 for 3 frames: tail contains only the constant 0. 
+PASS < [AudioBufferSource looping test] All assertions passed. (total 39 assertions) 
+PASS # AUDIT TASK RUNNER FINISHED: 1 tasks ran successfully. 
 

Modified: trunk/LayoutTests/webaudio/Oscillator/oscillator-basic-expected.txt (267442 => 267443)


--- trunk/LayoutTests/webaudio/Oscillator/oscillator-basic-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/webaudio/Oscillator/oscillator-basic-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -18,7 +18,7 @@
 PASS   start(NaN) threw TypeError: "The provided value is non-finite". 
 PASS   start(Infinity) threw TypeError: "The provided value is non-finite". 
 PASS   start(-Infinity) threw TypeError: "The provided value is non-finite". 
-PASS   Calling stop() before start() threw InvalidStateError: "The object is in an invalid state.". 
+PASS   Calling stop() before start() threw InvalidStateError: "cannot call stop without calling start first.". 
 PASS   start(-1) threw RangeError: "when value should be positive". 
 PASS   Calling start() twice threw InvalidStateError: "The object is in an invalid state.". 
 PASS   stop(-1) threw RangeError: "when value should be positive". 

Modified: trunk/LayoutTests/webaudio/audiobuffersource-exception-expected.txt (267442 => 267443)


--- trunk/LayoutTests/webaudio/audiobuffersource-exception-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/webaudio/audiobuffersource-exception-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -2,9 +2,9 @@
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
-PASS bufferSource.stop(0) threw exception InvalidStateError: The object is in an invalid state..
+PASS bufferSource.stop(0) threw exception InvalidStateError: cannot call stop without calling start first..
 PASS bufferSource.start(0) threw exception InvalidStateError: Cannot call start more than once..
-PASS bufferSource.stop(0) threw exception InvalidStateError: The object is in an invalid state..
+PASS InvalidStateError did not throw exception.
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/webaudio/audiobuffersource-exception.html (267442 => 267443)


--- trunk/LayoutTests/webaudio/audiobuffersource-exception.html	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/webaudio/audiobuffersource-exception.html	2020-09-22 22:52:42 UTC (rev 267443)
@@ -22,7 +22,7 @@
 
     var sampleRate = 44100.0;
     var numberOfFrames = 32;
-    var context = new webkitOfflineAudioContext(1, numberOfFrames, sampleRate);
+    var context = new OfflineAudioContext(1, numberOfFrames, sampleRate);
     bufferSource = context.createBufferSource();
     bufferSource.buffer = createTestBuffer(context, numberOfFrames);
     bufferSource.connect(context.destination);
@@ -35,8 +35,7 @@
     shouldThrowErrorName("bufferSource.start(0)", "InvalidStateError");
     bufferSource.stop(0);
 
-    // 'stop' should be called only once.
-    shouldThrowErrorName("bufferSource.stop(0)", "InvalidStateError");
+    shouldNotThrow("bufferSource.stop(0)", "InvalidStateError");
 
     context._oncomplete_ = finishJSTest;
     context.startRendering();

Modified: trunk/LayoutTests/webaudio/dom-exceptions-expected.txt (267442 => 267443)


--- trunk/LayoutTests/webaudio/dom-exceptions-expected.txt	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/LayoutTests/webaudio/dom-exceptions-expected.txt	2020-09-22 22:52:42 UTC (rev 267443)
@@ -189,7 +189,7 @@
 PASS   source4.start() did not throw an exception. 
 PASS   source5 = context.createBufferSource() did not throw an exception. 
 PASS   source5.buffer = buffer did not throw an exception. 
-PASS   source5.stop() threw InvalidStateError: "The object is in an invalid state.". 
+PASS   source5.stop() threw InvalidStateError: "cannot call stop without calling start first.". 
 PASS   source6 = context.createBufferSource() did not throw an exception. 
 PASS   source6.buffer = buffer did not throw an exception. 
 PASS   source6.start() did not throw an exception. 
@@ -212,7 +212,7 @@
 PASS   source8.stop(NaN) threw TypeError: "The provided value is non-finite". 
 PASS   source8.stop() did not throw an exception. 
 PASS   osc = context.createOscillator() did not throw an exception. 
-PASS   osc.stop() threw InvalidStateError: "The object is in an invalid state.". 
+PASS   osc.stop() threw InvalidStateError: "cannot call stop without calling start first.". 
 PASS   osc1 = context.createOscillator() did not throw an exception. 
 PASS   osc1.start() did not throw an exception. 
 PASS   osc1.stop() did not throw an exception. 

Modified: trunk/Source/WebCore/ChangeLog (267442 => 267443)


--- trunk/Source/WebCore/ChangeLog	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/Source/WebCore/ChangeLog	2020-09-22 22:52:42 UTC (rev 267443)
@@ -1,3 +1,30 @@
+2020-09-22  Chris Dumez  <[email protected]>
+
+        Merge AudioBufferSourceNode loop fixes from Blink
+        https://bugs.webkit.org/show_bug.cgi?id=216849
+
+        Reviewed by Eric Carlson.
+
+        Merge AudioBufferSourceNode loop fixes from Blink, the following one in particular:
+        - https://codereview.chromium.org/723823002
+
+        This allows us to pass all the checks in:
+        webaudio/AudioBufferSource/audiobuffersource-loop-comprehensive.html.
+
+        No new tests, rebaselined existing test.
+
+        * Modules/webaudio/AudioBufferSourceNode.cpp:
+        (WebCore::AudioBufferSourceNode::renderFromBuffer):
+        (WebCore::AudioBufferSourceNode::adjustGrainParameters):
+        Merge loop fixes from Blink.
+
+        * Modules/webaudio/AudioScheduledSourceNode.cpp:
+        (WebCore::AudioScheduledSourceNode::stopLater):
+        Stop throwing when m_endTime is already set. Our behavior did not match
+        Chrome and Firefox here. This was causing some existing tests to start
+        failing now that providing a grain duration when calling start() would
+        set m_endTime if loop() returns true.
+
 2020-09-22  Sihui Liu  <[email protected]>
 
         REGRESSION(r266075): WebContent process crashes at TextManipulationController::getPath

Modified: trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp (267442 => 267443)


--- trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp	2020-09-22 22:52:42 UTC (rev 267443)
@@ -242,6 +242,13 @@
         virtualDeltaFrames = virtualMaxFrame - virtualMinFrame;
     }
 
+    // If we're looping and the offset (virtualReadIndex) is past the end of the loop, wrap back to the
+    // beginning of the loop. For other cases, nothing needs to be done.
+    if (loop() && m_virtualReadIndex >= virtualMaxFrame) {
+        m_virtualReadIndex = (m_loopStart < 0) ? 0 : (m_loopStart * buffer()->sampleRate());
+        m_virtualReadIndex = std::min(m_virtualReadIndex, static_cast<double>(bufferLength - 1));
+    }
+
     // Sanity check that our playback rate isn't larger than the loop size.
     if (std::abs(pitchRate) > virtualDeltaFrames)
         return false;
@@ -516,12 +523,18 @@
 
     m_grainOffset = std::min(bufferDuration, m_grainOffset);
 
-    double maxDuration = bufferDuration - m_grainOffset;
+    if (!m_wasGrainDurationGiven)
+        m_grainDuration = bufferDuration - m_grainOffset;
 
-    if (m_wasGrainDurationGiven)
-        m_grainDuration = std::min(m_grainDuration, maxDuration);
-    else
-        m_grainDuration = maxDuration;
+    if (m_wasGrainDurationGiven && loop()) {
+        // We're looping a grain with a grain duration specified. Schedule the loop
+        // to stop after grainDuration seconds after starting, possibly running the
+        // loop multiple times if grainDuration is larger than the buffer duration.
+        // The net effect is as if the user called stop(when + grainDuration).
+        m_grainDuration = clampTo(m_grainDuration, 0.0, std::numeric_limits<double>::infinity());
+        m_endTime = m_startTime + m_grainDuration;
+    } else
+        m_grainDuration = clampTo(m_grainDuration, 0.0,  bufferDuration - m_grainOffset);
 
     // We call timeToSampleFrame here since at playbackRate == 1 we don't want to go through linear interpolation
     // at a sub-sample position since it will degrade the quality.

Modified: trunk/Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp (267442 => 267443)


--- trunk/Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp	2020-09-22 22:40:17 UTC (rev 267442)
+++ trunk/Source/WebCore/Modules/webaudio/AudioScheduledSourceNode.cpp	2020-09-22 22:52:42 UTC (rev 267443)
@@ -174,8 +174,8 @@
     ASSERT(isMainThread());
     ALWAYS_LOG(LOGIDENTIFIER, when);
 
-    if (m_playbackState == UNSCHEDULED_STATE || m_endTime != UnknownTime)
-        return Exception { InvalidStateError };
+    if (m_playbackState == UNSCHEDULED_STATE)
+        return Exception { InvalidStateError, "cannot call stop without calling start first."_s };
 
     if (!std::isfinite(when) || when < 0)
         return Exception { RangeError, "when value should be positive"_s };
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to