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

Side by Side Diff: third_party/WebKit/LayoutTests/webaudio/biquad-automation.html

Issue 2033503004: Avoid slow AudioParam automation path when possible (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address review comments Created 4 years, 6 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 | « no previous file | third_party/WebKit/LayoutTests/webaudio/biquad-automation-expected.txt » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 <!doctype html> 1 <!doctype html>
2 <html> 2 <html>
3 <head> 3 <head>
4 <title>Biquad Automation Test</title> 4 <title>Biquad Automation Test</title>
5 <script src="../resources/js-test.js"></script> 5 <script src="../resources/js-test.js"></script>
6 <script src="resources/compatibility.js"></script> 6 <script src="resources/compatibility.js"></script>
7 <script src="resources/audio-testing.js"></script> 7 <script src="resources/audio-testing.js"></script>
8 <script src="resources/biquad-filters.js"></script> 8 <script src="resources/biquad-filters.js"></script>
9 <script src="resources/audioparam-testing.js"></script> 9 <script src="resources/audioparam-testing.js"></script>
10 </head> 10 </head>
11 <body> 11 <body>
12 <script> 12 <script>
13 description("Test Automation of Biquad Filters"); 13 description("Test Automation of Biquad Filters");
14 14
15 window.jsTestIsAsync = true; 15 window.jsTestIsAsync = true;
16 16
17 // Don't need to run these tests at high sampling rate, so just use a low one to reduce memory 17 // Don't need to run these tests at high sampling rate, so just use a low one to reduce memory
18 // usage and complexity. 18 // usage and complexity.
19 var sampleRate = 16000; 19 var sampleRate = 16000;
20 20
21 // How long to render for each test. 21 // How long to render for each test.
22 var renderDuration = 1; 22 var renderDuration = 1;
23 // Where to end the automations. Fairly arbitrary, but must end before
24 // the renderDuration.
25 var automationEndTime = renderDuration / 2;
23 26
24 var audit = Audit.createTaskRunner(); 27 var audit = Audit.createTaskRunner();
25 28
26 // The definition of the linear ramp automation function. 29 // The definition of the linear ramp automation function.
27 function linearRamp(t, v0, v1, t0, t1) { 30 function linearRamp(t, v0, v1, t0, t1) {
28 return v0 + (v1 - v0) * (t - t0) / (t1 - t0); 31 return v0 + (v1 - v0) * (t - t0) / (t1 - t0);
29 } 32 }
30 33
31 // Generate the filter coefficients for the specified filter using the giv en parameters for 34 // Generate the filter coefficients for the specified filter using the giv en parameters for
32 // the given duration. |filterTypeFunction| is a function that returns th e filter 35 // the given duration. |filterTypeFunction| is a function that returns th e filter
33 // coefficients for one set of parameters. |parameters| is a property bag that contains the 36 // coefficients for one set of parameters. |parameters| is a property bag that contains the
34 // start and end values (as an array) for each of the biquad attributes. The properties are 37 // start and end values (as an array) for each of the biquad attributes. The properties are
35 // |freq|, |Q|, |gain|, and |detune|. |duration| is the number of seconds for which the 38 // |freq|, |Q|, |gain|, and |detune|. |duration| is the number of seconds for which the
36 // coefficients are generated. 39 // coefficients are generated.
37 // 40 //
38 // A property bag with properties |b0|, |b1|, |b2|, |a1|, |a2|. Each prop ery is an array 41 // A property bag with properties |b0|, |b1|, |b2|, |a1|, |a2|. Each prop ery is an array
39 // consisting of the coefficients for the time-varying biquad filter. 42 // consisting of the coefficients for the time-varying biquad filter.
40 function generateFilterCoefficients(filterTypeFunction, parameters, durati on) { 43 function generateFilterCoefficients(filterTypeFunction, parameters, durati on) {
44 var renderEndFrame = Math.ceil(renderDuration * sampleRate);
41 var endFrame = Math.ceil(duration * sampleRate); 45 var endFrame = Math.ceil(duration * sampleRate);
42 var nCoef = endFrame; 46 var nCoef = renderEndFrame;
43 var b0 = new Float64Array(nCoef); 47 var b0 = new Float64Array(nCoef);
44 var b1 = new Float64Array(nCoef); 48 var b1 = new Float64Array(nCoef);
45 var b2 = new Float64Array(nCoef); 49 var b2 = new Float64Array(nCoef);
46 var a1 = new Float64Array(nCoef); 50 var a1 = new Float64Array(nCoef);
47 var a2 = new Float64Array(nCoef); 51 var a2 = new Float64Array(nCoef);
48 52
49 var k = 0; 53 var k = 0;
50 // If the property is not given, use the defaults. 54 // If the property is not given, use the defaults.
51 var freqs = parameters.freq || [350, 350]; 55 var freqs = parameters.freq || [350, 350];
52 var qs = parameters.Q || [1, 1]; 56 var qs = parameters.Q || [1, 1];
53 var gains = parameters.gain || [0, 0]; 57 var gains = parameters.gain || [0, 0];
54 var detunes = parameters.detune || [0, 0]; 58 var detunes = parameters.detune || [0, 0];
55 59
56 for (var frame = 0; frame < endFrame; ++frame) { 60 for (var frame = 0; frame <= endFrame; ++frame) {
57 // Apply linear ramp at frame |frame|. 61 // Apply linear ramp at frame |frame|.
58 var f = linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, durati on); 62 var f = linearRamp(frame / sampleRate, freqs[0], freqs[1], 0, durati on);
59 var q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration); 63 var q = linearRamp(frame / sampleRate, qs[0], qs[1], 0, duration);
60 var g = linearRamp(frame / sampleRate, gains[0], gains[1], 0, durati on); 64 var g = linearRamp(frame / sampleRate, gains[0], gains[1], 0, durati on);
61 var d = linearRamp(frame / sampleRate, detunes[0], detunes[1], 0, du ration); 65 var d = linearRamp(frame / sampleRate, detunes[0], detunes[1], 0, du ration);
62 66
63 // Compute actual frequency parameter 67 // Compute actual frequency parameter
64 f = f * Math.pow(2, d / 1200); 68 f = f * Math.pow(2, d / 1200);
65 69
66 // Compute filter coefficients 70 // Compute filter coefficients
67 var coef = filterTypeFunction(f / (sampleRate / 2), q, g); 71 var coef = filterTypeFunction(f / (sampleRate / 2), q, g);
68 b0[k] = coef.b0; 72 b0[k] = coef.b0;
69 b1[k] = coef.b1; 73 b1[k] = coef.b1;
70 b2[k] = coef.b2; 74 b2[k] = coef.b2;
71 a1[k] = coef.a1; 75 a1[k] = coef.a1;
72 a2[k] = coef.a2; 76 a2[k] = coef.a2;
73 ++k; 77 ++k;
74 } 78 }
75 79
80 // Fill the rest of the arrays with the constant value to the end of
81 // the rendering duration.
82 b0.fill(b0[endFrame], endFrame + 1);
83 b1.fill(b1[endFrame], endFrame + 1);
84 b2.fill(b2[endFrame], endFrame + 1);
85 a1.fill(a1[endFrame], endFrame + 1);
86 a2.fill(a2[endFrame], endFrame + 1);
87
76 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}; 88 return {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2};
77 } 89 }
78 90
79 // Apply the given time-varying biquad filter to the given signal, |signal |. |coef| should be 91 // Apply the given time-varying biquad filter to the given signal, |signal |. |coef| should be
80 // the time-varying coefficients of the filter, as returned by |generateFi lterCoefficients|. 92 // the time-varying coefficients of the filter, as returned by |generateFi lterCoefficients|.
81 function timeVaryingFilter(signal, coef) { 93 function timeVaryingFilter(signal, coef) {
82 var length = signal.length; 94 var length = signal.length;
83 // Use double precision for the internal computations. 95 // Use double precision for the internal computations.
84 var y = new Float64Array(length); 96 var y = new Float64Array(length);
85 97
(...skipping 27 matching lines...) Expand all
113 f.connect(context.destination); 125 f.connect(context.destination);
114 126
115 src.start(); 127 src.start();
116 128
117 return {filter: f, source: b}; 129 return {filter: f, source: b};
118 } 130 }
119 131
120 function createFilterVerifier(filterCreator, threshold, parameters, input, message) { 132 function createFilterVerifier(filterCreator, threshold, parameters, input, message) {
121 return function (resultBuffer) { 133 return function (resultBuffer) {
122 var actual = resultBuffer.getChannelData(0); 134 var actual = resultBuffer.getChannelData(0);
123 var coefs = generateFilterCoefficients(filterCreator, parameters, rend erDuration); 135 var coefs = generateFilterCoefficients(filterCreator, parameters, auto mationEndTime);
124 136
125 reference = timeVaryingFilter(input, coefs); 137 reference = timeVaryingFilter(input, coefs);
126 138
127 Should(message, actual).beCloseToArray(reference, threshold); 139 Should(message, actual, {
140 verbose: true
141 }).beCloseToArray(reference, threshold);
128 }; 142 };
129 } 143 }
130 144
131 // Automate just the frequency parameter. A bandpass filter is used where the center 145 // Automate just the frequency parameter. A bandpass filter is used where the center
132 // frequency is swept across the source (which is a simple tone). 146 // frequency is swept across the source (which is a simple tone).
133 audit.defineTask("automate-freq", function (done) { 147 audit.defineTask("automate-freq", function (done) {
134 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 148 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate);
135 149
136 // Center frequency of bandpass filter and also the frequency of the tes t tone. 150 // Center frequency of bandpass filter and also the frequency of the tes t tone.
137 var centerFreq = 10*440; 151 var centerFreq = 10*440;
138 152
139 // Sweep the frequency +/- 9*440 Hz from the center. This should cause the output to low at 153 // Sweep the frequency +/- 5*440 Hz from the center. This should cause
140 // the beginning and end of the test where the done is outside the pass band of the filter, 154 // the output to be low at the beginning and end of the test where the
141 // but high in the center where the tone is near the center of the pass band. 155 // tone is outside the pass band of the filter, but high in the middle
156 // of the automation time where the tone is near the center of the pass
157 // band. Make sure the frequency sweep stays inside the Nyquist
158 // frequency.
142 var parameters = { 159 var parameters = {
143 freq: [centerFreq - 9*440, centerFreq + 9*440] 160 freq: [centerFreq - 5*440, centerFreq + 5*440]
144 } 161 }
145 var graph = configureGraph(context, centerFreq); 162 var graph = configureGraph(context, centerFreq);
146 var f = graph.filter; 163 var f = graph.filter;
147 var b = graph.source; 164 var b = graph.source;
148 165
149 f.type = "bandpass"; 166 f.type = "bandpass";
150 f.frequency.setValueAtTime(parameters.freq[0], 0); 167 f.frequency.setValueAtTime(parameters.freq[0], 0);
151 f.frequency.linearRampToValueAtTime(parameters.freq[1], renderDuration); 168 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim e);
152 169
153 context.startRendering() 170 context.startRendering()
154 .then(createFilterVerifier(createBandpassFilter, 5e-5, parameters, b.g etChannelData(0), 171 .then(createFilterVerifier(createBandpassFilter, 4.8429e-6, parameters , b.getChannelData(0),
155 "Output of bandpass filter with frequency automation")) 172 "Output of bandpass filter with frequency automation"))
156 .then(done); 173 .then(done);
157 }); 174 });
158 175
159 // Automate just the Q parameter. A bandpass filter is used where the Q o f the filter is 176 // Automate just the Q parameter. A bandpass filter is used where the Q o f the filter is
160 // swept. 177 // swept.
161 audit.defineTask("automate-q", function (done) { 178 audit.defineTask("automate-q", function (done) {
162 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 179 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate);
163 180
164 // The frequency of the test tone. 181 // The frequency of the test tone.
165 var centerFreq = 440; 182 var centerFreq = 440;
166 183
167 // Sweep the Q paramter between 1 and 200. This will cause the output o f the filter to pass 184 // Sweep the Q paramter between 1 and 200. This will cause the output o f the filter to pass
168 // most of the tone at the beginning to passing less of the tone at the end. This is 185 // most of the tone at the beginning to passing less of the tone at the end. This is
169 // because we set center frequency of the bandpass filter to be slightly off from the actual 186 // because we set center frequency of the bandpass filter to be slightly off from the actual
170 // tone. 187 // tone.
171 var parameters = { 188 var parameters = {
172 Q: [1, 200], 189 Q: [1, 200],
173 // Center frequency of the bandpass filter is just 25 Hz above the ton e frequency. 190 // Center frequency of the bandpass filter is just 25 Hz above the ton e frequency.
174 freq: [centerFreq + 25, centerFreq + 25] 191 freq: [centerFreq + 25, centerFreq + 25]
175 }; 192 };
176 var graph = configureGraph(context, centerFreq); 193 var graph = configureGraph(context, centerFreq);
177 var f = graph.filter; 194 var f = graph.filter;
178 var b = graph.source; 195 var b = graph.source;
179 196
180 f.type = "bandpass"; 197 f.type = "bandpass";
181 f.frequency.value = parameters.freq[0]; 198 f.frequency.value = parameters.freq[0];
182 f.Q.setValueAtTime(parameters.Q[0], 0); 199 f.Q.setValueAtTime(parameters.Q[0], 0);
183 f.Q.linearRampToValueAtTime(parameters.Q[1], renderDuration); 200 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime);
184 201
185 context.startRendering() 202 context.startRendering()
186 .then(createFilterVerifier(createBandpassFilter, 1.4e-6, parameters, b .getChannelData(0), 203 .then(createFilterVerifier(createBandpassFilter, 1.1062e-6, parameters , b.getChannelData(0),
187 "Output of bandpass filter with Q automation")) 204 "Output of bandpass filter with Q automation"))
188 .then(done); 205 .then(done);
189 }); 206 });
190 207
191 // Automate just the gain of the lowshelf filter. A test tone will be in the lowshelf part of 208 // Automate just the gain of the lowshelf filter. A test tone will be in the lowshelf part of
192 // the filter. The output will vary as the gain of the lowshelf is change d. 209 // the filter. The output will vary as the gain of the lowshelf is change d.
193 audit.defineTask("automate-gain", function (done) { 210 audit.defineTask("automate-gain", function (done) {
194 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 211 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate);
195 212
196 // Frequency of the test tone. 213 // Frequency of the test tone.
197 var centerFreq = 440; 214 var centerFreq = 440;
198 215
199 // Set the cutoff frequency of the lowshelf to be significantly higher t han the test tone. 216 // Set the cutoff frequency of the lowshelf to be significantly higher t han the test tone.
200 // Sweep the gain from 20 dB to -20 dB. (We go from 20 to -20 to easily verify that the 217 // Sweep the gain from 20 dB to -20 dB. (We go from 20 to -20 to easily verify that the
201 // filter didn't go unstable.) 218 // filter didn't go unstable.)
202 var parameters = { 219 var parameters = {
203 freq: [3500, 3500], 220 freq: [3500, 3500],
204 gain: [20, -20] 221 gain: [20, -20]
205 } 222 }
206 var graph = configureGraph(context, centerFreq); 223 var graph = configureGraph(context, centerFreq);
207 var f = graph.filter; 224 var f = graph.filter;
208 var b = graph.source; 225 var b = graph.source;
209 226
210 f.type = "lowshelf"; 227 f.type = "lowshelf";
211 f.frequency.value = parameters.freq[0]; 228 f.frequency.value = parameters.freq[0];
212 f.gain.setValueAtTime(parameters.gain[0], 0); 229 f.gain.setValueAtTime(parameters.gain[0], 0);
213 f.gain.linearRampToValueAtTime(parameters.gain[1], renderDuration); 230 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime);
214 231
215 context.startRendering() 232 context.startRendering()
216 .then(createFilterVerifier(createLowShelfFilter, 8e-6, parameters, b.g etChannelData(0), 233 .then(createFilterVerifier(createLowShelfFilter, 1.4306e-5, parameters , b.getChannelData(0),
217 "Output of lowshelf filter with gain automation")) 234 "Output of lowshelf filter with gain automation"))
218 .then(done); 235 .then(done);
219 }); 236 });
220 237
221 // Automate just the detune parameter. Basically the same test as for the frequncy parameter 238 // Automate just the detune parameter. Basically the same test as for the frequncy parameter
222 // but we just use the detune parameter to modulate the frequency paramete r. 239 // but we just use the detune parameter to modulate the frequency paramete r.
223 audit.defineTask("automate-detune", function (done) { 240 audit.defineTask("automate-detune", function (done) {
224 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 241 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate);
225 var centerFreq = 10*440; 242 var centerFreq = 10*440;
226 var parameters = { 243 var parameters = {
227 freq: [centerFreq, centerFreq], 244 freq: [centerFreq, centerFreq],
228 detune: [-10*1200, 10*1200] 245 detune: [-10*1200, 10*1200]
229 }; 246 };
230 var graph = configureGraph(context, centerFreq); 247 var graph = configureGraph(context, centerFreq);
231 var f = graph.filter; 248 var f = graph.filter;
232 var b = graph.source; 249 var b = graph.source;
233 250
234 f.type = "bandpass"; 251 f.type = "bandpass";
235 f.frequency.value = parameters.freq[0]; 252 f.frequency.value = parameters.freq[0];
236 f.detune.setValueAtTime(parameters.detune[0], 0); 253 f.detune.setValueAtTime(parameters.detune[0], 0);
237 f.detune.linearRampToValueAtTime(parameters.detune[1], renderDuration); 254 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime );
238 255
239 context.startRendering() 256 context.startRendering()
240 .then(createFilterVerifier(createBandpassFilter, 5e-6, parameters, b.g etChannelData(0), 257 .then(createFilterVerifier(createBandpassFilter, 2.9535e-5, parameters , b.getChannelData(0),
241 "Output of bandpass filter with detune automation")) 258 "Output of bandpass filter with detune automation"))
242 .then(done); 259 .then(done);
243 }); 260 });
244 261
245 // Automate all of the filter parameters at once. This is a basic check t hat everything is 262 // Automate all of the filter parameters at once. This is a basic check t hat everything is
246 // working. A peaking filter is used because it uses all of the parameter s. 263 // working. A peaking filter is used because it uses all of the parameter s.
247 audit.defineTask("automate-all", function (done) { 264 audit.defineTask("automate-all", function (done) {
248 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate); 265 var context = new OfflineAudioContext(1, renderDuration * sampleRate, sa mpleRate);
249 var graph = configureGraph(context, 10*440); 266 var graph = configureGraph(context, 10*440);
250 var f = graph.filter; 267 var f = graph.filter;
251 var b = graph.source; 268 var b = graph.source;
252 269
253 // Sweep all of the filter parameters. These are pretty much arbitrary. 270 // Sweep all of the filter parameters. These are pretty much arbitrary.
254 var parameters = { 271 var parameters = {
255 freq: [10000, 100], 272 freq: [8000, 100],
256 Q: [f.Q.value, .0001], 273 Q: [f.Q.value, .0001],
257 gain: [f.gain.value, 20], 274 gain: [f.gain.value, 20],
258 detune: [2400, -2400] 275 detune: [2400, -2400]
259 }; 276 };
260 277
261 f.type = "peaking"; 278 f.type = "peaking";
262 // Set starting points for all parameters of the filter. Start at 10 kH z for the center 279 // Set starting points for all parameters of the filter. Start at 10 kH z for the center
263 // frequency, and the defaults for Q and gain. 280 // frequency, and the defaults for Q and gain.
264 f.frequency.setValueAtTime(parameters.freq[0], 0); 281 f.frequency.setValueAtTime(parameters.freq[0], 0);
265 f.Q.setValueAtTime(parameters.Q[0], 0); 282 f.Q.setValueAtTime(parameters.Q[0], 0);
266 f.gain.setValueAtTime(parameters.gain[0], 0); 283 f.gain.setValueAtTime(parameters.gain[0], 0);
267 f.detune.setValueAtTime(parameters.detune[0], 0); 284 f.detune.setValueAtTime(parameters.detune[0], 0);
268 285
269 // Linear ramp each parameter 286 // Linear ramp each parameter
270 f.frequency.linearRampToValueAtTime(parameters.freq[1], renderDuration); 287 f.frequency.linearRampToValueAtTime(parameters.freq[1], automationEndTim e);
271 f.Q.linearRampToValueAtTime(parameters.Q[1], renderDuration); 288 f.Q.linearRampToValueAtTime(parameters.Q[1], automationEndTime);
272 f.gain.linearRampToValueAtTime(parameters.gain[1], renderDuration); 289 f.gain.linearRampToValueAtTime(parameters.gain[1], automationEndTime);
273 f.detune.linearRampToValueAtTime(parameters.detune[1], renderDuration); 290 f.detune.linearRampToValueAtTime(parameters.detune[1], automationEndTime );
274 291
275 context.startRendering() 292 context.startRendering()
276 .then(createFilterVerifier(createPeakingFilter, 3.3e-4, parameters, b. getChannelData(0), 293 .then(createFilterVerifier(createPeakingFilter, 3.1233e-4, parameters, b.getChannelData(0),
277 "Output of peaking filter with automation of all parameters")) 294 "Output of peaking filter with automation of all parameters"))
278 .then(done); 295 .then(done);
279 }); 296 });
280 297
281 // Test that modulation of the frequency parameter of the filter works. A sinusoid of 440 Hz 298 // Test that modulation of the frequency parameter of the filter works. A sinusoid of 440 Hz
282 // is the test signal that is applied to a bandpass biquad filter. The fr equency parameter of 299 // is the test signal that is applied to a bandpass biquad filter. The fr equency parameter of
283 // the filter is modulated by a sinusoid at 103 Hz, and the frequency modu lation varies from 300 // the filter is modulated by a sinusoid at 103 Hz, and the frequency modu lation varies from
284 // 116 to 412 Hz. (This test was taken from the description in 301 // 116 to 412 Hz. (This test was taken from the description in
285 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731 355) 302 // https://github.com/WebAudio/web-audio-api/issues/509#issuecomment-94731 355)
286 audit.defineTask("modulation", function (done) { 303 audit.defineTask("modulation", function (done) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 b1[k] = c.b1; 349 b1[k] = c.b1;
333 b2[k] = c.b2; 350 b2[k] = c.b2;
334 a1[k] = c.a1; 351 a1[k] = c.a1;
335 a2[k] = c.a2; 352 a2[k] = c.a2;
336 } 353 }
337 reference = timeVaryingFilter(b.getChannelData(0), 354 reference = timeVaryingFilter(b.getChannelData(0),
338 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2}); 355 {b0: b0, b1: b1, b2: b2, a1: a1, a2: a2});
339 356
340 Should("Output of bandpass filter with sinusoidal modulation of ban dpass center frequency", 357 Should("Output of bandpass filter with sinusoidal modulation of ban dpass center frequency",
341 actual) 358 actual)
342 .beCloseToArray(reference, 4e-6); 359 .beCloseToArray(reference, 3.9787e-5);
343 }) 360 })
344 .then(done); 361 .then(done);
345 }); 362 });
346 363
347 // All done! 364 // All done!
348 audit.defineTask("finish", function (done) { 365 audit.defineTask("finish", function (done) {
349 finishJSTest(); 366 finishJSTest();
350 done(); 367 done();
351 }); 368 });
352 369
353 audit.runTasks(); 370 audit.runTasks();
354 </script> 371 </script>
355 </body> 372 </body>
356 </html> 373 </html>
OLDNEW
« no previous file with comments | « no previous file | third_party/WebKit/LayoutTests/webaudio/biquad-automation-expected.txt » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698