| OLD | NEW |
| 1 <!doctype html> | 1 <!DOCTYPE html> |
| 2 <html> | 2 <html> |
| 3 <head> | 3 <head> |
| 4 <title> |
| 5 Handle Silent Inputs to AnalyserNode |
| 6 </title> |
| 4 <script src="../../resources/testharness.js"></script> | 7 <script src="../../resources/testharness.js"></script> |
| 5 <script src="../../resources/testharnessreport.js"></script> | 8 <script src="../../resources/testharnessreport.js"></script> |
| 6 <script src="../resources/audit-util.js"></script> | 9 <script src="../resources/audit-util.js"></script> |
| 7 <script src="../resources/audit.js"></script> | 10 <script src="../resources/audit.js"></script> |
| 8 <title>Handle Silent Inputs to AnalyserNode</title> | |
| 9 </head> | 11 </head> |
| 10 | |
| 11 <body> | 12 <body> |
| 12 <script> | 13 <script id="layout-test-code"> |
| 13 let audit = Audit.createTaskRunner(); | 14 let audit = Audit.createTaskRunner(); |
| 14 let sampleRate = 16000; | 15 let sampleRate = 16000; |
| 15 let renderDuration = 1; | 16 let renderDuration = 1; |
| 16 let renderFrames = renderDuration * sampleRate; | 17 let renderFrames = renderDuration * sampleRate; |
| 17 | 18 |
| 18 audit.define({ | 19 audit.define( |
| 19 label: 'connected', | 20 {label: 'connected', description: 'Test handling of silent inputs'}, |
| 20 description: 'Test handling of silent inputs' | 21 function(task, should) { |
| 21 }, function (task, should) { | 22 tester(should, false, '0').then(task.done.bind(task)); |
| 22 tester(should, false, '0').then(task.done.bind(task)); | 23 }); |
| 23 }); | |
| 24 | 24 |
| 25 audit.define({ | 25 audit.define( |
| 26 label: 'auto-pull', | 26 {label: 'auto-pull', description: 'Test handling of silent inputs'}, |
| 27 description: 'Test handling of silent inputs' | 27 function(task, should) { |
| 28 }, function(task, should) { | 28 tester(should, true, '1').then(task.done.bind(task)); |
| 29 tester(should, true, '1').then(task.done.bind(task)); | 29 }); |
| 30 }); | |
| 31 | 30 |
| 32 audit.define({ | 31 audit.define( |
| 33 label: 'timing', | 32 { |
| 34 description: 'Test shifting in of zeroes after source has stopped' | 33 label: 'timing', |
| 35 }, function(task, should) { | 34 description: 'Test shifting in of zeroes after source has stopped' |
| 36 let renderQuantumFrames = 128; | 35 }, |
| 36 function(task, should) { |
| 37 let renderQuantumFrames = 128; |
| 37 | 38 |
| 38 // sampleRate chosen to be a power of two so we don't have round-off | 39 // sampleRate chosen to be a power of two so we don't have round-off |
| 39 // errors in computing the times for when to suspend the context. | 40 // errors in computing the times for when to suspend the context. |
| 40 let context = new OfflineAudioContext(1, 16384, 16384); | 41 let context = new OfflineAudioContext(1, 16384, 16384); |
| 41 let source = new ConstantSourceNode(context); | 42 let source = new ConstantSourceNode(context); |
| 42 | 43 |
| 43 // The fftSize for the analyser is fairly arbitrary, except the code | 44 // The fftSize for the analyser is fairly arbitrary, except the code |
| 44 // assumes it is larger than 128. | 45 // assumes it is larger than 128. |
| 45 let analyser = new AnalyserNode(context, {fftSize: 2048}); | 46 let analyser = new AnalyserNode(context, {fftSize: 2048}); |
| 46 | 47 |
| 47 source.connect(analyser).connect(context.destination); | 48 source.connect(analyser).connect(context.destination); |
| 48 | 49 |
| 49 source.start(); | 50 source.start(); |
| 50 | 51 |
| 51 // Stop the source after 1 fftSize frames. | 52 // Stop the source after 1 fftSize frames. |
| 52 let time = analyser.fftSize / context.sampleRate; | 53 let time = analyser.fftSize / context.sampleRate; |
| 53 source.stop(time); | 54 source.stop(time); |
| 54 | 55 |
| 55 // Verify that the time data at this point is constant. | 56 // Verify that the time data at this point is constant. |
| 56 context.suspend(time) | 57 context.suspend(time) |
| 57 .then(() => { | 58 .then(() => { |
| 58 let data = new Float32Array(analyser.fftSize); | 59 let data = new Float32Array(analyser.fftSize); |
| 59 analyser.getFloatTimeDomainData(data); | 60 analyser.getFloatTimeDomainData(data); |
| 60 should( | 61 should( |
| 61 data, 'At time ' + context.currentTime + | 62 data, |
| 62 ' Analyser frames [0, ' + analyser.fftSize + ')') | 63 'At time ' + context.currentTime + |
| 63 .beConstantValueOf(1); | 64 ' Analyser frames [0, ' + analyser.fftSize + ')') |
| 64 }) | 65 .beConstantValueOf(1); |
| 65 .then(context.resume.bind(context)); | 66 }) |
| 67 .then(context.resume.bind(context)); |
| 66 | 68 |
| 67 // After each rendering quantum from the point at which the source | 69 // After each rendering quantum from the point at which the source |
| 68 // stopped, verify that zeroes are inserted into the time data one | 70 // stopped, verify that zeroes are inserted into the time data one |
| 69 // rendering quantum at a time. | 71 // rendering quantum at a time. |
| 70 | 72 |
| 71 let limit = analyser.fftSize / renderQuantumFrames; | 73 let limit = analyser.fftSize / renderQuantumFrames; |
| 72 | 74 |
| 73 for (let k = 1; k <= limit; ++k) { | 75 for (let k = 1; k <= limit; ++k) { |
| 74 let analyserTime = | 76 let analyserTime = (analyser.fftSize + k * renderQuantumFrames) / |
| 75 (analyser.fftSize + k * renderQuantumFrames) / context.sampleRate; | 77 context.sampleRate; |
| 76 context.suspend(analyserTime) | 78 context.suspend(analyserTime) |
| 77 .then(() => { | 79 .then(() => { |
| 78 let data = new Float32Array(analyser.fftSize); | 80 let data = new Float32Array(analyser.fftSize); |
| 79 let indexNewest = analyser.fftSize - k * renderQuantumFrames; | 81 let indexNewest = |
| 80 analyser.getFloatTimeDomainData(data); | 82 analyser.fftSize - k * renderQuantumFrames; |
| 81 if (k < limit) { | 83 analyser.getFloatTimeDomainData(data); |
| 82 should( | 84 if (k < limit) { |
| 83 data.slice(0, indexNewest), 'At time ' + | 85 should( |
| 84 context.currentTime + ' Analyser frames [0, ' + | 86 data.slice(0, indexNewest), |
| 85 indexNewest + ')') | 87 'At time ' + context.currentTime + |
| 86 .beConstantValueOf(1); | 88 ' Analyser frames [0, ' + indexNewest + ')') |
| 87 } | 89 .beConstantValueOf(1); |
| 88 should( | 90 } |
| 89 data.slice(indexNewest), 'At time ' + context.currentTime + | 91 should( |
| 90 ' Analyser frames [' + indexNewest + ', ' + | 92 data.slice(indexNewest), |
| 91 analyser.fftSize + ')') | 93 'At time ' + context.currentTime + |
| 92 .beConstantValueOf(0); | 94 ' Analyser frames [' + indexNewest + ', ' + |
| 93 }) | 95 analyser.fftSize + ')') |
| 94 .then(context.resume.bind(context)); | 96 .beConstantValueOf(0); |
| 95 } | 97 }) |
| 98 .then(context.resume.bind(context)); |
| 99 } |
| 96 | 100 |
| 97 // Start the test | 101 // Start the test |
| 98 context.startRendering().then(() => task.done()); | 102 context.startRendering().then(() => task.done()); |
| 99 }); | 103 }); |
| 100 | 104 |
| 101 audit.run(); | 105 audit.run(); |
| 102 | 106 |
| 103 function tester(should, isAutoPullTest, prefix) { | 107 function tester(should, isAutoPullTest, prefix) { |
| 104 // Connect an oscillator to an analyser for testing the time data of the | 108 // Connect an oscillator to an analyser for testing the time data of the |
| 105 // analyser after the oscillator stops. | 109 // analyser after the oscillator stops. |
| 106 let context = new OfflineAudioContext(1, renderFrames, sampleRate); | 110 let context = new OfflineAudioContext(1, renderFrames, sampleRate); |
| 107 let source = new OscillatorNode(context); | 111 let source = new OscillatorNode(context); |
| 108 let analyser = new AnalyserNode(context, {fftSize: 128}); | 112 let analyser = new AnalyserNode(context, {fftSize: 128}); |
| 109 let timeData = new Float32Array(analyser.fftSize); | 113 let timeData = new Float32Array(analyser.fftSize); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 120 | 124 |
| 121 source.start(); | 125 source.start(); |
| 122 | 126 |
| 123 // Stop the source well in advance of when we want to get the time data | 127 // Stop the source well in advance of when we want to get the time data |
| 124 // from the analyser. | 128 // from the analyser. |
| 125 let stopTime = 0.1; | 129 let stopTime = 0.1; |
| 126 let dataTime = 0.5; | 130 let dataTime = 0.5; |
| 127 | 131 |
| 128 source.stop(stopTime); | 132 source.stop(stopTime); |
| 129 context.suspend(dataTime) | 133 context.suspend(dataTime) |
| 130 .then(() => { analyser.getFloatTimeDomainData(timeData); }) | 134 .then(() => { |
| 135 analyser.getFloatTimeDomainData(timeData); |
| 136 }) |
| 131 .then(context.resume.bind(context)); | 137 .then(context.resume.bind(context)); |
| 132 | 138 |
| 133 return context.startRendering().then(buffer => { | 139 return context.startRendering().then(buffer => { |
| 134 should(timeData, prefix + ': Analyser time data at time ' + dataTime) | 140 should(timeData, prefix + ': Analyser time data at time ' + dataTime) |
| 135 .beConstantValueOf(0); | 141 .beConstantValueOf(0); |
| 136 }); | 142 }); |
| 137 } | 143 } |
| 138 </script> | 144 </script> |
| 139 </body> | 145 </body> |
| 140 </html> | 146 </html> |
| OLD | NEW |