Chromium Code Reviews| Index: third_party/WebKit/LayoutTests/webaudio/panner-automation-basic.html |
| diff --git a/third_party/WebKit/LayoutTests/webaudio/panner-automation-basic.html b/third_party/WebKit/LayoutTests/webaudio/panner-automation-basic.html |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..e6026093366f165137db01745e5c6a53388abc74 |
| --- /dev/null |
| +++ b/third_party/WebKit/LayoutTests/webaudio/panner-automation-basic.html |
| @@ -0,0 +1,283 @@ |
| +<!doctype html> |
| +<html> |
| + <head> |
| + <script src="../resources/js-test.js"></script> |
| + <script src="resources/compatibility.js"></script> |
| + <script src="resources/audio-testing.js"></script> |
| + <script src="resources/panner-formulas.js"></script> |
| + <title>Test Basic Panner Position Properties</title> |
| + </head> |
| + |
| + <body> |
| + <script> |
| + description("Test Basic SpatialPannerNode Properties."); |
| + window.jsTestIsAsync = true; |
| + |
| + var sampleRate = 48000; |
| + |
| + // These tests are quite slow, so don't run for many frames. 256 frames should be enough to |
| + // demonstrate that automations are working. |
| + var renderFrames = 256; |
| + var renderDuration = renderFrames / sampleRate; |
| + |
| + var audit = Audit.createTaskRunner(); |
| + |
| + audit.defineTask("panner position x-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
|
hongchan
2016/05/03 18:15:01
How about:
var nodes = { context, source, panner
Raymond Toy
2016/05/03 20:32:21
No problems with this, but js-beautify wants to in
hongchan
2016/05/03 20:38:58
That's perhaps because js-beautify doesn't know ab
Raymond Toy
2016/05/03 20:46:47
Yes, js-beautify probably doesn't know. Isn't mul
Raymond Toy
2016/05/03 21:03:45
Done, except no multiple assignment.
|
| + |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: panner.positionX, |
| + message: "panner.positionX" |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("panner position y-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
|
hongchan
2016/05/03 18:15:01
ditto.
Raymond Toy
2016/05/03 21:03:45
Done.
|
| + |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: panner.positionY, |
| + message: "panner.positionY" |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("panner position z-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
|
hongchan
2016/05/03 18:15:01
ditto.
Raymond Toy
2016/05/03 21:03:45
Done.
|
| + |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: panner.positionZ, |
| + message: "panner.positionZ" |
| + }).then(done); |
| + }); |
| + |
| + // This test currently fails because of the dezippering of the distance and cone gain that |
| + // happens when setPosition is used. |
| + audit.defineTask("setPosition", function (done) { |
| + var { context, panner, source } = createGraph(); |
| + |
| + // Initialize source position (values don't really matter). |
| + panner.setPosition(1,1,1); |
| + |
| + // After some (unimportant) time, move the panner to a (any) new location. |
| + var suspendFrame = 128; |
| + context.suspend(suspendFrame / sampleRate).then(function () { |
| + panner.setPosition(-100, 2000, 8000); |
| + }).then(context.resume.bind(context)); |
| + |
| + context.startRendering().then(function (resultBuffer) { |
| + verifyPannerOutputChanged(resultBuffer, {message: "setPosition", suspendFrame: suspendFrame}); |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("orientation setter", function (done) { |
| + var { context, panner, source } = createGraph(); |
| + |
| + // For orientation to matter, we need to make the source directional, and also move away |
| + // from the listener (because the default location is 0,0,0). |
| + panner.setPosition(0,0,1); |
| + panner.coneInnerAngle = 0; |
| + panner.coneOuterAngle = 360; |
| + panner.coneOuterGain = .001; |
| + |
| + // After some (unimportant) time, change the panner orientation to a new orientation. The |
| + // only constraint is that the orientation changes from before. |
| + var suspendFrame = 128; |
| + context.suspend(suspendFrame / sampleRate).then(function () { |
| + panner.orientationX.value = -100; |
| + panner.orientationY.value = 2000; |
| + panner.orientationZ.value = 8000; |
| + }).then(context.resume.bind(context)); |
| + |
| + context.startRendering().then(function (resultBuffer) { |
| + verifyPannerOutputChanged(resultBuffer, {message: "panner.orientation{XYZ}", suspendFrame: suspendFrame}); |
| + }).then(done); |
| + }); |
| + |
| + |
| + audit.defineTask("listener x-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
| + |
| + panner.setPosition(1,0,1); |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: context.listener.positionX, |
| + message: "listener.positionX" |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("listener y-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
| + |
| + panner.setPosition(1,0,1); |
| + //panner.setOrientation(0, 0, -1); |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: context.listener.positionY, |
| + message: "listener.positionY" |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("listener z-setter", function (done) { |
| + var nodes = createGraph(); |
| + var { |
| + context, source, panner |
| + } = nodes; |
| + |
| + panner.setPosition(1,0,1); |
| + //panner.setOrientation(0, 0, -1); |
| + testPositionSetter({ |
| + nodes: nodes, |
| + pannerSetter: context.listener.positionZ, |
| + message: "listener.positionZ" |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("forward setter", function (done) { |
| + var { context, panner, source } = createGraph(); |
| + |
| + // For orientation to matter, we need to make the source directional, and also move away |
| + // from the listener (because the default location is 0,0,0). |
| + panner.setPosition(0,0,1); |
| + panner.coneInnerAngle = 0; |
| + panner.coneOuterAngle = 360; |
| + panner.coneOuterGain = .001; |
| + |
| + // After some (unimportant) time, change the panner orientation to a new orientation. The |
| + // only constraint is that the orientation changes from before. |
| + var suspendFrame = 128; |
| + context.suspend(suspendFrame / sampleRate).then(function () { |
| + context.listener.forwardX.value = -100; |
| + context.listener.forwardY.value = 2000; |
| + context.listener.forwardZ.value = 8000; |
| + }).then(context.resume.bind(context)); |
| + |
| + context.startRendering().then(function (resultBuffer) { |
| + verifyPannerOutputChanged(resultBuffer, {message: "listener.forward{XYZ}", suspendFrame: suspendFrame}); |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("up setter", function (done) { |
| + var { context, panner, source } = createGraph(); |
| + |
| + // For orientation to matter, we need to make the source directional, and also move away |
| + // from the listener (because the default location is 0,0,0). |
| + panner.setPosition(0,0,1); |
| + panner.coneInnerAngle = 0; |
| + panner.coneOuterAngle = 360; |
| + panner.coneOuterGain = .001; |
| + panner.setPosition(1,0,1); |
| + |
| + // After some (unimportant) time, change the panner orientation to a new orientation. The |
| + // only constraint is that the orientation changes from before. |
| + var suspendFrame = 128; |
| + context.suspend(suspendFrame / sampleRate).then(function () { |
| + context.listener.upX.value = 100; |
| + context.listener.upY.value = 100; |
| + context.listener.upZ.value = 100;; |
| + }).then(context.resume.bind(context)); |
| + |
| + context.startRendering().then(function (resultBuffer) { |
| + verifyPannerOutputChanged(resultBuffer, {message: "listener.up{XYZ}", suspendFrame: suspendFrame}); |
| + }).then(done); |
| + }); |
| + |
| + audit.defineTask("finish", function (done) { |
| + finishJSTest(); |
| + done(); |
| + }); |
| + |
| + audit.runTasks( |
| + //"setPosition", |
| + //"finish" |
|
hongchan
2016/05/03 18:15:01
I can accept this as a pattern. However, is this i
Raymond Toy
2016/05/03 20:32:21
No. A bit of debugging left over.
|
| + ); |
| + |
| + function createGraph() { |
| + var context = new OfflineAudioContext(2, renderFrames, sampleRate); |
| + var panner = context.createPanner(); |
| + var source = context.createBufferSource(); |
| + source.buffer = createConstantBuffer(context, 1, 1); |
| + source.loop = true; |
| + |
| + source.connect(panner); |
| + panner.connect(context.destination); |
| + |
| + source.start(); |
| + return { context: context, |
|
hongchan
2016/05/03 18:15:01
Let's add a line break after {.
Raymond Toy
2016/05/03 21:03:45
Done.
|
| + source: source, |
| + panner: panner |
| + }; |
| + } |
| + |
| + function testPositionSetter(options) { |
| + var { |
| + nodes, pannerSetter, message |
| + } = options; |
|
hongchan
2016/05/03 18:15:01
ditto here - let's put them in a single line.
Raymond Toy
2016/05/03 21:03:45
Done.
|
| + |
| + var { |
| + context, source, panner |
| + } = nodes; |
|
hongchan
2016/05/03 18:15:01
ditto.
Raymond Toy
2016/05/03 21:03:45
Done.
|
| + |
| + // Set panner x position. (Value doesn't matter); |
| + pannerSetter.value = 1; |
| + |
| + // Wait a bit and set a new position. (Actual time and position doesn't matter). |
| + var suspendFrame = 128; |
| + context.suspend(suspendFrame / sampleRate).then(function () { |
| + pannerSetter.value = 10000; |
| + }).then(context.resume.bind(context)); |
| + |
| + return context.startRendering().then(function (resultBuffer) { |
| + verifyPannerOutputChanged(resultBuffer, {message: message, suspendFrame: suspendFrame}); |
| + }); |
| + } |
| + |
| + function verifyPannerOutputChanged(resultBuffer, options) { |
| + var { message, suspendFrame } = options; |
| + // Verify that the first part of output is constant. (Doesn't matter what.) |
| + var success = true; |
| + var data0 = resultBuffer.getChannelData(0); |
| + var data1 = resultBuffer.getChannelData(1); |
| + |
| + success = Should(message + ".value at frame 0 channel 0", data0.slice(0, suspendFrame)) |
| + .beConstantValueOf(data0[0]) && success; |
| + success = Should(message + ".value at frame 0 channel 1", data1.slice(0, suspendFrame)) |
| + .beConstantValueOf(data1[0]) && success; |
| + |
| + // The rest after suspendTime should be constant and different from the first part. |
| + success = Should(message + ".value at frame " + suspendFrame + " channel 0", |
| + data0.slice(suspendFrame)) |
| + .beConstantValueOf(data0[suspendFrame]) && success; |
| + success = Should(message + ".value at frame " + suspendFrame + " channel 0", |
| + data1.slice(suspendFrame)) |
| + .beConstantValueOf(data1[suspendFrame]) && success; |
| + success = Should("Output at frame " + suspendFrame + " channel 0", data0[0]) |
| + .notBeEqualTo(data0[suspendFrame]) && success; |
| + success = Should("Output at frame " + suspendFrame + " channel 1", data1[0]) |
| + .notBeEqualTo(data1[suspendFrame]) && success; |
| + |
| + var prefix = "Directly setting " + message + ".value"; |
| + if (success) |
| + testPassed(prefix + " worked.\n"); |
| + else |
| + testFailed(prefix + " failed.\n"); |
| + } |
| + </script> |
| + </body> |
| +</html> |