test_delayNodeTailWithReconnect.html (3660B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <title>Test tail time lifetime of DelayNode after input finishes and new input added</title> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <script type="text/javascript" src="webaudio.js"></script> 7 <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> 8 </head> 9 <body> 10 <pre id="test"> 11 <script class="testbody" type="text/javascript"> 12 13 SimpleTest.waitForExplicitFinish(); 14 15 // The buffer source will start on a block boundary, so keeping the signal 16 // within one block ensures that it will not cross AudioProcessingEvent buffer 17 // boundaries. 18 const signalLength = 128; 19 const bufferSize = 1024; 20 // Delay should be long enough to allow CC to run 21 var delayBufferCount = 50; 22 var delayBufferOffset; 23 const delayLength = delayBufferCount * bufferSize; 24 25 var phase = "initial"; 26 var sourceCount = 0; 27 var delayCount = 0; 28 var oscillator; 29 var delay; 30 var source; 31 32 function applySignal(buffer, offset) { 33 for (var i = 0; i < signalLength; ++i) { 34 buffer.getChannelData(0)[offset + i] = Math.cos(Math.PI * i / signalLength); 35 } 36 } 37 38 function bufferIsSilent(buffer, out) { 39 for (var i = 0; i < buffer.length; ++i) { 40 if (buffer.getChannelData(0)[i] != 0) { 41 if (out) { 42 out.soundOffset = i; 43 } 44 return false; 45 } 46 } 47 return true; 48 } 49 50 function onDelayOutput(e) { 51 switch(phase) { 52 53 case "initial": 54 // Wait for oscillator sound to exit delay 55 if (bufferIsSilent(e.inputBuffer)) 56 break; 57 58 phase = "played oscillator"; 59 break; 60 61 case "played oscillator": 62 // First tail time has expired. Start second source and remove references 63 // to the delay and connected second source. 64 oscillator.disconnect(); 65 source.connect(delay); 66 source.start(); 67 source = null; 68 delay = null; 69 phase = "started second source"; 70 break; 71 72 case "second tail time": 73 if (delayCount == delayBufferCount) { 74 var ctx = e.target.context; 75 var expected = ctx.createBuffer(1, bufferSize, ctx.sampleRate); 76 applySignal(expected, delayBufferOffset); 77 compareBuffers(e.inputBuffer, expected); 78 e.target.onaudioprocess = null; 79 SimpleTest.finish(); 80 } 81 } 82 83 delayCount++; 84 } 85 86 function onSourceOutput(e) { 87 switch(phase) { 88 case "started second source": 89 var out = {}; 90 if (!bufferIsSilent(e.inputBuffer, out)) { 91 delayBufferCount += sourceCount; 92 delayBufferOffset = out.soundOffset; 93 phase = "played second source"; 94 } 95 break; 96 case "played second source": 97 SpecialPowers.forceGC(); 98 SpecialPowers.forceCC(); 99 phase = "second tail time"; 100 e.target.onaudioprocess = null; 101 } 102 103 sourceCount++; 104 } 105 106 function startTest() { 107 var ctx = new AudioContext(); 108 var delayDuration = delayLength / ctx.sampleRate; 109 delay = ctx.createDelay(delayDuration); 110 delay.delayTime.value = delayDuration; 111 var processor1 = ctx.createScriptProcessor(bufferSize, 1, 0); 112 delay.connect(processor1); 113 processor1.onaudioprocess = onDelayOutput; 114 115 // Signal to trigger initial tail time reference 116 oscillator = ctx.createOscillator(); 117 oscillator.start(0); 118 oscillator.stop(100/ctx.sampleRate); 119 oscillator.connect(delay); 120 121 // Short signal, not started yet, with a ScriptProcessor to detect when it 122 // starts. It should finish before garbage collection. 123 var buffer = ctx.createBuffer(1, signalLength, ctx.sampleRate); 124 applySignal(buffer, 0); 125 source = ctx.createBufferSource(); 126 source.buffer = buffer; 127 var processor2 = ctx.createScriptProcessor(bufferSize, 1, 0); 128 source.connect(processor2); 129 processor2.onaudioprocess = onSourceOutput; 130 }; 131 132 startTest(); 133 </script> 134 </pre> 135 </body> 136 </html>