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 |