Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 // Helpers for Web Audio tests
3 function expectException(func, exceptionCode) {
4 var threw = false;
5 try {
6 func();
7 } catch (ex) {
8 threw = true;
9 ok(ex instanceof DOMException, "Expect a DOM exception");
10 is(ex.code, exceptionCode, "Expect the correct exception code");
11 }
12 ok(threw, "The exception was thrown");
13 }
15 function expectNoException(func) {
16 var threw = false;
17 try {
18 func();
19 } catch (ex) {
20 threw = true;
21 }
22 ok(!threw, "An exception was not thrown");
23 }
25 function expectTypeError(func) {
26 var threw = false;
27 try {
28 func();
29 } catch (ex) {
30 threw = true;
31 ok(ex instanceof TypeError, "Expect a TypeError");
32 }
33 ok(threw, "The exception was thrown");
34 }
36 function fuzzyCompare(a, b) {
37 return Math.abs(a - b) < 9e-3;
38 }
40 function compareChannels(buf1, buf2,
41 /*optional*/ length,
42 /*optional*/ sourceOffset,
43 /*optional*/ destOffset,
44 /*optional*/ skipLengthCheck) {
45 if (!skipLengthCheck) {
46 is(buf1.length, buf2.length, "Channels must have the same length");
47 }
48 sourceOffset = sourceOffset || 0;
49 destOffset = destOffset || 0;
50 if (length == undefined) {
51 length = buf1.length - sourceOffset;
52 }
53 var difference = 0;
54 var maxDifference = 0;
55 var firstBadIndex = -1;
56 for (var i = 0; i < length; ++i) {
57 if (!fuzzyCompare(buf1[i + sourceOffset], buf2[i + destOffset])) {
58 difference++;
59 maxDifference = Math.max(maxDifference, Math.abs(buf1[i + sourceOffset] - buf2[i + destOffset]));
60 if (firstBadIndex == -1) {
61 firstBadIndex = i;
62 }
63 }
64 };
66 is(difference, 0, "maxDifference: " + maxDifference +
67 ", first bad index: " + firstBadIndex +
68 " with test-data offset " + sourceOffset + " and expected-data offset " +
69 destOffset + "; corresponding values " + buf1[firstBadIndex + sourceOffset] +
70 " and " + buf2[firstBadIndex + destOffset] + " --- differences");
71 }
73 function compareBuffers(got, expected) {
74 if (got.numberOfChannels != expected.numberOfChannels) {
75 is(got.numberOfChannels, expected.numberOfChannels,
76 "Correct number of buffer channels");
77 return;
78 }
79 if (got.length != expected.length) {
80 is(got.length, expected.length,
81 "Correct buffer length");
82 return;
83 }
84 if (got.sampleRate != expected.sampleRate) {
85 is(got.sampleRate, expected.sampleRate,
86 "Correct sample rate");
87 return;
88 }
90 for (var i = 0; i < got.numberOfChannels; ++i) {
91 compareChannels(got.getChannelData(i), expected.getChannelData(i),
92 got.length, 0, 0, true);
93 }
94 }
96 function getEmptyBuffer(context, length) {
97 return context.createBuffer(gTest.numberOfChannels, length, context.sampleRate);
98 }
100 /**
101 * This function assumes that the test file defines a single gTest variable with
102 * the following properties and methods:
103 *
104 * + numberOfChannels: optional property which specifies the number of channels
105 * in the output. The default value is 2.
106 * + createGraph: mandatory method which takes a context object and does
107 * everything needed in order to set up the Web Audio graph.
108 * This function returns the node to be inspected.
109 * + createGraphAsync: async version of createGraph. This function takes
110 * a callback which should be called with an argument
111 * set to the node to be inspected when the callee is
112 * ready to proceed with the test. Either this function
113 * or createGraph must be provided.
114 * + createExpectedBuffers: optional method which takes a context object and
115 * returns either one expected buffer or an array of
116 * them, designating what is expected to be observed
117 * in the output. If omitted, the output is expected
118 * to be silence. All buffers must have the same
119 * length, which must be a bufferSize supported by
120 * ScriptProcessorNode. This function is guaranteed
121 * to be called before createGraph.
122 * + length: property equal to the total number of frames which we are waiting
123 * to see in the output, mandatory if createExpectedBuffers is not
124 * provided, in which case it must be a bufferSize supported by
125 * ScriptProcessorNode (256, 512, 1024, 2048, 4096, 8192, or 16384).
126 * If createExpectedBuffers is provided then this must be equal to
127 * the number of expected buffers * the expected buffer length.
128 *
129 * + skipOfflineContextTests: optional. when true, skips running tests on an offline
130 * context by circumventing testOnOfflineContext.
131 */
132 function runTest()
133 {
134 function done() {
135 SimpleTest.finish();
136 }
138 SimpleTest.waitForExplicitFinish();
139 function runTestFunction () {
140 if (!gTest.numberOfChannels) {
141 gTest.numberOfChannels = 2; // default
142 }
144 var testLength;
146 function runTestOnContext(context, callback, testOutput) {
147 if (!gTest.createExpectedBuffers) {
148 // Assume that the output is silence
149 var expectedBuffers = getEmptyBuffer(context, gTest.length);
150 } else {
151 var expectedBuffers = gTest.createExpectedBuffers(context);
152 }
153 if (!(expectedBuffers instanceof Array)) {
154 expectedBuffers = [expectedBuffers];
155 }
156 var expectedFrames = 0;
157 for (var i = 0; i < expectedBuffers.length; ++i) {
158 is(expectedBuffers[i].numberOfChannels, gTest.numberOfChannels,
159 "Correct number of channels for expected buffer " + i);
160 expectedFrames += expectedBuffers[i].length;
161 }
162 if (gTest.length && gTest.createExpectedBuffers) {
163 is(expectedFrames, gTest.length, "Correct number of expected frames");
164 }
166 if (gTest.createGraphAsync) {
167 gTest.createGraphAsync(context, function(nodeToInspect) {
168 testOutput(nodeToInspect, expectedBuffers, callback);
169 });
170 } else {
171 testOutput(gTest.createGraph(context), expectedBuffers, callback);
172 }
173 }
175 function testOnNormalContext(callback) {
176 function testOutput(nodeToInspect, expectedBuffers, callback) {
177 testLength = 0;
178 var sp = context.createScriptProcessor(expectedBuffers[0].length, gTest.numberOfChannels);
179 nodeToInspect.connect(sp);
180 sp.connect(context.destination);
181 sp.onaudioprocess = function(e) {
182 var expectedBuffer = expectedBuffers.shift();
183 testLength += expectedBuffer.length;
184 compareBuffers(e.inputBuffer, expectedBuffer);
185 if (expectedBuffers.length == 0) {
186 sp.onaudioprocess = null;
187 callback();
188 }
189 };
190 }
191 var context = new AudioContext();
192 runTestOnContext(context, callback, testOutput);
193 }
195 function testOnOfflineContext(callback, sampleRate) {
196 function testOutput(nodeToInspect, expectedBuffers, callback) {
197 nodeToInspect.connect(context.destination);
198 context.oncomplete = function(e) {
199 var samplesSeen = 0;
200 while (expectedBuffers.length) {
201 var expectedBuffer = expectedBuffers.shift();
202 is(e.renderedBuffer.numberOfChannels, expectedBuffer.numberOfChannels,
203 "Correct number of input buffer channels");
204 for (var i = 0; i < e.renderedBuffer.numberOfChannels; ++i) {
205 compareChannels(e.renderedBuffer.getChannelData(i),
206 expectedBuffer.getChannelData(i),
207 expectedBuffer.length,
208 samplesSeen,
209 undefined,
210 true);
211 }
212 samplesSeen += expectedBuffer.length;
213 }
214 callback();
215 };
216 context.startRendering();
217 }
219 var context = new OfflineAudioContext(gTest.numberOfChannels, testLength, sampleRate);
220 runTestOnContext(context, callback, testOutput);
221 }
223 testOnNormalContext(function() {
224 if (!gTest.skipOfflineContextTests) {
225 testOnOfflineContext(function() {
226 testOnOfflineContext(done, 44100);
227 }, 48000);
228 } else {
229 done();
230 }
231 });
232 };
234 if (document.readyState !== 'complete') {
235 addLoadEvent(runTestFunction);
236 } else {
237 runTestFunction();
238 }
239 }