audionode-disconnect.html (11022B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title> 5 audionode-disconnect.html 6 </title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/webaudio/resources/audit-util.js"></script> 10 <script src="/webaudio/resources/audit.js"></script> 11 </head> 12 <body> 13 <script id="layout-test-code"> 14 let audit = Audit.createTaskRunner(); 15 16 // Task 1: test disconnect() method. 17 audit.define('disconnect()', (task, should) => { 18 19 // Connect a source to multiple gain nodes, each connected to the 20 // destination. Then disconnect the source. The expected output should 21 // be all zeros since the source was disconnected. 22 let context = new OfflineAudioContext(1, 128, 44100); 23 let source = context.createBufferSource(); 24 let buffer1ch = createConstantBuffer(context, 128, [1]); 25 let gain1 = context.createGain(); 26 let gain2 = context.createGain(); 27 let gain3 = context.createGain(); 28 29 source.buffer = buffer1ch; 30 31 source.connect(gain1); 32 source.connect(gain2); 33 source.connect(gain3); 34 gain1.connect(context.destination); 35 gain2.connect(context.destination); 36 gain3.connect(context.destination); 37 source.start(); 38 39 // This disconnects everything. 40 source.disconnect(); 41 42 context.startRendering() 43 .then(function(buffer) { 44 45 // With everything disconnected, the result should be zero. 46 should(buffer.getChannelData(0), 'Channel #0') 47 .beConstantValueOf(0); 48 49 }) 50 .then(() => task.done()); 51 }); 52 53 // Task 2: test disconnect(output) method. 54 audit.define('disconnect(output)', (task, should) => { 55 56 // Create multiple connections from each output of a ChannelSplitter 57 // to a gain node. Then test if disconnecting a single output of 58 // splitter is actually disconnected. 59 let context = new OfflineAudioContext(1, 128, 44100); 60 let source = context.createBufferSource(); 61 let buffer3ch = createConstantBuffer(context, 128, [1, 2, 3]); 62 let splitter = context.createChannelSplitter(3); 63 let sum = context.createGain(); 64 65 source.buffer = buffer3ch; 66 67 source.connect(splitter); 68 splitter.connect(sum, 0); 69 splitter.connect(sum, 1); 70 splitter.connect(sum, 2); 71 sum.connect(context.destination); 72 source.start(); 73 74 // This disconnects the second output. 75 splitter.disconnect(1); 76 77 context.startRendering() 78 .then(function(buffer) { 79 80 // The rendered channel should contain 4. (= 1 + 0 + 3) 81 should(buffer.getChannelData(0), 'Channel #0') 82 .beConstantValueOf(4); 83 84 }) 85 .then(() => task.done()); 86 }); 87 88 // Task 3: test disconnect(AudioNode) method. 89 audit.define('disconnect(AudioNode)', (task, should) => { 90 91 // Connect a source to multiple gain nodes. Then test if disconnecting a 92 // single destination selectively works correctly. 93 let context = new OfflineAudioContext(1, 128, 44100); 94 let source = context.createBufferSource(); 95 let buffer1ch = createConstantBuffer(context, 128, [1]); 96 let gain1 = context.createGain(); 97 let gain2 = context.createGain(); 98 let gain3 = context.createGain(); 99 let orphan = context.createGain(); 100 101 source.buffer = buffer1ch; 102 103 source.connect(gain1); 104 source.connect(gain2); 105 source.connect(gain3); 106 gain1.connect(context.destination); 107 gain2.connect(context.destination); 108 gain3.connect(context.destination); 109 source.start(); 110 111 source.disconnect(gain2); 112 113 context.startRendering() 114 .then(function(buffer) { 115 116 // The |sum| gain node should produce value 2. (1 + 0 + 1 = 2) 117 should(buffer.getChannelData(0), 'Channel #0') 118 .beConstantValueOf(2); 119 120 }) 121 .then(() => task.done()); 122 }); 123 124 // Task 4: test disconnect(AudioNode, output) method. 125 audit.define('disconnect(AudioNode, output)', (task, should) => { 126 127 // Connect a buffer with 2 channels with each containing 1 and 2 128 // respectively to a ChannelSplitter, then connect the splitter to 2 129 // gain nodes as shown below: 130 // (1) splitter#0 => gain1 131 // (2) splitter#0 => gain2 132 // (3) splitter#1 => gain2 133 // Then disconnect (2) and verify if the selective disconnection on a 134 // specified output of the destination node works correctly. 135 let context = new OfflineAudioContext(1, 128, 44100); 136 let source = context.createBufferSource(); 137 let buffer2ch = createConstantBuffer(context, 128, [1, 2]); 138 let splitter = context.createChannelSplitter(2); 139 let gain1 = context.createGain(); 140 let gain2 = context.createGain(); 141 142 source.buffer = buffer2ch; 143 144 source.connect(splitter); 145 splitter.connect(gain1, 0); // gain1 gets channel 0. 146 splitter.connect(gain2, 0); // gain2 sums channel 0 and 1. 147 splitter.connect(gain2, 1); 148 gain1.connect(context.destination); 149 gain2.connect(context.destination); 150 source.start(); 151 152 splitter.disconnect(gain2, 0); // Now gain2 gets [2] 153 154 context.startRendering() 155 .then(function(buffer) { 156 157 // The sum of gain1 and gain2 should produce value 3. (= 1 + 2) 158 should(buffer.getChannelData(0), 'Channel #0') 159 .beConstantValueOf(3); 160 161 }) 162 .then(() => task.done()); 163 }); 164 165 // Task 5: test disconnect(AudioNode, output, input) method. 166 audit.define('disconnect(AudioNode, output, input)', (task, should) => { 167 168 // Create a 3-channel buffer with [1, 2, 3] in each channel and then 169 // pass it through a splitter and a merger. Each input/output of the 170 // splitter and the merger is connected in a sequential order as shown 171 // below. 172 // (1) splitter#0 => merger#0 173 // (2) splitter#1 => merger#1 174 // (3) splitter#2 => merger#2 175 // Then disconnect (3) and verify if each channel contains [1] and [2] 176 // respectively. 177 let context = new OfflineAudioContext(3, 128, 44100); 178 let source = context.createBufferSource(); 179 let buffer3ch = createConstantBuffer(context, 128, [1, 2, 3]); 180 let splitter = context.createChannelSplitter(3); 181 let merger = context.createChannelMerger(3); 182 183 source.buffer = buffer3ch; 184 185 source.connect(splitter); 186 splitter.connect(merger, 0, 0); 187 splitter.connect(merger, 1, 1); 188 splitter.connect(merger, 2, 2); 189 merger.connect(context.destination); 190 source.start(); 191 192 splitter.disconnect(merger, 2, 2); 193 194 context.startRendering() 195 .then(function(buffer) { 196 197 // Each channel should have 1, 2, and 0 respectively. 198 should(buffer.getChannelData(0), 'Channel #0') 199 .beConstantValueOf(1); 200 should(buffer.getChannelData(1), 'Channel #1') 201 .beConstantValueOf(2); 202 should(buffer.getChannelData(2), 'Channel #2') 203 .beConstantValueOf(0); 204 205 }) 206 .then(() => task.done()); 207 }); 208 209 // Task 6: exception checks. 210 audit.define('exceptions', (task, should) => { 211 let context = new OfflineAudioContext(2, 128, 44100); 212 let gain1 = context.createGain(); 213 let splitter = context.createChannelSplitter(2); 214 let merger = context.createChannelMerger(2); 215 let gain2 = context.createGain(); 216 let gain3 = context.createGain(); 217 218 // Connect a splitter to gain nodes and merger so we can test the 219 // possible ways of disconnecting the nodes to verify that appropriate 220 // exceptions are thrown. 221 gain1.connect(splitter); 222 splitter.connect(gain2, 0); 223 splitter.connect(gain3, 1); 224 splitter.connect(merger, 0, 0); 225 splitter.connect(merger, 1, 1); 226 gain2.connect(gain3); 227 gain3.connect(context.destination); 228 merger.connect(context.destination); 229 230 // There is no output #2. An exception should be thrown. 231 should(function() { 232 splitter.disconnect(2); 233 }, 'splitter.disconnect(2)').throw(DOMException, 'IndexSizeError'); 234 235 // Disconnecting the output already disconnected should not throw. 236 should(function() { 237 splitter.disconnect(1); 238 splitter.disconnect(1); 239 }, 'Disconnecting a connection twice').notThrow(); 240 241 // gain1 is not connected gain2. An exception should be thrown. 242 should(function() { 243 gain1.disconnect(gain2); 244 }, 'gain1.disconnect(gain2)').throw(DOMException, 'InvalidAccessError'); 245 246 // gain1 and gain3 are not connected. An exception should be thrown. 247 should(function() { 248 gain1.disconnect(gain3); 249 }, 'gain1.disconnect(gain3)').throw(DOMException, 'InvalidAccessError'); 250 251 // There is no output #2 in the splitter. An exception should be thrown. 252 should(function() { 253 splitter.disconnect(gain2, 2); 254 }, 'splitter.disconnect(gain2, 2)').throw(DOMException, 'IndexSizeError'); 255 256 // The splitter and gain1 are not connected. An exception should be 257 // thrown. 258 should(function() { 259 splitter.disconnect(gain1, 0); 260 }, 'splitter.disconnect(gain1, 0)').throw(DOMException, 'InvalidAccessError'); 261 262 // The splitter output #0 and the gain3 output #0 are not connected. An 263 // exception should be thrown. 264 should(function() { 265 splitter.disconnect(gain3, 0, 0); 266 }, 'splitter.disconnect(gain3, 0, 0)').throw(DOMException, 'InvalidAccessError'); 267 268 // The output index is out of bound. An exception should be thrown. 269 should(function() { 270 splitter.disconnect(merger, 3, 0); 271 }, 'splitter.disconnect(merger, 3, 0)').throw(DOMException, 'IndexSizeError'); 272 273 task.done(); 274 }); 275 276 audit.define('disabled-outputs', (task, should) => { 277 // See crbug.com/656652 278 let context = new OfflineAudioContext(2, 1024, 44100); 279 let g1 = context.createGain(); 280 let g2 = context.createGain(); 281 g1.connect(g2); 282 g1.disconnect(g2); 283 let g3 = context.createGain(); 284 g2.connect(g3); 285 g1.connect(g2); 286 context.startRendering() 287 .then(function() { 288 // If we make it here, we passed. 289 should(true, 'Disabled outputs handled') 290 .message('correctly', 'inccorrectly'); 291 }) 292 .then(() => task.done()); 293 }); 294 295 audit.run(); 296 </script> 297 </body> 298 </html>