curve-tests.html (8699B)
1 <!doctype html> 2 <html> 3 <head> 4 <title>WaveShaperNode interface - Curve tests | WebAudio</title> 5 6 <script type="text/javascript" src="/resources/testharness.js"></script> 7 <script type="text/javascript" src="/resources/testharnessreport.js"></script> 8 </head> 9 <body> 10 <div id="log"> 11 </div> 12 13 <script type="text/javascript"> 14 var sampleRate=44100.0; 15 var tolerance=0.01; 16 17 /* 18 Testing that -1, 0 and +1 map correctly to curve (with 1:1 correlation) 19 ======================================================================= 20 From the specification: 21 The input signal is nominally within the range -1 -> +1. 22 Each input sample within this range will index into the shaping curve with a signal level of zero corresponding 23 to the center value of the curve array. 24 */ 25 (function() { 26 var threeElementCurve=[2.0, -3.0, 4.0]; 27 var inputData=[-1.0, 0, 1.0]; 28 var expectedData=[2.0, -3.0, 4.0]; 29 executeTest(threeElementCurve, inputData, expectedData, "Testing that -1, 0 and +1 map correctly to curve (with 1:1 correlation)"); 30 })(); 31 32 /* 33 Testing interpolation (where inputs don't correlate directly to curve elements) 34 =============================================================================== 35 From the specification: 36 The implementation must perform linear interpolation between adjacent points in the curve. 37 */ 38 (function() { 39 var threeElementCurve=[2.0, -3.0, 4.0]; 40 var inputData=[-0.5, +0.5, +0.75]; 41 var expectedData=[-0.5, +0.5, +2.25]; 42 executeTest(threeElementCurve, inputData, expectedData, "Testing interpolation (where inputs don't correlate directly to curve elements)"); 43 })(); 44 45 /* 46 Testing out-of-range inputs (should be mapped to the first/last elements of the curve) 47 ====================================================================================== 48 From the specification: 49 Any sample value less than -1 will correspond to the first value in the curve array. 50 Any sample value greater than +1 will correspond to the last value in the curve array. 51 */ 52 (function() { 53 var threeElementCurve=[2.0, -3.0, 4.0]; 54 var inputData=[-1.5, +1.5]; 55 var expectedData=[2.0, 4.0]; 56 executeTest(threeElementCurve, inputData, expectedData, "Testing out-of-range inputs (should be mapped to the first/last elements of the curve)"); 57 })(); 58 59 /* 60 Testing a 2-element curve (does not have a middle element) 61 ========================================================== 62 From the specification: 63 Each input sample within this range will index into the shaping curve with a signal level of zero corresponding 64 to the center value of the curve array. 65 The implementation must perform linear interpolation between adjacent points in the curve. 66 */ 67 (function() { 68 var twoElementCurve=[2.0, -2.0]; 69 var inputData=[-1.0, 0, 1.0]; 70 var expectedData=[2.0, 0.0, -2.0]; 71 executeTest(twoElementCurve, inputData, expectedData, "Testing a 2-element curve (does not have a middle element)"); 72 })(); 73 74 /* 75 Testing a 4-element curve (does not have a middle element) 76 ========================================================== 77 From the specification: 78 Each input sample within this range will index into the shaping curve with a signal level of zero corresponding 79 to the center value of the curve array. 80 The implementation must perform linear interpolation between adjacent points in the curve. 81 */ 82 (function() { 83 var fourElementCurve=[1.0, 2.0, 4.0, 7.0]; 84 var inputData=[-1.0, 0, 1.0]; 85 var expectedData=[1.0, 3.0, 7.0]; 86 executeTest(fourElementCurve, inputData, expectedData, "Testing a 4-element curve (does not have a middle element)"); 87 })(); 88 89 /* 90 Testing a huge curve 91 ==================== 92 From the specification: 93 Each input sample within this range will index into the shaping curve with a signal level of zero corresponding 94 to the center value of the curve array. 95 */ 96 (function() { 97 var bigCurve=[]; 98 for(var i=0;i<=60000;i++) { bigCurve.push(i/3.5435); } 99 var inputData=[-1.0, 0, 1.0]; 100 var expectedData=[bigCurve[0], bigCurve[30000], bigCurve[60000]]; 101 executeTest(bigCurve, inputData, expectedData, "Testing a huge curve"); 102 })(); 103 104 /* 105 Testing single-element curve (boundary condition) 106 ================================================= 107 From the specification: 108 Each input sample within this range will index into the shaping curve with a signal level of zero corresponding 109 to the center value of the curve array. 110 Any sample value less than -1 will correspond to the first value in the curve array. 111 Any sample value greater than +1 will correspond to the last value in the curve array. 112 The implementation must perform linear interpolation between adjacent points in the curve. 113 */ 114 115 /* 116 Testing null curve (should return input values) 117 =============================================== 118 From the specification: 119 Initially the curve attribute is null, which means that the WaveShaperNode will pass its input to its output 120 without modification. 121 */ 122 (function() { 123 var inputData=[-1.0, 0, 1.0, 2.0]; 124 var expectedData=[-1.0, 0.0, 1.0, 2.0]; 125 executeTest(null, inputData, expectedData, "Testing null curve (should return input values)"); 126 })(); 127 128 /** 129 * Function that does the actual testing (using an asynchronous test). 130 * @param {?Array.<number>} curveData - Array containing values for the WaveShaper curve. 131 * @param {!Array.<number>} inputData - Array containing values for the input stream. 132 * @param {!Array.<number>} expectedData - Array containing expected results for each of the corresponding inputs. 133 * @param {!string} testName - Name of the test case. 134 */ 135 function executeTest(curveData, inputData, expectedData, testName) { 136 var stTest=async_test("WaveShaperNode - "+testName); 137 stTest.step(function() { 138 139 // Create offline audio context. 140 var ac=new OfflineAudioContext(1, inputData.length, sampleRate); 141 142 // Create the WaveShaper and its curve. 143 var waveShaper=ac.createWaveShaper(); 144 if(curveData!=null) { 145 var curve=new Float32Array(curveData.length); 146 for(var i=0;i<curveData.length;i++) { curve[i]=curveData[i]; } 147 waveShaper.curve=curve; 148 } 149 waveShaper.connect(ac.destination); 150 151 // Create buffer containing the input values. 152 var inputBuffer=ac.createBuffer(1, Math.max(inputData.length, 2), sampleRate); 153 var d=inputBuffer.getChannelData(0); 154 for(var i=0;i<inputData.length;i++) { d[i]=inputData[i]; } 155 156 // Play the input buffer through the WaveShaper. 157 var src=ac.createBufferSource(); 158 src.buffer=inputBuffer; 159 src.connect(waveShaper); 160 src.start(); 161 162 // Test the outputs match the expected values. 163 ac.oncomplete=stTest.step_func_done(function(ev) { 164 var d=ev.renderedBuffer.getChannelData(0); 165 166 for(var i=0;i<expectedData.length;i++) { 167 var curveText="null"; 168 if(curve!=null) { 169 if(curveData.length<20) { 170 curveText=curveData.join(","); 171 } else { 172 curveText="TooBigToDisplay ("+(curveData.length-1)+" elements)"; 173 } 174 } 175 var comment="Input="+inputData[i]+", Curve=["+curveText+"] >>> "; 176 assert_approx_equals(d[i], expectedData[i], tolerance, comment); 177 } 178 }); 179 ac.startRendering(); 180 }); 181 } 182 </script> 183 </body> 184 </html>