OLD | NEW |
1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
2 <html> | 2 <html> |
3 | 3 <head> |
4 <head> | 4 <title> |
5 <script src="../../resources/testharness.js"></script> | 5 audionode-disconnect-audioparam.html |
6 <script src="../../resources/testharnessreport.js"></script> | 6 </title> |
7 <script src="../resources/audit-util.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
8 <script src="../resources/audit.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
9 </head> | 9 <script src="../resources/audit-util.js"></script> |
10 | 10 <script src="../resources/audit.js"></script> |
11 <body> | 11 </head> |
12 <script> | 12 <body> |
13 | 13 <script id="layout-test-code"> |
14 var renderQuantum = 128; | 14 let renderQuantum = 128; |
15 | 15 |
16 var sampleRate = 44100; | 16 let sampleRate = 44100; |
17 var renderDuration = 0.5; | 17 let renderDuration = 0.5; |
18 var disconnectTime = 0.5 * renderDuration; | 18 let disconnectTime = 0.5 * renderDuration; |
19 | 19 |
20 var audit = Audit.createTaskRunner(); | 20 let audit = Audit.createTaskRunner(); |
21 | 21 |
22 // Calculate the index for disconnection. | 22 // Calculate the index for disconnection. |
23 function getDisconnectIndex(disconnectTime) { | 23 function getDisconnectIndex(disconnectTime) { |
24 var disconnectIndex = disconnectTime * sampleRate; | 24 let disconnectIndex = disconnectTime * sampleRate; |
25 return disconnectIndex -= (disconnectIndex) % renderQuantum; | 25 return disconnectIndex -= (disconnectIndex) % renderQuantum; |
26 } | 26 } |
27 | 27 |
28 // Get the index of value change. | 28 // Get the index of value change. |
29 function getValueChangeIndex(array, targetValue) { | 29 function getValueChangeIndex(array, targetValue) { |
30 return array.findIndex(function (element, index) { | 30 return array.findIndex(function(element, index) { |
31 if (element === targetValue) | 31 if (element === targetValue) |
32 return true; | 32 return true; |
| 33 }); |
| 34 } |
| 35 |
| 36 // Task 1: test disconnect(AudioParam) method. |
| 37 audit.define('disconnect(AudioParam)', (task, should) => { |
| 38 |
| 39 // Creates a buffer source with value [1] and then connect it to two |
| 40 // gain nodes in series. The output of the buffer source is lowered by |
| 41 // half |
| 42 // (* 0.5) and then connected to two |.gain| AudioParams in each gain |
| 43 // node. |
| 44 // |
| 45 // (1) bufferSource => gain1 => gain2 |
| 46 // (2) bufferSource => half => gain1.gain |
| 47 // (3) half => gain2.gain |
| 48 // |
| 49 // This graph should produce the output of 2.25 (= 1 * 1.5 * 1.5). After |
| 50 // disconnecting (3), it should produce 1.5. |
| 51 let context = |
| 52 new OfflineAudioContext(1, renderDuration * sampleRate, sampleRate); |
| 53 let source = context.createBufferSource(); |
| 54 let buffer1ch = createConstantBuffer(context, 1, 1); |
| 55 let half = context.createGain(); |
| 56 let gain1 = context.createGain(); |
| 57 let gain2 = context.createGain(); |
| 58 |
| 59 source.buffer = buffer1ch; |
| 60 source.loop = true; |
| 61 half.gain.value = 0.5; |
| 62 |
| 63 source.connect(gain1); |
| 64 gain1.connect(gain2); |
| 65 gain2.connect(context.destination); |
| 66 source.connect(half); |
| 67 |
| 68 // Connecting |half| to both |gain1.gain| and |gain2.gain| amplifies the |
| 69 // signal by 2.25 (= 1.5 * 1.5) because each gain node amplifies the |
| 70 // signal by 1.5 (= 1.0 + 0.5). |
| 71 half.connect(gain1.gain); |
| 72 half.connect(gain2.gain); |
| 73 |
| 74 source.start(); |
| 75 |
| 76 // Schedule the disconnection at the half of render duration. |
| 77 context.suspend(disconnectTime).then(function() { |
| 78 half.disconnect(gain2.gain); |
| 79 context.resume(); |
| 80 }); |
| 81 |
| 82 context.startRendering() |
| 83 .then(function(buffer) { |
| 84 let channelData = buffer.getChannelData(0); |
| 85 let disconnectIndex = getDisconnectIndex(disconnectTime); |
| 86 let valueChangeIndex = getValueChangeIndex(channelData, 1.5); |
| 87 |
| 88 // Expected values are: 1 * 1.5 * 1.5 -> 1 * 1.5 = [2.25, 1.5] |
| 89 should(channelData, 'Channel #0').containValues([2.25, 1.5]); |
| 90 should(valueChangeIndex, 'The index of value change') |
| 91 .beEqualTo(disconnectIndex); |
| 92 |
| 93 }) |
| 94 .then(() => task.done()); |
33 }); | 95 }); |
34 } | 96 |
35 | 97 // Task 2: test disconnect(AudioParam, output) method. |
36 // Task 1: test disconnect(AudioParam) method. | 98 audit.define('disconnect(AudioParam, output)', (task, should) => { |
37 audit.define('disconnect(AudioParam)', (task, should) => { | 99 |
38 | 100 // Create a 2-channel buffer source with [1, 2] in each channel and |
39 // Creates a buffer source with value [1] and then connect it to two gain | 101 // make a serial connection through gain1 and gain 2. The make the |
40 // nodes in series. The output of the buffer source is lowered by half | 102 // buffer source half with a gain node and connect it to a 2-output |
41 // (* 0.5) and then connected to two |.gain| AudioParams in each gain node
. | 103 // splitter. Connect each output to 2 gain AudioParams respectively. |
42 // | 104 // |
43 // (1) bufferSource => gain1 => gain2 | 105 // (1) bufferSource => gain1 => gain2 |
44 // (2) bufferSource => half => gain1.gain | 106 // (2) bufferSource => half => splitter(2) |
45 // (3) half => gain2.gain | 107 // (3) splitter#0 => gain1.gain |
46 // | 108 // (4) splitter#1 => gain2.gain |
47 // This graph should produce the output of 2.25 (= 1 * 1.5 * 1.5). After | 109 // |
48 // disconnecting (3), it should produce 1.5. | 110 // This graph should produce 3 (= 1 * 1.5 * 2) and 6 (= 2 * 1.5 * 2) for |
49 var context = new OfflineAudioContext(1, renderDuration * sampleRate, samp
leRate); | 111 // each channel. After disconnecting (4), it should output 1.5 and 3. |
50 var source = context.createBufferSource(); | 112 let context = |
51 var buffer1ch = createConstantBuffer(context, 1, 1); | 113 new OfflineAudioContext(2, renderDuration * sampleRate, sampleRate); |
52 var half = context.createGain(); | 114 let source = context.createBufferSource(); |
53 var gain1 = context.createGain(); | 115 let buffer2ch = createConstantBuffer(context, 1, [1, 2]); |
54 var gain2 = context.createGain(); | 116 let splitter = context.createChannelSplitter(2); |
55 | 117 let half = context.createGain(); |
56 source.buffer = buffer1ch; | 118 let gain1 = context.createGain(); |
57 source.loop = true; | 119 let gain2 = context.createGain(); |
58 half.gain.value = 0.5; | 120 |
59 | 121 source.buffer = buffer2ch; |
60 source.connect(gain1); | 122 source.loop = true; |
61 gain1.connect(gain2); | 123 half.gain.value = 0.5; |
62 gain2.connect(context.destination); | 124 |
63 source.connect(half); | 125 source.connect(gain1); |
64 | 126 gain1.connect(gain2); |
65 // Connecting |half| to both |gain1.gain| and |gain2.gain| amplifies the | 127 gain2.connect(context.destination); |
66 // signal by 2.25 (= 1.5 * 1.5) because each gain node amplifies the signa
l | 128 |
67 // by 1.5 (= 1.0 + 0.5). | 129 // |source| originally is [1, 2] but it becomes [0.5, 1] after 0.5 gain. |
68 half.connect(gain1.gain); | 130 // Each splitter's output will be applied to |gain1.gain| and |
69 half.connect(gain2.gain); | 131 // |gain2.gain| respectively in an additive fashion. |
70 | 132 source.connect(half); |
71 source.start(); | 133 half.connect(splitter); |
72 | 134 |
73 // Schedule the disconnection at the half of render duration. | 135 // This amplifies the signal by 1.5. (= 1.0 + 0.5) |
74 context.suspend(disconnectTime).then(function () { | 136 splitter.connect(gain1.gain, 0); |
75 half.disconnect(gain2.gain); | 137 |
76 context.resume(); | 138 // This amplifies the signal by 2. (= 1.0 + 1.0) |
| 139 splitter.connect(gain2.gain, 1); |
| 140 |
| 141 source.start(); |
| 142 |
| 143 // Schedule the disconnection at the half of render duration. |
| 144 context.suspend(disconnectTime).then(function() { |
| 145 splitter.disconnect(gain2.gain, 1); |
| 146 context.resume(); |
| 147 }); |
| 148 |
| 149 context.startRendering() |
| 150 .then(function(buffer) { |
| 151 let channelData0 = buffer.getChannelData(0); |
| 152 let channelData1 = buffer.getChannelData(1); |
| 153 |
| 154 let disconnectIndex = getDisconnectIndex(disconnectTime); |
| 155 let valueChangeIndexCh0 = getValueChangeIndex(channelData0, 1.5); |
| 156 let valueChangeIndexCh1 = getValueChangeIndex(channelData1, 3); |
| 157 |
| 158 // Expected values are: 1 * 1.5 * 2 -> 1 * 1.5 = [3, 1.5] |
| 159 should(channelData0, 'Channel #0').containValues([3, 1.5]); |
| 160 should( |
| 161 valueChangeIndexCh0, |
| 162 'The index of value change in channel #0') |
| 163 .beEqualTo(disconnectIndex); |
| 164 |
| 165 // Expected values are: 2 * 1.5 * 2 -> 2 * 1.5 = [6, 3] |
| 166 should(channelData1, 'Channel #1').containValues([6, 3]); |
| 167 should( |
| 168 valueChangeIndexCh1, |
| 169 'The index of value change in channel #1') |
| 170 .beEqualTo(disconnectIndex); |
| 171 |
| 172 }) |
| 173 .then(() => task.done()); |
77 }); | 174 }); |
78 | 175 |
79 context.startRendering().then(function (buffer) { | 176 // Task 3: exception checks. |
80 var channelData = buffer.getChannelData(0); | 177 audit.define('exceptions', (task, should) => { |
81 var disconnectIndex = getDisconnectIndex(disconnectTime); | 178 let context = new AudioContext(); |
82 var valueChangeIndex = getValueChangeIndex(channelData, 1.5); | 179 let gain1 = context.createGain(); |
83 | 180 let splitter = context.createChannelSplitter(2); |
84 // Expected values are: 1 * 1.5 * 1.5 -> 1 * 1.5 = [2.25, 1.5] | 181 let gain2 = context.createGain(); |
85 should(channelData, 'Channel #0').containValues([2.25, 1.5]); | 182 let gain3 = context.createGain(); |
86 should(valueChangeIndex, 'The index of value change') | 183 |
87 .beEqualTo(disconnectIndex); | 184 // Connect a splitter to gain nodes and merger so we can test the |
88 | 185 // possible ways of disconnecting the nodes to verify that appropriate |
89 }).then(() => task.done()); | 186 // exceptions are thrown. |
90 }); | 187 gain1.connect(splitter); |
91 | 188 splitter.connect(gain2.gain, 0); |
92 // Task 2: test disconnect(AudioParam, output) method. | 189 splitter.connect(gain3.gain, 1); |
93 audit.define('disconnect(AudioParam, output)', (task, should) => { | 190 gain2.connect(gain3); |
94 | 191 gain3.connect(context.destination); |
95 // Create a 2-channel buffer source with [1, 2] in each channel and | 192 |
96 // make a serial connection through gain1 and gain 2. The make the buffer | 193 // gain1 is not connected to gain3.gain. Exception should be thrown. |
97 // source half with a gain node and connect it to a 2-output splitter. | 194 should(function() { |
98 // Connect each output to 2 gain AudioParams respectively. | 195 gain1.disconnect(gain3.gain); |
99 // | 196 }, 'gain1.disconnect(gain3.gain)').throw('InvalidAccessError'); |
100 // (1) bufferSource => gain1 => gain2 | 197 |
101 // (2) bufferSource => half => splitter(2) | 198 // When the output index is good but the destination is invalid. |
102 // (3) splitter#0 => gain1.gain | 199 should(function() { |
103 // (4) splitter#1 => gain2.gain | 200 splitter.disconnect(gain1.gain, 1); |
104 // | 201 }, 'splitter.disconnect(gain1.gain, 1)').throw('InvalidAccessError'); |
105 // This graph should produce 3 (= 1 * 1.5 * 2) and 6 (= 2 * 1.5 * 2) for | 202 |
106 // each channel. After disconnecting (4), it should output 1.5 and 3. | 203 // When both arguments are wrong, throw IndexSizeError first. |
107 var context = new OfflineAudioContext(2, renderDuration * sampleRate, samp
leRate); | 204 should(function() { |
108 var source = context.createBufferSource(); | 205 splitter.disconnect(gain1.gain, 2); |
109 var buffer2ch = createConstantBuffer(context, 1, [1, 2]); | 206 }, 'splitter.disconnect(gain1.gain, 2)').throw('IndexSizeError'); |
110 var splitter = context.createChannelSplitter(2); | 207 |
111 var half = context.createGain(); | 208 task.done(); |
112 var gain1 = context.createGain(); | |
113 var gain2 = context.createGain(); | |
114 | |
115 source.buffer = buffer2ch; | |
116 source.loop = true; | |
117 half.gain.value = 0.5; | |
118 | |
119 source.connect(gain1); | |
120 gain1.connect(gain2); | |
121 gain2.connect(context.destination); | |
122 | |
123 // |source| originally is [1, 2] but it becomes [0.5, 1] after 0.5 gain. | |
124 // Each splitter's output will be applied to |gain1.gain| and |gain2.gain| | |
125 // respectively in an additive fashion. | |
126 source.connect(half); | |
127 half.connect(splitter); | |
128 | |
129 // This amplifies the signal by 1.5. (= 1.0 + 0.5) | |
130 splitter.connect(gain1.gain, 0); | |
131 | |
132 // This amplifies the signal by 2. (= 1.0 + 1.0) | |
133 splitter.connect(gain2.gain, 1); | |
134 | |
135 source.start(); | |
136 | |
137 // Schedule the disconnection at the half of render duration. | |
138 context.suspend(disconnectTime).then(function () { | |
139 splitter.disconnect(gain2.gain, 1); | |
140 context.resume(); | |
141 }); | 209 }); |
142 | 210 |
143 context.startRendering().then(function (buffer) { | 211 audit.run(); |
144 var channelData0 = buffer.getChannelData(0); | 212 </script> |
145 var channelData1 = buffer.getChannelData(1); | 213 </body> |
146 | |
147 var disconnectIndex = getDisconnectIndex(disconnectTime); | |
148 var valueChangeIndexCh0 = getValueChangeIndex(channelData0, 1.5); | |
149 var valueChangeIndexCh1 = getValueChangeIndex(channelData1, 3); | |
150 | |
151 // Expected values are: 1 * 1.5 * 2 -> 1 * 1.5 = [3, 1.5] | |
152 should(channelData0, 'Channel #0').containValues([3, 1.5]); | |
153 should(valueChangeIndexCh0, 'The index of value change in channel #0') | |
154 .beEqualTo(disconnectIndex); | |
155 | |
156 // Expected values are: 2 * 1.5 * 2 -> 2 * 1.5 = [6, 3] | |
157 should(channelData1, 'Channel #1').containValues([6, 3]); | |
158 should(valueChangeIndexCh1, 'The index of value change in channel #1') | |
159 .beEqualTo(disconnectIndex); | |
160 | |
161 }).then(() => task.done()); | |
162 }); | |
163 | |
164 // Task 3: exception checks. | |
165 audit.define('exceptions', (task, should) => { | |
166 var context = new AudioContext(); | |
167 var gain1 = context.createGain(); | |
168 var splitter = context.createChannelSplitter(2); | |
169 var gain2 = context.createGain(); | |
170 var gain3 = context.createGain(); | |
171 | |
172 // Connect a splitter to gain nodes and merger so we can test the possible | |
173 // ways of disconnecting the nodes to verify that appropriate exceptions | |
174 // are thrown. | |
175 gain1.connect(splitter); | |
176 splitter.connect(gain2.gain, 0); | |
177 splitter.connect(gain3.gain, 1); | |
178 gain2.connect(gain3); | |
179 gain3.connect(context.destination); | |
180 | |
181 // gain1 is not connected to gain3.gain. Exception should be thrown. | |
182 should(function () { | |
183 gain1.disconnect(gain3.gain); | |
184 }, 'gain1.disconnect(gain3.gain)').throw('InvalidAccessError'); | |
185 | |
186 // When the output index is good but the destination is invalid. | |
187 should(function () { | |
188 splitter.disconnect(gain1.gain, 1); | |
189 }, 'splitter.disconnect(gain1.gain, 1)').throw('InvalidAccessError'); | |
190 | |
191 // When both arguments are wrong, throw IndexSizeError first. | |
192 should(function () { | |
193 splitter.disconnect(gain1.gain, 2); | |
194 }, 'splitter.disconnect(gain1.gain, 2)').throw('IndexSizeError'); | |
195 | |
196 task.done(); | |
197 }); | |
198 | |
199 audit.run(); | |
200 </script> | |
201 </body> | |
202 | |
203 </html> | 214 </html> |
OLD | NEW |