OLD | NEW |
(Empty) | |
| 1 <!doctype html> |
| 2 <html> |
| 3 <head> |
| 4 <title>Test Constructor: PeriodicWave</title> |
| 5 <script src="../../resources/testharness.js"></script> |
| 6 <script src="../../resources/testharnessreport.js"></script> |
| 7 <script src="../resources/audio-testing.js"></script> |
| 8 <script src="audionodeoptions.js"></script> |
| 9 </head> |
| 10 |
| 11 <body> |
| 12 <script> |
| 13 var context; |
| 14 |
| 15 var audit = Audit.createTaskRunner(); |
| 16 |
| 17 audit.defineTask("initialize", function (taskDone) { |
| 18 Should("context = new OfflineAudioContext(...)", function () { |
| 19 context = new OfflineAudioContext(1, 1, 48000); |
| 20 }).notThrow(); |
| 21 |
| 22 taskDone(); |
| 23 }); |
| 24 |
| 25 audit.defineTask("invalid constructor", function (taskDone) { |
| 26 var node; |
| 27 var success = true; |
| 28 |
| 29 success = Should("new PeriodicWave()", function () { |
| 30 node = new PeriodicWave(); |
| 31 }).throw("TypeError"); |
| 32 success = Should("new PeriodicWave(1)", function () { |
| 33 node = new PeriodicWave(1) && success; |
| 34 }).throw("TypeError"); |
| 35 success = Should("new PeriodicWave(context, 42)", function () { |
| 36 node = new PeriodicWave(context, 42) && success; |
| 37 }).throw("TypeError"); |
| 38 |
| 39 Should("Invalid constructors", success) |
| 40 .summarize( |
| 41 "correctly threw errors", |
| 42 "did not throw errors in all cases"); |
| 43 |
| 44 taskDone(); |
| 45 }); |
| 46 |
| 47 audit.defineTask("default constructor", function (taskDone) { |
| 48 var node; |
| 49 var success = true; |
| 50 |
| 51 success = Should("node = new PeriodicWave(context)", function () { |
| 52 node = new PeriodicWave(context); |
| 53 }).throw("InvalidStateError"); |
| 54 |
| 55 taskDone(); |
| 56 }); |
| 57 |
| 58 audit.defineTask("constructor with options", function (taskDone) { |
| 59 var node; |
| 60 var success = true; |
| 61 |
| 62 var options = { |
| 63 real: [1, 1] |
| 64 }; |
| 65 success = Should("node = new PeriodicWave(context, " + JSON.stringify(op
tions) + ")", |
| 66 function () { |
| 67 node = new PeriodicWave(context, options); |
| 68 }).notThrow(); |
| 69 success = Should("node instanceof PeriodicWave", node instanceof Periodi
cWave) |
| 70 .beEqualTo(true) && success; |
| 71 |
| 72 options = { |
| 73 imag: [1, 1] |
| 74 }; |
| 75 success = Should("node = new PeriodicWave(context, " + JSON.stringify(op
tions) + ")", |
| 76 function () { |
| 77 node = new PeriodicWave(context, options); |
| 78 }).notThrow(); |
| 79 success = Should("node instanceof PeriodicWave", node instanceof Periodi
cWave) |
| 80 .beEqualTo(true) && success; |
| 81 |
| 82 options = { |
| 83 real: [1, 2], |
| 84 imag: [1, 1] |
| 85 }; |
| 86 success = Should("node = new PeriodicWave(context, " + JSON.stringify(op
tions) + ")", |
| 87 function () { |
| 88 node = new PeriodicWave(context, options); |
| 89 }).notThrow(); |
| 90 success = Should("node instanceof PeriodicWave", node instanceof Periodi
cWave) |
| 91 .beEqualTo(true) && success; |
| 92 |
| 93 Should("new PeriodicWave() with options", success) |
| 94 .summarize( |
| 95 "constructed with correct attributes", |
| 96 "was not constructed correctly"); |
| 97 |
| 98 taskDone(); |
| 99 }); |
| 100 |
| 101 // The following test that the correct waveforms are produced when various |
| 102 // possible PeriodicWave options are used. These are needed because it's |
| 103 // the only way to tell if the various options were correctly applied. |
| 104 |
| 105 // TODO(rtoy): These functionality tests should be moved out to a separate |
| 106 // file. |
| 107 audit.defineTask("1: real periodicwave test", function (taskDone) { |
| 108 waveTest({ |
| 109 real: [0, 2] |
| 110 }, function (length, freq, sampleRate) { |
| 111 var expected = new Float32Array(length); |
| 112 var omega = 2 * Math.PI * freq / sampleRate; |
| 113 var normalizationFactor = 0.5; |
| 114 for (var k = 0; k < length; ++k) { |
| 115 expected[k] = Math.cos(omega * k); |
| 116 } |
| 117 return expected; |
| 118 }, |
| 119 2.7106e-5).then(taskDone); |
| 120 }); |
| 121 |
| 122 audit.defineTask("2: real periodicwave test", function (taskDone) { |
| 123 waveTest({ |
| 124 real: [0, 2], |
| 125 disableNormalization: false |
| 126 }, function (length, freq, sampleRate) { |
| 127 var expected = new Float32Array(length); |
| 128 var omega = 2 * Math.PI * freq / sampleRate; |
| 129 for (var k = 0; k < length; ++k) { |
| 130 expected[k] = Math.cos(omega * k); |
| 131 } |
| 132 return expected; |
| 133 }, |
| 134 2.7106e-5).then(taskDone); |
| 135 }), |
| 136 |
| 137 audit.defineTask("3: real periodicwave test", function (taskDone) { |
| 138 |
| 139 waveTest({ |
| 140 real: [0, 2], |
| 141 disableNormalization: true |
| 142 }, function (length, freq, sampleRate) { |
| 143 var expected = new Float32Array(length); |
| 144 var omega = 2 * Math.PI * freq / sampleRate; |
| 145 for (var k = 0; k < length; ++k) { |
| 146 expected[k] = 2 * Math.cos(omega * k); |
| 147 } |
| 148 return expected; |
| 149 }, |
| 150 5.4211e-5).then(taskDone); |
| 151 }); |
| 152 |
| 153 audit.defineTask("1: imag periodicwave test", function (taskDone) { |
| 154 waveTest({ |
| 155 imag: [0, 2] |
| 156 }, function (length, freq, sampleRate) { |
| 157 var expected = new Float32Array(length); |
| 158 var omega = 2 * Math.PI * freq / sampleRate; |
| 159 for (var k = 0; k < length; ++k) { |
| 160 expected[k] = Math.sin(omega * k); |
| 161 } |
| 162 return expected; |
| 163 }, |
| 164 2.7232e-5).then(taskDone); |
| 165 }); |
| 166 |
| 167 audit.defineTask("2: imag periodicwave test", function (taskDone) { |
| 168 waveTest({ |
| 169 imag: [0, 2], |
| 170 disableNormalization: false |
| 171 }, function (length, freq, sampleRate) { |
| 172 var expected = new Float32Array(length); |
| 173 var omega = 2 * Math.PI * freq / sampleRate; |
| 174 for (var k = 0; k < length; ++k) { |
| 175 expected[k] = Math.sin(omega * k); |
| 176 } |
| 177 return expected; |
| 178 }, |
| 179 2.7232e-5).then(taskDone); |
| 180 }); |
| 181 |
| 182 audit.defineTask("3: imag periodicwave test", function (taskDone) { |
| 183 waveTest({ |
| 184 imag: [0, 2], |
| 185 disableNormalization: true |
| 186 }, function (length, freq, sampleRate) { |
| 187 var expected = new Float32Array(length); |
| 188 var omega = 2 * Math.PI * freq / sampleRate; |
| 189 for (var k = 0; k < length; ++k) { |
| 190 expected[k] = 2 * Math.sin(omega * k); |
| 191 } |
| 192 return expected; |
| 193 }, |
| 194 5.4464e-5).then(taskDone); |
| 195 }); |
| 196 |
| 197 audit.defineTask("1: real/imag periodicwave test", function (taskDone) { |
| 198 waveTest({ |
| 199 real: [0, 1], |
| 200 imag: [0, 1], |
| 201 }, function (length, freq, sampleRate) { |
| 202 var expected = new Float32Array(length); |
| 203 var omega = 2 * Math.PI * freq / sampleRate; |
| 204 var normalizationFactor = Math.SQRT1_2; |
| 205 for (var k = 0; k < length; ++k) { |
| 206 expected[k] = normalizationFactor * (Math.sin(omega * k) + Math.co
s(omega * k)); |
| 207 } |
| 208 return expected; |
| 209 }, |
| 210 3.8371e-5).then(taskDone); |
| 211 }); |
| 212 |
| 213 audit.defineTask("2: real/imag periodicwave test", function (taskDone) { |
| 214 waveTest({ |
| 215 real: [0, 1], |
| 216 imag: [0, 1], |
| 217 disableNormalization: false |
| 218 }, function (length, freq, sampleRate) { |
| 219 var expected = new Float32Array(length); |
| 220 var omega = 2 * Math.PI * freq / sampleRate; |
| 221 var normalizationFactor = Math.SQRT1_2; |
| 222 for (var k = 0; k < length; ++k) { |
| 223 expected[k] = normalizationFactor * (Math.sin(omega * k) + Math.co
s(omega * k)); |
| 224 } |
| 225 return expected; |
| 226 }, |
| 227 2.7165e-5).then(taskDone); |
| 228 }); |
| 229 |
| 230 audit.defineTask("3: real/imag periodicwave test", function (taskDone) { |
| 231 waveTest({ |
| 232 real: [0, 1], |
| 233 imag: [0, 1], |
| 234 disableNormalization: true |
| 235 }, function (length, freq, sampleRate) { |
| 236 var expected = new Float32Array(length); |
| 237 var omega = 2 * Math.PI * freq / sampleRate; |
| 238 for (var k = 0; k < length; ++k) { |
| 239 expected[k] = Math.sin(omega * k) + Math.cos(omega * k); |
| 240 } |
| 241 return expected; |
| 242 }, |
| 243 3.8416e-5).then(taskDone); |
| 244 }); |
| 245 |
| 246 function waveTest(waveOptions, expectedFunction, threshold) { |
| 247 var node; |
| 248 var success = true; |
| 249 |
| 250 // Rather arbitrary sample rate and render length. Length doesn't have |
| 251 // to be very long. |
| 252 var sampleRate = 48000; |
| 253 var renderLength = 0.25; |
| 254 var testContext = new OfflineAudioContext(1, renderLength * sampleRate,
sampleRate); |
| 255 |
| 256 var options = { |
| 257 periodicWave: new PeriodicWave(testContext, waveOptions) |
| 258 }; |
| 259 node = new OscillatorNode(testContext, options); |
| 260 |
| 261 // Create the graph |
| 262 node.connect(testContext.destination); |
| 263 node.start(); |
| 264 |
| 265 return testContext.startRendering().then(function (resultBuffer) { |
| 266 var actual = resultBuffer.getChannelData(0); |
| 267 var expected = expectedFunction(actual.length, |
| 268 node.frequency.value, |
| 269 testContext.sampleRate); |
| 270 // Actual must match expected to within the (experimentally) |
| 271 // determined threshold. |
| 272 var message = ""; |
| 273 if (waveOptions.disableNormalization != undefined) |
| 274 message = "disableNormalization: " + waveOptions.disableNormalizatio
n; |
| 275 if (waveOptions.real) { |
| 276 if (message.length > 0) |
| 277 message += ", " |
| 278 message += "real: [" + waveOptions.real + "]"; |
| 279 } |
| 280 if (waveOptions.imag) { |
| 281 if (message.length > 0) |
| 282 message += ", " |
| 283 message += "imag: [" + waveOptions.imag + "]"; |
| 284 } |
| 285 Should("Oscillator with periodicWave {" + message + "}", actual) |
| 286 .beCloseToArray(expected, threshold); |
| 287 }); |
| 288 } |
| 289 |
| 290 audit.runTasks(); |
| 291 </script> |
| 292 </body> |
| 293 </html> |
OLD | NEW |