test-analyser-resume-after-suspended.html (3108B)
1 <!doctype html> 2 <meta name="timeout" content="long"> 3 <title>AnalyzerNode resumed after suspended</title> 4 <script src=/resources/testharness.js></script> 5 <script src=/resources/testharnessreport.js></script> 6 <script> 7 8 function areFloat32ArraysEqual(arr1, arr2) { 9 if (arr1.length !== arr2.length) { 10 return false; 11 } 12 13 for (let i = 0; i < arr1.length; i++) { 14 if (arr1[i] !== arr2[i]) { 15 return false; 16 } 17 } 18 19 return true; 20 } 21 22 // This test ensures that calling suspend() does not clear or reset 23 // the AnalyserNode, and that after resuming the AudioContext, 24 // it continues retrieving valid data without any interruptions. 25 promise_test(async () => { 26 function runTest(resolve) { 27 const context = new AudioContext(); 28 context.suspend(); 29 30 const oscillator = new OscillatorNode(context); 31 oscillator.connect(context.destination); 32 oscillator.start(); 33 34 const analyser = new AnalyserNode(context); 35 oscillator.connect(analyser); 36 37 let analyserReadCount = 0; 38 let lastTime = 0; 39 // Time between checks in milliseconds. 40 const interval = 300; 41 42 let previousTimeDomainDataArray = 43 new Float32Array(analyser.frequencyBinCount); 44 45 // The analyser.getFloatTimeDomainData() is called every 300 ms under 46 // suspended or resumed state. If it is a suspended state, the value 47 // from the function should be the same as the previous value. If 48 // it is a resumed state, the value should be different. 49 async function readAnalyserData(timestamp) { 50 if (lastTime === 0) { 51 lastTime = timestamp; 52 } 53 54 const elapsed = timestamp - lastTime; 55 56 // Only run the readAnalyserData every 300ms in order to give enough time 57 // for context to pull the data. 58 if (elapsed >= interval) { 59 analyserReadCount++; 60 61 let shouldSkipAsserts = false; 62 switch (analyserReadCount) { 63 case 1: 64 shouldSkipAsserts = true; 65 break; 66 case 10: 67 await context.suspend(); 68 shouldSkipAsserts = true; 69 break; 70 case 5: 71 case 15: 72 await context.resume(); 73 shouldSkipAsserts = true; 74 break; 75 case 20: 76 oscillator.stop(); 77 resolve(); 78 break; 79 default: 80 break; 81 } 82 83 const timeDomainDataArray = 84 new Float32Array(analyser.frequencyBinCount); 85 analyser.getFloatTimeDomainData(timeDomainDataArray); 86 87 if (!shouldSkipAsserts) { 88 let result = areFloat32ArraysEqual(timeDomainDataArray, 89 previousTimeDomainDataArray); 90 context.state === 'suspended' ? assert_true(result) 91 : assert_false(result); 92 } 93 94 previousTimeDomainDataArray.set(timeDomainDataArray); 95 lastTime = timestamp; 96 } 97 98 requestAnimationFrame(readAnalyserData); 99 } 100 101 requestAnimationFrame(readAnalyserData); 102 } 103 104 return new Promise((resolve) => runTest(resolve)); 105 }, 'AnalyserNode resume after suspended'); 106 </script>