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 |