| OLD | NEW |
| (Empty) |
| 1 <!DOCTYPE html> | |
| 2 | |
| 3 <html> | |
| 4 <head> | |
| 5 <script src="../resources/js-test.js"></script> | |
| 6 <script src="resources/compatibility.js"></script> | |
| 7 <script src="resources/audit-util.js"></script> | |
| 8 <script src="resources/audio-testing.js"></script> | |
| 9 <script type="text/javascript" src="resources/buffer-loader.js"></script> | |
| 10 </head> | |
| 11 | |
| 12 <body> | |
| 13 | |
| 14 <div id="description"></div> | |
| 15 <div id="console"></div> | |
| 16 | |
| 17 <script> | |
| 18 description("Tests that WaveShaperNode applies proper non-linear distortion."); | |
| 19 | |
| 20 var sampleRate = 44100; | |
| 21 var lengthInSeconds = 4; | |
| 22 var numberOfRenderFrames = sampleRate * lengthInSeconds; | |
| 23 var numberOfCurveFrames = 65536; | |
| 24 var inputBuffer; | |
| 25 var waveShapingCurve; | |
| 26 | |
| 27 var context; | |
| 28 | |
| 29 function generateInputBuffer() { | |
| 30 // Create mono input buffer. | |
| 31 var buffer = context.createBuffer(1, numberOfRenderFrames, context.sampleRat
e); | |
| 32 var data = buffer.getChannelData(0); | |
| 33 | |
| 34 // Generate an input vector with values from -1 -> +1 over a duration of len
gthInSeconds. | |
| 35 // This exercises the full nominal input range and will touch every point of
the shaping curve. | |
| 36 for (var i = 0; i < numberOfRenderFrames; ++i) { | |
| 37 var x = i / numberOfRenderFrames; // 0 -> 1 | |
| 38 x = 2 * x - 1; // -1 -> +1 | |
| 39 data[i] = x; | |
| 40 } | |
| 41 | |
| 42 return buffer; | |
| 43 } | |
| 44 | |
| 45 // Generates a symmetric curve: Math.atan(5 * x) / (0.5 * Math.PI) | |
| 46 // (with x == 0 corresponding to the center of the array) | |
| 47 // This curve is arbitrary, but would be useful in the real-world. | |
| 48 // To some extent, the actual curve we choose is not important in this test, | |
| 49 // since the input vector walks through all possible curve values. | |
| 50 function generateWaveShapingCurve() { | |
| 51 var curve = new Float32Array(numberOfCurveFrames); | |
| 52 | |
| 53 var n = numberOfCurveFrames; | |
| 54 var n2 = n / 2; | |
| 55 | |
| 56 for (var i = 0; i < n; ++i) { | |
| 57 var x = (i - n2) / n2; | |
| 58 var y = Math.atan(5 * x) / (0.5 * Math.PI); | |
| 59 } | |
| 60 | |
| 61 return curve; | |
| 62 } | |
| 63 | |
| 64 function checkShapedCurve(event) { | |
| 65 var buffer = event.renderedBuffer; | |
| 66 | |
| 67 var inputData = inputBuffer.getChannelData(0); | |
| 68 var outputData = buffer.getChannelData(0); | |
| 69 | |
| 70 var success = true; | |
| 71 | |
| 72 // Go through every sample and make sure it has been shaped exactly accordin
g to the shaping curve we gave it. | |
| 73 for (var i = 0; i < buffer.length; ++i) { | |
| 74 var input = inputData[i]; | |
| 75 | |
| 76 // Calculate an index based on input -1 -> +1 with 0 being at the center
of the curve data. | |
| 77 var index = Math.floor(numberOfCurveFrames * 0.5 * (input + 1)); | |
| 78 | |
| 79 // Clip index to the input range of the curve. | |
| 80 // This takes care of input outside of nominal range -1 -> +1 | |
| 81 index = index < 0 ? 0 : index; | |
| 82 index = index > numberOfCurveFrames - 1 ? numberOfCurveFrames - 1 : inde
x; | |
| 83 | |
| 84 var expectedOutput = waveShapingCurve[index]; | |
| 85 | |
| 86 var output = outputData[i]; | |
| 87 | |
| 88 if (output != expectedOutput) { | |
| 89 success = false; | |
| 90 break; | |
| 91 } | |
| 92 } | |
| 93 | |
| 94 if (success) { | |
| 95 testPassed("WaveShaperNode properly applied non-linear distortion."); | |
| 96 } else { | |
| 97 testFailed("WaveShaperNode did not properly apply non-linear distortion.
"); | |
| 98 } | |
| 99 | |
| 100 finishJSTest(); | |
| 101 } | |
| 102 | |
| 103 function runTest() { | |
| 104 if (window.testRunner) { | |
| 105 testRunner.dumpAsText(); | |
| 106 testRunner.waitUntilDone(); | |
| 107 } | |
| 108 | |
| 109 window.jsTestIsAsync = true; | |
| 110 | |
| 111 // Create offline audio context. | |
| 112 context = new OfflineAudioContext(1, numberOfRenderFrames, sampleRate); | |
| 113 | |
| 114 // source -> waveshaper -> destination | |
| 115 var source = context.createBufferSource(); | |
| 116 var waveshaper = context.createWaveShaper(); | |
| 117 source.connect(waveshaper); | |
| 118 waveshaper.connect(context.destination); | |
| 119 | |
| 120 // Create an input test vector. | |
| 121 inputBuffer = generateInputBuffer(); | |
| 122 source.buffer = inputBuffer; | |
| 123 | |
| 124 // We'll apply non-linear distortion according to this shaping curve. | |
| 125 waveShapingCurve = generateWaveShapingCurve(); | |
| 126 waveshaper.curve = waveShapingCurve; | |
| 127 | |
| 128 source.start(0); | |
| 129 | |
| 130 context.oncomplete = checkShapedCurve; | |
| 131 context.startRendering(); | |
| 132 } | |
| 133 | |
| 134 runTest(); | |
| 135 | |
| 136 </script> | |
| 137 | |
| 138 </body> | |
| 139 </html> | |
| OLD | NEW |