OLD | NEW |
1 var sampleRate = 44100.0; | 1 var sampleRate = 44100.0; |
2 | 2 |
3 // How many panner nodes to create for the test. | 3 // How many panner nodes to create for the test. |
4 var nodesToCreate = 100; | 4 var nodesToCreate = 100; |
5 | 5 |
6 // Time step when each panner node starts. | 6 // Time step when each panner node starts. |
7 var timeStep = 0.001; | 7 var timeStep = 0.001; |
8 | 8 |
9 // Make sure we render long enough to get all of our nodes. | 9 // Make sure we render long enough to get all of our nodes. |
10 var renderLengthSeconds = timeStep * (nodesToCreate + 1); | 10 var renderLengthSeconds = timeStep * (nodesToCreate + 1); |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
94 bufferSource[k].connect(panner[k]); | 94 bufferSource[k].connect(panner[k]); |
95 panner[k].connect(context.destination); | 95 panner[k].connect(context.destination); |
96 | 96 |
97 time[k] = k * timeStep; | 97 time[k] = k * timeStep; |
98 bufferSource[k].start(time[k]); | 98 bufferSource[k].start(time[k]); |
99 } | 99 } |
100 } | 100 } |
101 | 101 |
102 // distanceModel should be the distance model string like | 102 // distanceModel should be the distance model string like |
103 // "linear", "inverse", or "exponential". | 103 // "linear", "inverse", or "exponential". |
104 function createTestAndRun(context, distanceModel) { | 104 function createTestAndRun(context, distanceModel, should) { |
105 // To test the distance models, we create a number of panners at | 105 // To test the distance models, we create a number of panners at |
106 // uniformly spaced intervals on the z-axis. Each of these are | 106 // uniformly spaced intervals on the z-axis. Each of these are |
107 // started at equally spaced time intervals. After rendering the | 107 // started at equally spaced time intervals. After rendering the |
108 // signals, we examine where each impulse is located and the | 108 // signals, we examine where each impulse is located and the |
109 // attenuation of the impulse. The attenuation is compared | 109 // attenuation of the impulse. The attenuation is compared |
110 // against our expected attenuation. | 110 // against our expected attenuation. |
111 | 111 |
112 createGraph(context, distanceModel, nodesToCreate); | 112 createGraph(context, distanceModel, nodesToCreate); |
113 | 113 |
114 context.oncomplete = checkDistanceResult(distanceModel); | 114 return context.startRendering() |
115 context.startRendering(); | 115 .then(buffer => checkDistanceResult(buffer, distanceModel, should)); |
116 } | 116 } |
117 | 117 |
118 // The gain caused by the EQUALPOWER panning model, if we stay on the | 118 // The gain caused by the EQUALPOWER panning model, if we stay on the |
119 // z axis, with the default orientations. | 119 // z axis, with the default orientations. |
120 function equalPowerGain() { | 120 function equalPowerGain() { |
121 return Math.SQRT1_2; | 121 return Math.SQRT1_2; |
122 } | 122 } |
123 | 123 |
124 function checkDistanceResult(model) { | 124 function checkDistanceResult(renderedBuffer, model, should) { |
125 return function(event) { | 125 renderedData = renderedBuffer.getChannelData(0); |
126 renderedBuffer = event.renderedBuffer; | |
127 renderedData = renderedBuffer.getChannelData(0); | |
128 | 126 |
129 // The max allowed error between the actual gain and the expected | 127 // The max allowed error between the actual gain and the expected |
130 // value. This is determined experimentally. Set to 0 to see what | 128 // value. This is determined experimentally. Set to 0 to see |
131 // the actual errors are. | 129 // what the actual errors are. |
132 var maxAllowedError = 3.3e-6; | 130 var maxAllowedError = 3.3e-6; |
133 | 131 |
134 var success = true; | 132 var success = true; |
135 | 133 |
136 // Number of impulses we found in the rendered result. | 134 // Number of impulses we found in the rendered result. |
137 var impulseCount = 0; | 135 var impulseCount = 0; |
138 | 136 |
139 // Maximum relative error in the gain of the impulses. | 137 // Maximum relative error in the gain of the impulses. |
140 var maxError = 0; | 138 var maxError = 0; |
141 | 139 |
142 // Array of locations of the impulses that were not at the | 140 // Array of locations of the impulses that were not at the |
143 // expected location. (Contains the actual and expected frame | 141 // expected location. (Contains the actual and expected frame |
144 // of the impulse.) | 142 // of the impulse.) |
145 var impulsePositionErrors = new Array(); | 143 var impulsePositionErrors = new Array(); |
146 | 144 |
147 // Step through the rendered data to find all the non-zero points | 145 // Step through the rendered data to find all the non-zero points |
148 // so we can find where our distance-attenuated impulses are. | 146 // so we can find where our distance-attenuated impulses are. |
149 // These are tested against the expected attenuations at that | 147 // These are tested against the expected attenuations at that |
150 // distance. | 148 // distance. |
151 for (var k = 0; k < renderedData.length; ++k) { | 149 for (var k = 0; k < renderedData.length; ++k) { |
152 if (renderedData[k] != 0) { | 150 if (renderedData[k] != 0) { |
153 // Convert from string to index. | 151 // Convert from string to index. |
154 var distanceFunction = distanceModelFunction[model]; | 152 var distanceFunction = distanceModelFunction[model]; |
155 var expected = distanceFunction(panner[impulseCount], 0, 0, posi
tion[impulseCount]); | 153 var expected = |
| 154 distanceFunction(panner[impulseCount], 0, 0, |
| 155 position[impulseCount]); |
156 | 156 |
157 // Adjust for the center-panning of the EQUALPOWER panning | 157 // Adjust for the center-panning of the EQUALPOWER panning |
158 // model that we're using. | 158 // model that we're using. |
159 expected *= equalPowerGain(); | 159 expected *= equalPowerGain(); |
160 | 160 |
161 var error = Math.abs(renderedData[k] - expected) / Math.abs(expe
cted); | 161 var error = |
| 162 Math.abs(renderedData[k] - expected) / Math.abs(expected); |
162 | 163 |
163 maxError = Math.max(maxError, Math.abs(error)); | 164 maxError = Math.max(maxError, Math.abs(error)); |
164 | 165 |
165 // Keep track of any impulses that aren't where we expect them | 166 // Keep track of any impulses that aren't where we expect them |
166 // to be. | 167 // to be. |
167 var expectedOffset = timeToSampleFrame(time[impulseCount], sampl
eRate); | 168 var expectedOffset = timeToSampleFrame(time[impulseCount], |
168 if (k != expectedOffset) { | 169 sampleRate); |
169 impulsePositionErrors.push({ actual : k, expected : expected
Offset}); | 170 if (k != expectedOffset) { |
170 } | 171 impulsePositionErrors.push({ |
171 ++impulseCount; | 172 actual: k, |
| 173 expected: expectedOffset |
| 174 }); |
172 } | 175 } |
| 176 ++impulseCount; |
173 } | 177 } |
| 178 } |
| 179 should(impulseCount, "Number of impulses") |
| 180 .beEqualTo(nodesToCreate); |
174 | 181 |
175 if (impulseCount == nodesToCreate) { | 182 should(maxError, "Max error in distance gains") |
176 testPassed("Number of impulses found matches number of panner nodes.
"); | 183 .beLessThanOrEqualTo(maxAllowedError); |
177 } else { | |
178 testFailed("Number of impulses is incorrect. Found " + impulseCount
+ " but expected " + nodesToCreate + "."); | |
179 success = false; | |
180 } | |
181 | 184 |
182 if (maxError <= maxAllowedError) { | 185 // Display any timing errors that we found. |
183 testPassed("Distance gains are correct."); | 186 if (impulsePositionErrors.length > 0) { |
184 } else { | 187 let actual = impulsePositionErrors.map(x => x.actual); |
185 testFailed("Distance gains are incorrect. Max rel error = " + maxEr
ror + " (maxAllowedError = " + maxAllowedError + ")"); | 188 let expected = impulsePositionErrors.map(x => x.expected); |
186 success = false; | 189 should(actual, "Actual impulse positions found") |
187 } | 190 .beEqualToArray(expected); |
188 | |
189 // Display any timing errors that we found. | |
190 if (impulsePositionErrors.length > 0) { | |
191 success = false; | |
192 testFailed(impulsePositionErrors.length + " timing errors found"); | |
193 for (var k = 0; k < impulsePositionErrors.length; ++k) { | |
194 testFailed("Sample at frame " + impulsePositionErrors[k].actual
+ " but expected " + impulsePositionErrors[k].expected); | |
195 } | |
196 } | |
197 | |
198 if (success) { | |
199 testPassed("Distance test passed for distance model " + model); | |
200 } else { | |
201 testFailed("Distance test failed for distance model " + model); | |
202 } | |
203 | |
204 finishJSTest(); | |
205 } | 191 } |
206 } | 192 } |
OLD | NEW |