| 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 |