5 <script src=
"../resources/js-test.js"></script>
6 <script src=
"resources/compatibility.js"></script>
7 <script src=
"resources/audio-testing.js"></script>
12 description('Test disconnect() method on AudioParam destination.');
13 window
.jsTestIsAsync
= true;
15 var audit
= Audit
.createTaskRunner();
17 // The long render length (20 seconds) test 1 and 2 is to make sure the
18 // |onstatechange| event gets fired to start the source, which can take
19 // quite a bit of time.
20 var testDuration
= 20;
22 // Task 1: test disconnect(AudioParam) method.
23 audit
.defineTask('disconnect(AudioParam)', function (done
) {
25 // Creates a buffer source with value [1] and then connect it to two gain
26 // nodes in series. The output of the buffer source is lowered by half
27 // (* 0.5) and then connected to two |.gain| AudioParams in each gain node.
28 // (1) bufferSource => gain1 => gain2
29 // (2) bufferSource => half => gain1.gain
30 // (3) half => gain2.gain
31 // This graph should produce the output of 2.25 (= 1 * 1.5 * 1.5). After
32 // disconnecting (3), it should produce 1.5.
33 var context
= new OfflineAudioContext(1, 44100 * testDuration
, 44100);
34 var source
= context
.createBufferSource();
35 var buffer1ch
= createTestingAudioBuffer(context
, 1, 128);
36 var half
= context
.createGain();
37 var gain1
= context
.createGain();
38 var gain2
= context
.createGain();
40 source
.buffer
= buffer1ch
;
42 half
.gain
.value
= 0.5;
44 source
.connect(gain1
);
46 gain2
.connect(context
.destination
);
49 // Connecting |half| to both |gain1.gain| and |gain2.gain| amplifies the
50 // signal by 2.25 (= 1.5 * 1.5) because each gain node amplifies the signal
51 // by 1.5 (= 1.0 + 0.5).
52 half
.connect(gain1
.gain
);
53 half
.connect(gain2
.gain
);
57 // Disconnects after the rendering starts.
59 // FIXME: Although this guarantees that the disconnection happens after
60 // the rendering starts, still the actual disconnection might happen after
61 // oncomplete event fired.
63 // The 10ms delay is 1/1000 of the total render length (10,000ms). Because
64 // OfflineAudioContext runs faster than real time, the disconnection might
65 // happen after the rendering finishes. Then lower the delay and increase
66 // the render length to avoid the test failure.
67 context
.onstatechange = function () {
68 if (context
.state
=== 'running')
69 half
.disconnect(gain2
.gain
);
72 context
.startRendering().then(function (buffer
) {
74 // Note that this test depends on the disconnection below to happen
75 // sometime during rendering.
77 // Expected values are: 1 * 1.5 * 1.5 -> 1 * 1.5 = [2.25, 1.5]
78 Should('Channel #0', buffer
.getChannelData(0)).containValues([2.25, 1.5]);
83 // Task 2: test disconnect(AudioParam, output) method.
84 audit
.defineTask('disconnect(AudioParam, output)', function (done
) {
86 // Create a 2-channel buffer source with [1, 2] in each channel and
87 // make a serial connection through gain1 and gain 2. The make the buffer
88 // source half with a gain node and connect it to a 2-output splitter.
89 // Connect each output to 2 gain AudioParams respectively.
90 // (1) bufferSource => gain1 => gain2
91 // (2) bufferSource => half => splitter(2)
92 // (3) splitter#0 => gain1.gain
93 // (4) splitter#1 => gain2.gain
94 // This graph should produce 3 (= 1 * 1.5 * 2) and 6 (= 2 * 1.5 * 2) for
95 // each channel. After disconnecting (4), it should output 1.5 and 3.
96 var context
= new OfflineAudioContext(2, 44100 * testDuration
, 44100);
97 var source
= context
.createBufferSource();
98 var buffer2ch
= createTestingAudioBuffer(context
, 2, 128);
99 var splitter
= context
.createChannelSplitter(2);
100 var half
= context
.createGain();
101 var gain1
= context
.createGain();
102 var gain2
= context
.createGain();
104 source
.buffer
= buffer2ch
;
106 half
.gain
.value
= 0.5;
108 source
.connect(gain1
);
109 gain1
.connect(gain2
);
110 gain2
.connect(context
.destination
);
112 // |source| originally is [1, 2] but it becomes [0.5, 1] after 0.5 gain.
113 // Each splitter's output will be applied to |gain1.gain| and |gain2.gain|
114 // respectively in an additive fashion.
115 source
.connect(half
);
116 half
.connect(splitter
);
118 // This amplifies the signal by 1.5. (= 1.0 + 0.5)
119 splitter
.connect(gain1
.gain
, 0);
121 // This amplifies the signal by 2. (= 1.0 + 1.0)
122 splitter
.connect(gain2
.gain
, 1);
126 // Disconnect after the rendering starts. See the comment in the previous
128 context
.onstatechange = function () {
129 if (context
.state
=== 'running')
130 splitter
.disconnect(gain2
.gain
, 1);
133 context
.startRendering().then(function (buffer
) {
135 // Expected values are: 1 * 1.5 * 2 -> 1 * 1.5 = [3, 1.5]
136 Should('Channel #0', buffer
.getChannelData(0)).containValues([3, 1.5]);
138 // Expected values are: 2 * 1.5 * 2 -> 2 * 1.5 = [6, 3]
139 Should('Channel #1', buffer
.getChannelData(1)).containValues([6, 3]);
144 // Task 3: exception checks.
145 audit
.defineTask('exceptions', function (done
) {
146 var context
= new AudioContext();
147 var gain1
= context
.createGain();
148 var splitter
= context
.createChannelSplitter(2);
149 var gain2
= context
.createGain();
150 var gain3
= context
.createGain();
152 // Connect a splitter to gain nodes and merger so we can test the possible
153 // ways of disconnecting the nodes to verify that appropriate exceptions
155 gain1
.connect(splitter
);
156 splitter
.connect(gain2
.gain
, 0);
157 splitter
.connect(gain3
.gain
, 1);
158 gain2
.connect(gain3
);
159 gain3
.connect(context
.destination
);
161 // gain1 is not connected to gain3.gain. Exception should be thrown.
162 Should('gain1.disconnect(gain3.gain)', function () {
163 gain1
.disconnect(gain3
.gain
);
164 }).throw('InvalidAccessError');
166 // When the output index is good but the destination is invalid.
167 Should('splitter.disconnect(gain1.gain, 1)', function () {
168 splitter
.disconnect(gain1
.gain
, 1);
169 }).throw('InvalidAccessError');
171 // When both arguments are wrong, throw IndexSizeError first.
172 Should('splitter.disconnect(gain1.gain, 2)', function () {
173 splitter
.disconnect(gain1
.gain
, 2);
174 }).throw('IndexSizeError');
179 audit
.defineTask('finish', function (done
) {
185 'disconnect(AudioParam)',
186 'disconnect(AudioParam, output)',
191 successfullyParsed
= true;