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

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/resources/oscillator-testing.js

Issue 2675973003: Convert Oscillator sweep tests to testharness (Closed)
Patch Set: Update periodicwave-contexts test Created 3 years, 10 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
« no previous file with comments | « third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts-expected.txt ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Notes about generated waveforms: 1 // Notes about generated waveforms:
2 // 2 //
3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges) ? 3 // QUESTION: Why does the wave shape not look like the exact shape (sharp edges) ?
4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten t. 4 // ANSWER: Because a shape with sharp edges has infinitely high frequency conten t.
5 // Since a digital audio signal must be band-limited based on the nyquist freque ncy (half the sample-rate) 5 // Since a digital audio signal must be band-limited based on the nyquist freque ncy (half the sample-rate)
6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in the 6 // in order to avoid aliasing, this creates more rounded edges and "ringing" in the
7 // appearance of the waveform. See Nyquist-Shannon sampling theorem: 7 // appearance of the waveform. See Nyquist-Shannon sampling theorem:
8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem 8 // http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem
9 // 9 //
10 // QUESTION: Why does the very end of the generated signal appear to get slightl y weaker? 10 // QUESTION: Why does the very end of the generated signal appear to get slightl y weaker?
11 // ANSWER: This is an artifact of the algorithm to avoid aliasing. 11 // ANSWER: This is an artifact of the algorithm to avoid aliasing.
12 // 12 //
13 // QUESTION: Since the tests compare the actual result with an expected referenc e file, how are the 13 // QUESTION: Since the tests compare the actual result with an expected referenc e file, how are the
14 // reference files created? 14 // reference files created?
15 // ANSWER: Create an html with the following contents in the webaudio directory. Then run a layout 15 // ANSWER: Create an html with the following contents in the webaudio directory. Then run a layout
16 // test on this file. A new file names "<file>-actual.wav" is created that cont ains the new result 16 // test on this file. A new file names "<file>-actual.wav" is created that cont ains the new result
17 // that can be used as the new expected reference file. Replace the "sine" belo w with the 17 // that can be used as the new expected reference file. Replace the "sine" belo w with the
18 // oscillator type that you want to use. 18 // oscillator type that you want to use.
19 // 19 //
20 // <!doctype html> 20 // <!doctype html>
21 // <html> 21 // <html>
22 // <head> 22 // <head>
23 // <script src="resources/compatibility.js"></script> 23 // <script src="resources/compatibility.js"></script>
24 // <script src="resources/buffer-loader.js"></script> 24 // <script src="resources/buffer-loader.js"></script>
25 // <script src="../resources/js-test.js"></script> 25 // <script src="../resources/js-test.js"></script>
hongchan 2017/02/06 17:28:43 This comment might have to be updated.
Raymond Toy 2017/02/06 18:36:18 I'll have to retest. Other than the paths being wr
hongchan 2017/02/07 18:18:53 Does this work with 'js-test' at all? What I meant
Raymond Toy 2017/02/07 18:57:58 You mean this bit of commented-out code? It used t
26 // <script src="resources/oscillator-testing.js"></script> 26 // <script src="resources/oscillator-testing.js"></script>
27 // <script src="resources/audio-testing.js"></script> 27 // <script src="resources/audio-testing.js"></script>
28 // </head> 28 // </head>
29 // <body> 29 // <body>
30 // <script> 30 // <script>
31 // OscillatorTestingUtils.createNewReference("sine"); 31 // OscillatorTestingUtils.createNewReference("sine");
32 // </script> 32 // </script>
33 // </body> 33 // </body>
34 // </html> 34 // </html>
35 35
36 OscillatorTestingUtils = (function () { 36 OscillatorTestingUtils = (function () {
37 37
38 var audit = Audit.createTaskRunner();
hongchan 2017/02/06 17:28:43 Not really sure about this pattern. Audit should b
Raymond Toy 2017/02/06 18:36:18 Yeah, I debated on whether to bury everything here
Raymond Toy 2017/02/07 00:16:28 Done.
38 var sampleRate = 44100.0; 39 var sampleRate = 44100.0;
39 var nyquist = 0.5 * sampleRate; 40 var nyquist = 0.5 * sampleRate;
40 var lengthInSeconds = 4; 41 var lengthInSeconds = 4;
41 var lowFrequency = 10; 42 var lowFrequency = 10;
42 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s ure we generate silence there 43 var highFrequency = nyquist + 2000; // go slightly higher than nyquist to make s ure we generate silence there
43 var context = 0; 44 var context = 0;
44 45
45 // Scaling factor for converting the 16-bit WAV data to float (and vice-versa). 46 // Scaling factor for converting the 16-bit WAV data to float (and vice-versa).
46 var waveScaleFactor = 32768; 47 var waveScaleFactor = 32768;
47 48
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 } 103 }
103 104
104 function calculateSNR(sPower, nPower) 105 function calculateSNR(sPower, nPower)
105 { 106 {
106 if (nPower == 0 && sPower > 0) { 107 if (nPower == 0 && sPower > 0) {
107 return 1000; 108 return 1000;
108 } 109 }
109 return 10 * Math.log10(sPower / nPower); 110 return 10 * Math.log10(sPower / nPower);
110 } 111 }
111 112
112 function loadReferenceAndRunTest(oscType) { 113 function checkResult (renderedBuffer, should) {
113 var bufferLoader = new BufferLoader( 114 renderedData = renderedBuffer.getChannelData(0);
hongchan 2017/02/06 17:28:43 Why isn't this a local variable? Any reason being
Raymond Toy 2017/02/06 18:36:18 Probably to make debugging easier so that it could
hongchan 2017/02/07 18:18:53 I think it's easy to put 'let' at the beginning. N
Raymond Toy 2017/02/07 18:57:58 You mean make renderedData truly local to checkRes
114 context,
115 [ "../Oscillator/oscillator-" + oscType + "-expected.wav" ],
116 function (bufferList) {
117 reference = bufferList[0].getChannelData(0);
118 generateExponentialOscillatorSweep(context, oscType);
119 context.oncomplete = checkResult;
120 context.startRendering();
121 });
122
123 bufferLoader.load();
124 }
125
126 function checkResult (event) {
127 renderedData = event.renderedBuffer.getChannelData(0);
128 // Compute signal to noise ratio between the result and the reference. Also keep track 115 // Compute signal to noise ratio between the result and the reference. Also keep track
129 // of the max difference (and position). 116 // of the max difference (and position).
130 117
131 var maxError = -1; 118 var maxError = -1;
132 var errorPosition = -1; 119 var errorPosition = -1;
133 var diffCount = 0; 120 var diffCount = 0;
134 121
135 for (var k = 0; k < renderedData.length; ++k) { 122 for (var k = 0; k < renderedData.length; ++k) {
136 var diff = renderedData[k] - reference[k]; 123 var diff = renderedData[k] - reference[k];
137 noisePower += diff * diff; 124 noisePower += diff * diff;
138 signalPower += reference[k] * reference[k]; 125 signalPower += reference[k] * reference[k];
139 if (Math.abs(diff) > maxError) { 126 if (Math.abs(diff) > maxError) {
140 maxError = Math.abs(diff); 127 maxError = Math.abs(diff);
141 errorPosition = k; 128 errorPosition = k;
142 } 129 }
143 // The reference file is a 16-bit WAV file, so we will almost never get an exact match 130 // The reference file is a 16-bit WAV file, so we will almost never get an exact match
144 // between it and the actual floating-point result. 131 // between it and the actual floating-point result.
145 if (diff > 1/waveScaleFactor) { 132 if (diff > 1/waveScaleFactor) {
146 diffCount++; 133 diffCount++;
147 } 134 }
148 } 135 }
149 136
150 var snr = calculateSNR(signalPower, noisePower); 137 var snr = calculateSNR(signalPower, noisePower);
151 if (snr >= thresholdSNR) { 138 should(snr, "SNR")
152 testPassed("Exceeded SNR threshold of " + thresholdSNR + " dB"); 139 .beGreaterThanOrEqualTo(thresholdSNR);
153 } else { 140 should(maxError * waveScaleFactor, "Maximum difference in ulp (16-bits)")
154 testFailed("Expected SNR of " + thresholdSNR + " dB, but actual SNR is " + snr + " dB"); 141 .beLessThanOrEqualTo(thresholdDiff * waveScaleFactor);
155 }
156 142
157 if (maxError <= thresholdDiff) { 143 should(diffCount,
158 testPassed("Maximum difference below threshold of " 144 "Number of differences between actual and expected result out of "
159 + (thresholdDiff * waveScaleFactor) + " ulp (16-bits)"); 145 + renderedData.length + " frames")
160 } else { 146 .beLessThanOrEqualTo(thresholdDiffCount);
161 testFailed("Maximum difference of " + (maxError * waveScaleFactor) + " a t "
162 + errorPosition + " exceeded threshold of " + (thresholdDiff * waveScaleFactor)
163 + " ulp (16-bits)");
164 }
165
166 if (diffCount <= thresholdDiffCount) {
167 testPassed("Number of differences between actual and expected result is less than " + thresholdDiffCount
168 + " out of " + renderedData.length);
169 } else {
170 testFailed(diffCount + " differences found but expected no more than " + thresholdDiffCount
171 + " out of " + renderedData.length);
172 }
173
174 finishJSTest();
175 } 147 }
176 148
177 function setThresholds(thresholds) { 149 function setThresholds(thresholds) {
178 thresholdSNR = thresholds.snr; 150 thresholdSNR = thresholds.snr;
179 thresholdDiff = thresholds.maxDiff / waveScaleFactor; 151 thresholdDiff = thresholds.maxDiff / waveScaleFactor;
180 thresholdDiffCount = thresholds.diffCount; 152 thresholdDiffCount = thresholds.diffCount;
181 } 153 }
182 154
183 function runTest(oscType) { 155 function runTest(oscType, description) {
184 window.jsTestIsAsync = true; 156 audit.define("load-ref", function (task, should) {
185 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRat e); 157 task.describe("Load reference file");
186 loadReferenceAndRunTest(oscType); 158 context = new OfflineAudioContext(1, sampleRate *
159 lengthInSeconds, sampleRate);
160 var bufferLoader = new BufferLoader(
161 context, ["../Oscillator/oscillator-" + oscType +
162 "-expected.wav"
163 ],
164 function (bufferList) {
165 reference = bufferList[0].getChannelData(0);
166 task.done();
167 });
168
169 bufferLoader.load();
170 });
171
172 audit.define("test", function (task, should) {
173 task.describe(description);
174 generateExponentialOscillatorSweep(context, oscType);
175 context.startRendering()
176 .then(buffer => checkResult(buffer, should))
177 .then(task.done.bind(task));;
178 });
179
180 audit.run();
187 } 181 }
188 182
189 function createNewReference(oscType) { 183 function createNewReference(oscType) {
190 if (!window.testRunner) 184 if (!window.testRunner)
191 return; 185 return;
192 186
193 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRa te); 187 context = new OfflineAudioContext(1, sampleRate * lengthInSeconds, sampleRa te);
194 generateExponentialOscillatorSweep(context, oscType); 188 generateExponentialOscillatorSweep(context, oscType);
195 189
196 context.oncomplete = finishAudioTest; 190 context.oncomplete = finishAudioTest;
197 context.startRendering(); 191 context.startRendering();
198 192
199 testRunner.waitUntilDone(); 193 testRunner.waitUntilDone();
200 } 194 }
201 195
202 return { 196 return {
203 sampleRate: sampleRate, 197 sampleRate: sampleRate,
204 lengthInSeconds: lengthInSeconds, 198 lengthInSeconds: lengthInSeconds,
205 thresholdSNR: thresholdSNR, 199 thresholdSNR: thresholdSNR,
206 thresholdDiff: thresholdDiff, 200 thresholdDiff: thresholdDiff,
207 thresholdDiffCount: thresholdDiffCount, 201 thresholdDiffCount: thresholdDiffCount,
208 waveScaleFactor: waveScaleFactor, 202 waveScaleFactor: waveScaleFactor,
209 setThresholds: setThresholds, 203 setThresholds: setThresholds,
210 loadReferenceAndRunTest: loadReferenceAndRunTest,
211 runTest: runTest, 204 runTest: runTest,
212 createNewReference: createNewReference, 205 createNewReference: createNewReference,
213 }; 206 };
214 207
215 }()); 208 }());
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/webaudio/PeriodicWave/periodicwave-contexts-expected.txt ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698