| Index: third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html
|
| diff --git a/third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html b/third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html
|
| index 6708c3d57c7d90f6ff748703d6aa0143d95db4aa..01d69da5f9bdc8573069ebb40cecdee5d64a2dd9 100644
|
| --- a/third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html
|
| +++ b/third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html
|
| @@ -1,176 +1,183 @@
|
| <!DOCTYPE html>
|
| <html>
|
| -
|
| -<head>
|
| - <script src="../../resources/testharness.js"></script>
|
| - <script src="../../resources/testharnessreport.js"></script>
|
| - <script src="../resources/audit-util.js"></script>
|
| - <script src="../resources/audit.js"></script>
|
| -</head>
|
| -
|
| -<body>
|
| - <script>
|
| - var sampleRate = 44100;
|
| - var renderDuration = 0.5;
|
| -
|
| - // The threshold for glitch detection. This was experimentally determined.
|
| - var GLITCH_THRESHOLD = 0.0005;
|
| -
|
| - // The maximum threshold for the error between the actual and the expected
|
| - // sample values. Experimentally determined.
|
| - var MAX_ERROR_ALLOWED = 0.0000001;
|
| -
|
| - // Option for |Should| test util. The number of array elements to be printed
|
| - // out is arbitrary.
|
| - var SHOULD_OPTS = {
|
| - numberOfArrayLog: 2
|
| - };
|
| -
|
| - var audit = Audit.createTaskRunner();
|
| -
|
| - // Extract a transitional region from the AudioBuffer. If no transition
|
| - // found, fail this test.
|
| - function extractPanningTransition(should, input, prefix) {
|
| - var chanL = input.getChannelData(0);
|
| - var chanR = input.getChannelData(1);
|
| - var start, end;
|
| - var index = 1;
|
| -
|
| - // Find transition by comparing two consecutive samples. If two consecutive
|
| - // samples are identical, the transition has not started.
|
| - while (chanL[index-1] === chanL[index] || chanR[index-1] === chanR[index]) {
|
| - if (++index >= input.length) {
|
| - should(false, prefix + ': Transition in the channel data')
|
| - .summarize('found', 'not found');
|
| - return null;
|
| + <head>
|
| + <title>
|
| + stereopannernode-no-glitch.html
|
| + </title>
|
| + <script src="../../resources/testharness.js"></script>
|
| + <script src="../../resources/testharnessreport.js"></script>
|
| + <script src="../resources/audit-util.js"></script>
|
| + <script src="../resources/audit.js"></script>
|
| + </head>
|
| + <body>
|
| + <script id="layout-test-code">
|
| + let sampleRate = 44100;
|
| + let renderDuration = 0.5;
|
| +
|
| + // The threshold for glitch detection. This was experimentally determined.
|
| + let GLITCH_THRESHOLD = 0.0005;
|
| +
|
| + // The maximum threshold for the error between the actual and the expected
|
| + // sample values. Experimentally determined.
|
| + let MAX_ERROR_ALLOWED = 0.0000001;
|
| +
|
| + // Option for |Should| test util. The number of array elements to be
|
| + // printed out is arbitrary.
|
| + let SHOULD_OPTS = {numberOfArrayLog: 2};
|
| +
|
| + let audit = Audit.createTaskRunner();
|
| +
|
| + // Extract a transitional region from the AudioBuffer. If no transition
|
| + // found, fail this test.
|
| + function extractPanningTransition(should, input, prefix) {
|
| + let chanL = input.getChannelData(0);
|
| + let chanR = input.getChannelData(1);
|
| + let start, end;
|
| + let index = 1;
|
| +
|
| + // Find transition by comparing two consecutive samples. If two
|
| + // consecutive samples are identical, the transition has not started.
|
| + while (chanL[index - 1] === chanL[index] ||
|
| + chanR[index - 1] === chanR[index]) {
|
| + if (++index >= input.length) {
|
| + should(false, prefix + ': Transition in the channel data')
|
| + .summarize('found', 'not found');
|
| + return null;
|
| + }
|
| }
|
| - }
|
| - start = index - 1;
|
| -
|
| - // Find the end of transition. If two consecutive samples are not equal,
|
| - // the transition is still ongoing.
|
| - while (chanL[index-1] !== chanL[index] || chanR[index-1] !== chanR[index]) {
|
| - if (++index >= input.length) {
|
| - should(false, 'Transition found')
|
| - .summarize('', 'but the buffer ended prematurely');
|
| - return null;
|
| + start = index - 1;
|
| +
|
| + // Find the end of transition. If two consecutive samples are not equal,
|
| + // the transition is still ongoing.
|
| + while (chanL[index - 1] !== chanL[index] ||
|
| + chanR[index - 1] !== chanR[index]) {
|
| + if (++index >= input.length) {
|
| + should(false, 'Transition found')
|
| + .summarize('', 'but the buffer ended prematurely');
|
| + return null;
|
| + }
|
| }
|
| + end = index;
|
| +
|
| + return {
|
| + left: chanL.subarray(start, end),
|
| + right: chanR.subarray(start, end),
|
| + length: end - start
|
| + };
|
| }
|
| - end = index;
|
| -
|
| - return {
|
| - left: chanL.subarray(start, end),
|
| - right: chanR.subarray(start, end),
|
| - length: end - start
|
| - };
|
| - }
|
| -
|
| - // JS implementation of stereo equal power panning.
|
| - function panStereoEqualPower(pan, inputL, inputR) {
|
| - pan = Math.min(1.0, Math.max(-1.0, pan));
|
| - var output = [];
|
| - var panRadian;
|
| - if (!inputR) { // mono case.
|
| - panRadian = (pan * 0.5 + 0.5) * Math.PI / 2;
|
| - output[0] = inputL * Math.cos(panRadian);
|
| - output[1] = inputR * Math.sin(panRadian);
|
| - } else { // stereo case.
|
| - panRadian = (pan <= 0 ? pan + 1 : pan) * Math.PI / 2;
|
| - var gainL = Math.cos(panRadian);
|
| - var gainR = Math.sin(panRadian);
|
| - if (pan <= 0) {
|
| - output[0] = inputL + inputR * gainL;
|
| - output[1] = inputR * gainR;
|
| - } else {
|
| - output[0] = inputL * gainL;
|
| - output[1] = inputR + inputL * gainR;
|
| +
|
| + // JS implementation of stereo equal power panning.
|
| + function panStereoEqualPower(pan, inputL, inputR) {
|
| + pan = Math.min(1.0, Math.max(-1.0, pan));
|
| + let output = [];
|
| + let panRadian;
|
| + if (!inputR) { // mono case.
|
| + panRadian = (pan * 0.5 + 0.5) * Math.PI / 2;
|
| + output[0] = inputL * Math.cos(panRadian);
|
| + output[1] = inputR * Math.sin(panRadian);
|
| + } else { // stereo case.
|
| + panRadian = (pan <= 0 ? pan + 1 : pan) * Math.PI / 2;
|
| + let gainL = Math.cos(panRadian);
|
| + let gainR = Math.sin(panRadian);
|
| + if (pan <= 0) {
|
| + output[0] = inputL + inputR * gainL;
|
| + output[1] = inputR * gainR;
|
| + } else {
|
| + output[0] = inputL * gainL;
|
| + output[1] = inputR + inputL * gainR;
|
| + }
|
| }
|
| - }
|
| - return output;
|
| - }
|
| -
|
| - // Generate the expected result of stereo equal panning. |input| is an
|
| - // AudioBuffer to be panned.
|
| - function generateStereoEqualPanningResult(input, startPan, endPan, length) {
|
| -
|
| - // Smoothing constant time is 0.05 second.
|
| - var smoothingConstant = 1 - Math.exp(-1 / (sampleRate * 0.05));
|
| -
|
| - var inputL = input.getChannelData(0);
|
| - var inputR = input.getChannelData(1);
|
| - var pan = startPan;
|
| - var outputL = [], outputR = [];
|
| -
|
| - for (var i = 0; i < length; i++) {
|
| - var samples = panStereoEqualPower(pan, inputL[i], inputR[i]);
|
| - outputL[i] = samples[0];
|
| - outputR[i] = samples[1];
|
| - pan += (endPan - pan) * smoothingConstant;
|
| + return output;
|
| }
|
|
|
| - return {
|
| - left: outputL,
|
| - right: outputR
|
| - };
|
| - }
|
| -
|
| - // Build audio graph and render. Change the pan parameter in the middle of
|
| - // rendering.
|
| - function panAndVerify(should, options) {
|
| - var context = new OfflineAudioContext(2, renderDuration * sampleRate, sampleRate);
|
| - var source = context.createBufferSource();
|
| - var panner = context.createStereoPanner();
|
| - var stereoBuffer = createConstantBuffer(context, renderDuration * sampleRate, [1.0, 1.0]);
|
| -
|
| - source.buffer = stereoBuffer;
|
| -
|
| - panner.pan.value = options.startPanValue;
|
| -
|
| - source.connect(panner);
|
| - panner.connect(context.destination);
|
| - source.start();
|
| -
|
| - // Schedule the parameter transition by the setter at 1/10 of the render
|
| - // duration.
|
| - context.suspend(0.1 * renderDuration).then(function () {
|
| - panner.pan.value = options.endPanValue;
|
| - context.resume();
|
| - });
|
| + // Generate the expected result of stereo equal panning. |input| is an
|
| + // AudioBuffer to be panned.
|
| + function generateStereoEqualPanningResult(
|
| + input, startPan, endPan, length) {
|
| + // Smoothing constant time is 0.05 second.
|
| + let smoothingConstant = 1 - Math.exp(-1 / (sampleRate * 0.05));
|
| +
|
| + let inputL = input.getChannelData(0);
|
| + let inputR = input.getChannelData(1);
|
| + let pan = startPan;
|
| + let outputL = [], outputR = [];
|
| +
|
| + for (let i = 0; i < length; i++) {
|
| + let samples = panStereoEqualPower(pan, inputL[i], inputR[i]);
|
| + outputL[i] = samples[0];
|
| + outputR[i] = samples[1];
|
| + pan += (endPan - pan) * smoothingConstant;
|
| + }
|
|
|
| - return context.startRendering().then(function (buffer) {
|
| - var actual = extractPanningTransition(should, buffer, options.message);
|
| - var expected = generateStereoEqualPanningResult(stereoBuffer,
|
| - options.startPanValue, options.endPanValue, actual.length);
|
| + return {left: outputL, right: outputR};
|
| + }
|
|
|
| - // |notGlitch| tests are redundant if the actual and expected results
|
| - // match and if the expected results themselves don't glitch.
|
| - should(actual.left, options.message + ': Channel #0').notGlitch(GLITCH_THRESHOLD);
|
| - should(actual.right, options.message + ': Channel #1').notGlitch(GLITCH_THRESHOLD);
|
| + // Build audio graph and render. Change the pan parameter in the middle of
|
| + // rendering.
|
| + function panAndVerify(should, options) {
|
| + let context =
|
| + new OfflineAudioContext(2, renderDuration * sampleRate, sampleRate);
|
| + let source = context.createBufferSource();
|
| + let panner = context.createStereoPanner();
|
| + let stereoBuffer = createConstantBuffer(
|
| + context, renderDuration * sampleRate, [1.0, 1.0]);
|
| +
|
| + source.buffer = stereoBuffer;
|
| +
|
| + panner.pan.value = options.startPanValue;
|
| +
|
| + source.connect(panner);
|
| + panner.connect(context.destination);
|
| + source.start();
|
| +
|
| + // Schedule the parameter transition by the setter at 1/10 of the render
|
| + // duration.
|
| + context.suspend(0.1 * renderDuration).then(function() {
|
| + panner.pan.value = options.endPanValue;
|
| + context.resume();
|
| + });
|
| +
|
| + return context.startRendering().then(function(buffer) {
|
| + let actual =
|
| + extractPanningTransition(should, buffer, options.message);
|
| + let expected = generateStereoEqualPanningResult(
|
| + stereoBuffer, options.startPanValue, options.endPanValue,
|
| + actual.length);
|
| +
|
| + // |notGlitch| tests are redundant if the actual and expected results
|
| + // match and if the expected results themselves don't glitch.
|
| + should(actual.left, options.message + ': Channel #0')
|
| + .notGlitch(GLITCH_THRESHOLD);
|
| + should(actual.right, options.message + ': Channel #1')
|
| + .notGlitch(GLITCH_THRESHOLD);
|
| +
|
| + should(actual.left, options.message + ': Channel #0', SHOULD_OPTS)
|
| + .beCloseToArray(
|
| + expected.left, {absoluteThreshold: MAX_ERROR_ALLOWED});
|
| + should(actual.right, options.message + ': Channel #1', SHOULD_OPTS)
|
| + .beCloseToArray(
|
| + expected.right, {absoluteThreshold: MAX_ERROR_ALLOWED});
|
| + });
|
| + }
|
|
|
| - should(actual.left, options.message + ': Channel #0', SHOULD_OPTS)
|
| - .beCloseToArray(expected.left, {absoluteThreshold: MAX_ERROR_ALLOWED});
|
| - should(actual.right, options.message + ': Channel #1', SHOULD_OPTS)
|
| - .beCloseToArray(expected.right, {absoluteThreshold: MAX_ERROR_ALLOWED});
|
| + // Task: move pan from negative (-0.1) to positive (0.1) value to check if
|
| + // there is a glitch during the transition. See crbug.com/470559.
|
| + audit.define('negative-to-positive', (task, should) => {
|
| + panAndVerify(
|
| + should, {startPanValue: -0.1, endPanValue: 0.1, message: 'L->R'})
|
| + .then(() => task.done());
|
| });
|
| - }
|
|
|
| - // Task: move pan from negative (-0.1) to positive (0.1) value to check if
|
| - // there is a glitch during the transition. See crbug.com/470559.
|
| - audit.define('negative-to-positive', (task, should) => {
|
| - panAndVerify(should, { startPanValue: -0.1, endPanValue: 0.1, message: "L->R" })
|
| - .then(() => task.done());
|
| - });
|
|
|
| + // Task: move pan from positive (0.1) to negative (-0.1) value to check if
|
| + // there is a glitch during the transition.
|
| + audit.define('positive-to-negative', (task, should) => {
|
| + panAndVerify(
|
| + should, {startPanValue: 0.1, endPanValue: -0.1, message: 'R->L'})
|
| + .then(() => task.done());
|
| + });
|
|
|
| - // Task: move pan from positive (0.1) to negative (-0.1) value to check if
|
| - // there is a glitch during the transition.
|
| - audit.define('positive-to-negative', (task, should) => {
|
| - panAndVerify(should, { startPanValue: 0.1, endPanValue: -0.1, message: "R->L" })
|
| - .then(() => task.done());
|
| - });
|
| -
|
| - audit.run();
|
| - </script>
|
| -</body>
|
| -
|
| + audit.run();
|
| + </script>
|
| + </body>
|
| </html>
|
|
|