Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/StereoPanner/stereopannernode-no-glitch.html

Issue 2895963003: Apply layout-test-tidy to LayoutTests/webaudio (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 <!DOCTYPE html> 1 <!DOCTYPE html>
2 <html> 2 <html>
3 <head>
4 <title>
5 stereopannernode-no-glitch.html
6 </title>
7 <script src="../../resources/testharness.js"></script>
8 <script src="../../resources/testharnessreport.js"></script>
9 <script src="../resources/audit-util.js"></script>
10 <script src="../resources/audit.js"></script>
11 </head>
12 <body>
13 <script id="layout-test-code">
14 let sampleRate = 44100;
15 let renderDuration = 0.5;
3 16
4 <head> 17 // The threshold for glitch detection. This was experimentally determined.
5 <script src="../../resources/testharness.js"></script> 18 let GLITCH_THRESHOLD = 0.0005;
6 <script src="../../resources/testharnessreport.js"></script>
7 <script src="../resources/audit-util.js"></script>
8 <script src="../resources/audit.js"></script>
9 </head>
10 19
11 <body> 20 // The maximum threshold for the error between the actual and the expected
12 <script> 21 // sample values. Experimentally determined.
13 var sampleRate = 44100; 22 let MAX_ERROR_ALLOWED = 0.0000001;
14 var renderDuration = 0.5;
15 23
16 // The threshold for glitch detection. This was experimentally determined. 24 // Option for |Should| test util. The number of array elements to be
17 var GLITCH_THRESHOLD = 0.0005; 25 // printed out is arbitrary.
26 let SHOULD_OPTS = {numberOfArrayLog: 2};
18 27
19 // The maximum threshold for the error between the actual and the expected 28 let audit = Audit.createTaskRunner();
20 // sample values. Experimentally determined.
21 var MAX_ERROR_ALLOWED = 0.0000001;
22 29
23 // Option for |Should| test util. The number of array elements to be printed 30 // Extract a transitional region from the AudioBuffer. If no transition
24 // out is arbitrary. 31 // found, fail this test.
25 var SHOULD_OPTS = { 32 function extractPanningTransition(should, input, prefix) {
26 numberOfArrayLog: 2 33 let chanL = input.getChannelData(0);
27 }; 34 let chanR = input.getChannelData(1);
35 let start, end;
36 let index = 1;
28 37
29 var audit = Audit.createTaskRunner(); 38 // Find transition by comparing two consecutive samples. If two
39 // consecutive samples are identical, the transition has not started.
40 while (chanL[index - 1] === chanL[index] ||
41 chanR[index - 1] === chanR[index]) {
42 if (++index >= input.length) {
43 should(false, prefix + ': Transition in the channel data')
44 .summarize('found', 'not found');
45 return null;
46 }
47 }
48 start = index - 1;
30 49
31 // Extract a transitional region from the AudioBuffer. If no transition 50 // Find the end of transition. If two consecutive samples are not equal,
32 // found, fail this test. 51 // the transition is still ongoing.
33 function extractPanningTransition(should, input, prefix) { 52 while (chanL[index - 1] !== chanL[index] ||
34 var chanL = input.getChannelData(0); 53 chanR[index - 1] !== chanR[index]) {
35 var chanR = input.getChannelData(1); 54 if (++index >= input.length) {
36 var start, end; 55 should(false, 'Transition found')
37 var index = 1; 56 .summarize('', 'but the buffer ended prematurely');
57 return null;
58 }
59 }
60 end = index;
38 61
39 // Find transition by comparing two consecutive samples. If two consecutiv e 62 return {
40 // samples are identical, the transition has not started. 63 left: chanL.subarray(start, end),
41 while (chanL[index-1] === chanL[index] || chanR[index-1] === chanR[index]) { 64 right: chanR.subarray(start, end),
42 if (++index >= input.length) { 65 length: end - start
43 should(false, prefix + ': Transition in the channel data') 66 };
44 .summarize('found', 'not found');
45 return null;
46 }
47 }
48 start = index - 1;
49
50 // Find the end of transition. If two consecutive samples are not equal,
51 // the transition is still ongoing.
52 while (chanL[index-1] !== chanL[index] || chanR[index-1] !== chanR[index]) {
53 if (++index >= input.length) {
54 should(false, 'Transition found')
55 .summarize('', 'but the buffer ended prematurely');
56 return null;
57 }
58 }
59 end = index;
60
61 return {
62 left: chanL.subarray(start, end),
63 right: chanR.subarray(start, end),
64 length: end - start
65 };
66 }
67
68 // JS implementation of stereo equal power panning.
69 function panStereoEqualPower(pan, inputL, inputR) {
70 pan = Math.min(1.0, Math.max(-1.0, pan));
71 var output = [];
72 var panRadian;
73 if (!inputR) { // mono case.
74 panRadian = (pan * 0.5 + 0.5) * Math.PI / 2;
75 output[0] = inputL * Math.cos(panRadian);
76 output[1] = inputR * Math.sin(panRadian);
77 } else { // stereo case.
78 panRadian = (pan <= 0 ? pan + 1 : pan) * Math.PI / 2;
79 var gainL = Math.cos(panRadian);
80 var gainR = Math.sin(panRadian);
81 if (pan <= 0) {
82 output[0] = inputL + inputR * gainL;
83 output[1] = inputR * gainR;
84 } else {
85 output[0] = inputL * gainL;
86 output[1] = inputR + inputL * gainR;
87 }
88 }
89 return output;
90 }
91
92 // Generate the expected result of stereo equal panning. |input| is an
93 // AudioBuffer to be panned.
94 function generateStereoEqualPanningResult(input, startPan, endPan, length) {
95
96 // Smoothing constant time is 0.05 second.
97 var smoothingConstant = 1 - Math.exp(-1 / (sampleRate * 0.05));
98
99 var inputL = input.getChannelData(0);
100 var inputR = input.getChannelData(1);
101 var pan = startPan;
102 var outputL = [], outputR = [];
103
104 for (var i = 0; i < length; i++) {
105 var samples = panStereoEqualPower(pan, inputL[i], inputR[i]);
106 outputL[i] = samples[0];
107 outputR[i] = samples[1];
108 pan += (endPan - pan) * smoothingConstant;
109 } 67 }
110 68
111 return { 69 // JS implementation of stereo equal power panning.
112 left: outputL, 70 function panStereoEqualPower(pan, inputL, inputR) {
113 right: outputR 71 pan = Math.min(1.0, Math.max(-1.0, pan));
114 }; 72 let output = [];
115 } 73 let panRadian;
74 if (!inputR) { // mono case.
75 panRadian = (pan * 0.5 + 0.5) * Math.PI / 2;
76 output[0] = inputL * Math.cos(panRadian);
77 output[1] = inputR * Math.sin(panRadian);
78 } else { // stereo case.
79 panRadian = (pan <= 0 ? pan + 1 : pan) * Math.PI / 2;
80 let gainL = Math.cos(panRadian);
81 let gainR = Math.sin(panRadian);
82 if (pan <= 0) {
83 output[0] = inputL + inputR * gainL;
84 output[1] = inputR * gainR;
85 } else {
86 output[0] = inputL * gainL;
87 output[1] = inputR + inputL * gainR;
88 }
89 }
90 return output;
91 }
116 92
117 // Build audio graph and render. Change the pan parameter in the middle of 93 // Generate the expected result of stereo equal panning. |input| is an
118 // rendering. 94 // AudioBuffer to be panned.
119 function panAndVerify(should, options) { 95 function generateStereoEqualPanningResult(
120 var context = new OfflineAudioContext(2, renderDuration * sampleRate, samp leRate); 96 input, startPan, endPan, length) {
121 var source = context.createBufferSource(); 97 // Smoothing constant time is 0.05 second.
122 var panner = context.createStereoPanner(); 98 let smoothingConstant = 1 - Math.exp(-1 / (sampleRate * 0.05));
123 var stereoBuffer = createConstantBuffer(context, renderDuration * sampleRa te, [1.0, 1.0]);
124 99
125 source.buffer = stereoBuffer; 100 let inputL = input.getChannelData(0);
101 let inputR = input.getChannelData(1);
102 let pan = startPan;
103 let outputL = [], outputR = [];
126 104
127 panner.pan.value = options.startPanValue; 105 for (let i = 0; i < length; i++) {
106 let samples = panStereoEqualPower(pan, inputL[i], inputR[i]);
107 outputL[i] = samples[0];
108 outputR[i] = samples[1];
109 pan += (endPan - pan) * smoothingConstant;
110 }
128 111
129 source.connect(panner); 112 return {left: outputL, right: outputR};
130 panner.connect(context.destination); 113 }
131 source.start();
132 114
133 // Schedule the parameter transition by the setter at 1/10 of the render 115 // Build audio graph and render. Change the pan parameter in the middle of
134 // duration. 116 // rendering.
135 context.suspend(0.1 * renderDuration).then(function () { 117 function panAndVerify(should, options) {
136 panner.pan.value = options.endPanValue; 118 let context =
137 context.resume(); 119 new OfflineAudioContext(2, renderDuration * sampleRate, sampleRate);
120 let source = context.createBufferSource();
121 let panner = context.createStereoPanner();
122 let stereoBuffer = createConstantBuffer(
123 context, renderDuration * sampleRate, [1.0, 1.0]);
124
125 source.buffer = stereoBuffer;
126
127 panner.pan.value = options.startPanValue;
128
129 source.connect(panner);
130 panner.connect(context.destination);
131 source.start();
132
133 // Schedule the parameter transition by the setter at 1/10 of the render
134 // duration.
135 context.suspend(0.1 * renderDuration).then(function() {
136 panner.pan.value = options.endPanValue;
137 context.resume();
138 });
139
140 return context.startRendering().then(function(buffer) {
141 let actual =
142 extractPanningTransition(should, buffer, options.message);
143 let expected = generateStereoEqualPanningResult(
144 stereoBuffer, options.startPanValue, options.endPanValue,
145 actual.length);
146
147 // |notGlitch| tests are redundant if the actual and expected results
148 // match and if the expected results themselves don't glitch.
149 should(actual.left, options.message + ': Channel #0')
150 .notGlitch(GLITCH_THRESHOLD);
151 should(actual.right, options.message + ': Channel #1')
152 .notGlitch(GLITCH_THRESHOLD);
153
154 should(actual.left, options.message + ': Channel #0', SHOULD_OPTS)
155 .beCloseToArray(
156 expected.left, {absoluteThreshold: MAX_ERROR_ALLOWED});
157 should(actual.right, options.message + ': Channel #1', SHOULD_OPTS)
158 .beCloseToArray(
159 expected.right, {absoluteThreshold: MAX_ERROR_ALLOWED});
160 });
161 }
162
163 // Task: move pan from negative (-0.1) to positive (0.1) value to check if
164 // there is a glitch during the transition. See crbug.com/470559.
165 audit.define('negative-to-positive', (task, should) => {
166 panAndVerify(
167 should, {startPanValue: -0.1, endPanValue: 0.1, message: 'L->R'})
168 .then(() => task.done());
138 }); 169 });
139 170
140 return context.startRendering().then(function (buffer) {
141 var actual = extractPanningTransition(should, buffer, options.message);
142 var expected = generateStereoEqualPanningResult(stereoBuffer,
143 options.startPanValue, options.endPanValue, actual.length);
144 171
145 // |notGlitch| tests are redundant if the actual and expected results 172 // Task: move pan from positive (0.1) to negative (-0.1) value to check if
146 // match and if the expected results themselves don't glitch. 173 // there is a glitch during the transition.
147 should(actual.left, options.message + ': Channel #0').notGlitch(GLITCH_T HRESHOLD); 174 audit.define('positive-to-negative', (task, should) => {
148 should(actual.right, options.message + ': Channel #1').notGlitch(GLITCH_ THRESHOLD); 175 panAndVerify(
176 should, {startPanValue: 0.1, endPanValue: -0.1, message: 'R->L'})
177 .then(() => task.done());
178 });
149 179
150 should(actual.left, options.message + ': Channel #0', SHOULD_OPTS) 180 audit.run();
151 .beCloseToArray(expected.left, {absoluteThreshold: MAX_ERROR_ALLOWED}) ; 181 </script>
152 should(actual.right, options.message + ': Channel #1', SHOULD_OPTS) 182 </body>
153 .beCloseToArray(expected.right, {absoluteThreshold: MAX_ERROR_ALLOWED} );
154 });
155 }
156
157 // Task: move pan from negative (-0.1) to positive (0.1) value to check if
158 // there is a glitch during the transition. See crbug.com/470559.
159 audit.define('negative-to-positive', (task, should) => {
160 panAndVerify(should, { startPanValue: -0.1, endPanValue: 0.1, message: "L- >R" })
161 .then(() => task.done());
162 });
163
164
165 // Task: move pan from positive (0.1) to negative (-0.1) value to check if
166 // there is a glitch during the transition.
167 audit.define('positive-to-negative', (task, should) => {
168 panAndVerify(should, { startPanValue: 0.1, endPanValue: -0.1, message: "R- >L" })
169 .then(() => task.done());
170 });
171
172 audit.run();
173 </script>
174 </body>
175
176 </html> 183 </html>
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698