| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 <html> | |
| 3 | |
| 4 <head> | |
| 5 <script src="../resources/js-test.js"></script> | |
| 6 <script src="resources/compatibility.js"></script> | |
| 7 <script src="resources/audit-util.js"></script> | |
| 8 <script src="resources/audio-testing.js"></script> | |
| 9 <script src="resources/audioparam-testing.js"></script> | |
| 10 </head> | |
| 11 | |
| 12 <body> | |
| 13 <script> | |
| 14 description('Test method chaining feature of AudioParam automation methods.'
); | |
| 15 window.jsTestIsAsync = true; | |
| 16 | |
| 17 var sampleRate = 44100; | |
| 18 | |
| 19 // Create a dummy array for setValueCurveAtTime method. | |
| 20 var curveArray = new Float32Array([5.0, 6.0]); | |
| 21 | |
| 22 // AudioNode dictionary with associated dummy arguments. | |
| 23 var methodDictionary = [ | |
| 24 { name: 'setValueAtTime', args: [1.0, 0.0] }, | |
| 25 { name: 'linearRampToValueAtTime', args: [2.0, 1.0] }, | |
| 26 { name: 'exponentialRampToValueAtTime', args: [3.0, 2.0] }, | |
| 27 { name: 'setTargetAtTime', args: [4.0, 2.0, 0.5] }, | |
| 28 { name: 'setValueCurveAtTime', args: [curveArray, 5.0, 1.0] }, | |
| 29 { name: 'cancelScheduledValues', args: [6.0] } | |
| 30 ]; | |
| 31 | |
| 32 function verifyReturnedParam(config) { | |
| 33 if (config.source === config.returned) | |
| 34 testPassed('The return value of ' + config.desc + ' matches the source A
udioParam.'); | |
| 35 else | |
| 36 testFailed('The return value of ' + config.desc + ' does NOT match sourc
e AudioParam.'); | |
| 37 } | |
| 38 | |
| 39 var audit = Audit.createTaskRunner(); | |
| 40 | |
| 41 // Task: testing entries from the dictionary. | |
| 42 audit.defineTask('from-dictionary', function (done) { | |
| 43 var context = new AudioContext(); | |
| 44 | |
| 45 methodDictionary.forEach(function (method) { | |
| 46 var sourceParam = context.createGain().gain; | |
| 47 verifyReturnedParam({ | |
| 48 source: sourceParam, | |
| 49 returned: sourceParam[method.name](...method.args), | |
| 50 desc: sourceParam.constructor.name + '.' + method.name + '()' | |
| 51 }); | |
| 52 }); | |
| 53 | |
| 54 done(); | |
| 55 }); | |
| 56 | |
| 57 // Task: test method chaining with invalid operation. | |
| 58 audit.defineTask('invalid-operation', function (done) { | |
| 59 var context = new OfflineAudioContext(1, 44100, 44100); | |
| 60 var osc = context.createOscillator(); | |
| 61 var amp1 = context.createGain(); | |
| 62 var amp2 = context.createGain(); | |
| 63 | |
| 64 osc.connect(amp1); | |
| 65 osc.connect(amp2); | |
| 66 amp1.connect(context.destination); | |
| 67 amp2.connect(context.destination); | |
| 68 | |
| 69 // The first operation fails with an exception, thus the second one | |
| 70 // should not have effect on the parameter value. Instead, it should | |
| 71 // maintain the default value of 1.0. | |
| 72 Should('Calling setValueAtTime() with a negative end time', function () { | |
| 73 amp1.gain | |
| 74 .setValueAtTime(0.25, -1.0) | |
| 75 .linearRampToValueAtTime(2.0, 1.0); | |
| 76 }).throw('InvalidAccessError'); | |
| 77 | |
| 78 // The first operation succeeds but the second fails due to zero target | |
| 79 // value for the exponential ramp. Thus only the first should have effect | |
| 80 // on the parameter value, setting the value to 0.5. | |
| 81 Should('Calling exponentialRampToValueAtTime() with a zero target value',
function () { | |
| 82 amp2.gain | |
| 83 .setValueAtTime(0.5, 0.0) | |
| 84 .exponentialRampToValueAtTime(0.0, 1.0); | |
| 85 }).throw('InvalidAccessError'); | |
| 86 | |
| 87 osc.start(); | |
| 88 osc.stop(1.0); | |
| 89 | |
| 90 context.startRendering().then(function (buffer) { | |
| 91 Should('The gain value of the first gain node', amp1.gain.value).beEqual
To(1.0); | |
| 92 Should('The gain value of the second gain node', amp2.gain.value).beEqua
lTo(0.5); | |
| 93 }).then(done); | |
| 94 }); | |
| 95 | |
| 96 // Task: verify if the method chaining actually works. Create an arbitrary | |
| 97 // envelope and compare the result with the expected one created by JS code. | |
| 98 audit.defineTask('verification', function (done) { | |
| 99 var context = new OfflineAudioContext(1, sampleRate * 4, sampleRate); | |
| 100 var constantBuffer = createConstantBuffer(context, 1, 1.0); | |
| 101 | |
| 102 var source = context.createBufferSource(); | |
| 103 source.buffer = constantBuffer; | |
| 104 source.loop = true; | |
| 105 | |
| 106 var envelope = context.createGain(); | |
| 107 | |
| 108 source.connect(envelope); | |
| 109 envelope.connect(context.destination); | |
| 110 | |
| 111 envelope.gain | |
| 112 .setValueAtTime(0.0, 0.0) | |
| 113 .linearRampToValueAtTime(1.0, 1.0) | |
| 114 .exponentialRampToValueAtTime(0.5, 2.0) | |
| 115 .setTargetAtTime(0.001, 2.0, 0.5); | |
| 116 | |
| 117 source.start(); | |
| 118 | |
| 119 context.startRendering().then(function (buffer) { | |
| 120 var expectedEnvelope = createLinearRampArray(0.0, 1.0, 0.0, 1.0, sampleR
ate); | |
| 121 expectedEnvelope.push(...createExponentialRampArray(1.0, 2.0, 1.0, 0.5,
sampleRate)); | |
| 122 expectedEnvelope.push(...createExponentialApproachArray(2.0, 4.0, 0.5, 0
.001, sampleRate, 0.5)); | |
| 123 | |
| 124 // There are slight differences between JS implementation of AudioParam | |
| 125 // envelope and the internal implementation. (i.e. double/float and | |
| 126 // rounding up) The error threshold is adjusted empirically through | |
| 127 // the local testing. | |
| 128 Should('The rendered envelope', buffer.getChannelData(0), { | |
| 129 numberOfArrayLog: 5 | |
| 130 }).beCloseToArray(expectedEnvelope, 4.0532e-6); | |
| 131 }).then(done); | |
| 132 }); | |
| 133 | |
| 134 audit.defineTask('finish', function (done) { | |
| 135 finishJSTest(); | |
| 136 done(); | |
| 137 }); | |
| 138 | |
| 139 audit.runTasks(); | |
| 140 | |
| 141 successfullyParsed = true; | |
| 142 </script> | |
| 143 </body> | |
| 144 | |
| 145 </html> | |
| OLD | NEW |