OLD | NEW |
| (Empty) |
1 <!doctype html> | |
2 <html> | |
3 <head> | |
4 <script src="../resources/js-test.js"></script> | |
5 <script src="resources/compatibility.js"></script> | |
6 <script src="resources/audit-util.js"></script> | |
7 <script src="resources/audio-testing.js"></script> | |
8 <script src="resources/audio-param.js"></script> | |
9 <title>Updating of Value Attribute from Timeline</title> | |
10 </head> | |
11 | |
12 <body> | |
13 <script> | |
14 description("Test Updating of Value Attribute from Timeline"); | |
15 window.jsTestIsAsync = true; | |
16 | |
17 // This should be a power of two so that all time computations have no rou
nd-off errors. | |
18 var sampleRate = 32768; | |
19 var renderQuantumSize = 128; | |
20 // How many tests to run. | |
21 var renderLoops = 20; | |
22 var renderFrames = renderLoops * renderQuantumSize; | |
23 var renderDuration = renderFrames / sampleRate; | |
24 | |
25 var audit = Audit.createTaskRunner(); | |
26 | |
27 audit.defineTask("linear", function (done) { | |
28 // Test the value attribute from a linearRamp event | |
29 runTest(function (g, v0, t0, v1, t1) { | |
30 g.gain.linearRampToValueAtTime(v1, t1); | |
31 return { | |
32 expectedValue: function (testTime) { | |
33 return audioParamLinearRamp(testTime, v0, t0, v1, t1); | |
34 }, | |
35 message: "linearRamp(" + v1 + ", " + t1 + ")", | |
36 errorThreshold: 1.1650e-6 | |
37 }; | |
38 }).then(done); | |
39 }); | |
40 | |
41 audit.defineTask("exponential", function (done) { | |
42 // Test the value attribute from an exponentialRamp event | |
43 runTest(function (g, v0, t0, v1, t1) { | |
44 g.gain.exponentialRampToValueAtTime(v1, t1); | |
45 return { | |
46 expectedValue: function (testTime) { | |
47 return audioParamExponentialRamp(testTime, v0, t0, v1, t1); | |
48 }, | |
49 message: "exponentialRamp(" + v1 + ", " + t1 + ")", | |
50 errorThreshold: 7.4601e-7 | |
51 }; | |
52 }).then(done); | |
53 }); | |
54 | |
55 audit.defineTask("setTarget", function (done) { | |
56 // Test the value attribute from a setTargetAtTime event | |
57 runTest(function (g, v0, t0, v1, t1) { | |
58 var timeConstant = 0.1; | |
59 var vFinal = 0; | |
60 g.gain.setTargetAtTime(vFinal, t0, timeConstant); | |
61 return { | |
62 expectedValue: function (testTime) { | |
63 return audioParamSetTarget(testTime, v0, t0, vFinal, timeConstant)
; | |
64 }, | |
65 message: "setTargetAtTime(" + vFinal + ", " + t0 + ", " + timeConsta
nt + ")", | |
66 errorThreshold: 2.2599e-6 | |
67 }; | |
68 }).then(done); | |
69 }); | |
70 | |
71 audit.defineTask("setValueCurve", function (done) { | |
72 // Test the value attribute from a setValueCurve event | |
73 runTest(function (g, v0, t0, v1, t1) { | |
74 var curve = [1, 1.5, 4]; | |
75 var duration = t1 - t0; | |
76 g.gain.setValueCurveAtTime(Float32Array.from(curve), t0, duration); | |
77 return { | |
78 expectedValue: function (testTime) { | |
79 return audioParamSetValueCurve(testTime, curve, t0, duration); | |
80 }, | |
81 message: "setValueCurveAtTime([" + curve + "], " + t0 + ", " + durat
ion + ")", | |
82 errorThreshold: 7.9577e-8 | |
83 }; | |
84 }).then(done); | |
85 }); | |
86 | |
87 audit.defineTask("finish", function (done) { | |
88 finishJSTest(); | |
89 done(); | |
90 }); | |
91 | |
92 audit.runTasks(); | |
93 | |
94 // Test that the .value getter has the correct value when a timeline is ru
nning. | |
95 // The |testFunction| is the underlying test to be run. | |
96 function runTest(testFunction) { | |
97 // Create a simple graph consisting of a constant source and a gain node
where the | |
98 // automations are run. A setValueAtTime event starts things off. | |
99 var context = new OfflineAudioContext(1, renderFrames, sampleRate); | |
100 var source = context.createBufferSource(); | |
101 source.buffer = createConstantBuffer(context, 1, 1); | |
102 source.loop = true; | |
103 var gain = context.createGain(); | |
104 | |
105 source.connect(gain); | |
106 gain.connect(context.destination); | |
107 | |
108 // Start the timeline with setValueAtTime(v0, t0). | |
109 var v0 = 0.25; | |
110 var t0 = 0; | |
111 // End value and time, for those that need it. The end time is less tha
n the rendering | |
112 // duration so we can test that the final values of the automation (if a
ny) are also | |
113 // correct. | |
114 var v1 = 100; | |
115 var t1 = renderDuration - 5 * renderQuantumSize / sampleRate; | |
116 | |
117 gain.gain.setValueAtTime(v0, t0); | |
118 | |
119 // Run the desired automation test. The test function returns a diction
ary consisting of | |
120 // the following properties: | |
121 // | |
122 // |message| an informative message about the automation being te
sted. | |
123 // |errorThreshold| error threshold to determine if the test passes or n
ot. | |
124 // |expectedValue| a function that compute the expected value at time |
t|. | |
125 var test = testFunction(gain, v0, t0, v1, t1); | |
126 | |
127 // Print an informative message about the test being run. | |
128 testPassed("Initialize " + test.message + " with setValueAtTime(" + v0 +
", " + t0 + ")."); | |
129 | |
130 var success = true; | |
131 | |
132 // Max relative error found for this test. This is printed if the test f
ails so that setting | |
133 // the thresholds is easier. | |
134 var maxError = 0; | |
135 | |
136 // For every rendering quantum (except the first), suspend the context s
o the we can inspect | |
137 // the value attribute and compare it with the expected value. | |
138 for (var k = 1; k < renderLoops; ++k) { | |
139 var time = k * renderQuantumSize / sampleRate; | |
140 context.suspend(time).then(function () { | |
141 // The context is supsended at time |time|, which is just before the
rendering quantum | |
142 // starts. Thus, the value of the attribute is actually 1 frame bef
ore the current | |
143 // context time. | |
144 var sampleTime = context.currentTime - 1 / sampleRate; | |
145 | |
146 // Compute the max relative error | |
147 var expected = test.expectedValue(sampleTime); | |
148 var relError = Math.abs(expected - gain.gain.value) / Math.abs(expec
ted); | |
149 maxError = Math.max(relError, maxError); | |
150 | |
151 success = Should(test.message + " at frame " + (sampleRate * sampleT
ime), | |
152 gain.gain.value, { | |
153 precision: 7 | |
154 }) | |
155 .beCloseTo(expected, test.errorThreshold || 0) && success; | |
156 }).then(context.resume.bind(context)); | |
157 } | |
158 | |
159 source.start(); | |
160 | |
161 return context.startRendering().then(function (resultBuffer) { | |
162 // Just print a final pass (or fail) message. | |
163 if (success) | |
164 testPassed("Gain .value attribute correctly updated during automatio
n.\n"); | |
165 else | |
166 testFailed( | |
167 "Gain .value attribute not correctly updated during automation; ma
x error = " + | |
168 maxError + ".\n"); | |
169 }); | |
170 } | |
171 </script> | |
172 </body> | |
173 </html> | |
OLD | NEW |