waveshaper-limits.html (3362B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title> 5 waveshaper-limits.html 6 </title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="../../resources/audit-util.js"></script> 10 </head> 11 <body> 12 <script> 13 let context; 14 let bufferData; 15 let outputData; 16 let reference; 17 18 const sampleRate = 48000; 19 // Must be odd so we have an exact middle point. 20 const testFrames = 23; 21 const scale = 1 / ((testFrames - 1) / 2 - 1); 22 // Number of decimal digits to print 23 const decimals = 6; 24 // Required accuracy 25 const diffThreshold = Math.pow(10, -decimals); 26 27 // Generate reference data 28 const generateReference = () => { 29 // The curve data is 0, 1, 0, and the input data is a ramp from -1+eps 30 // to 1+eps. Then the output is a ramp from 0 to 1 back to 0. 31 const ref = new Float32Array(testFrames); 32 const midPoint = (testFrames - 1) / 2; 33 // First sample is below -1 at -1-scale. 34 ref[0] = 0; 35 // Generate ramp up to the mid-point 36 for (let k = 0; k < midPoint; ++k) { 37 ref[k + 1] = k * scale; 38 } 39 // The value at the mid-point must be 1, from the curve 40 ref[midPoint] = 1; 41 // Generate a ramp from 1 down to 0 42 for (let k = midPoint; k < testFrames - 1; ++k) { 43 ref[k + 1] = 2 - k * scale; 44 } 45 // The last sample is out of range at 1+scale 46 ref[testFrames - 1] = 0; 47 return ref; 48 }; 49 50 const checkResult = renderedBuffer => { 51 outputData = renderedBuffer.getChannelData(0); 52 reference = generateReference(); 53 for (let k = 0; k < outputData.length; ++k) { 54 const diff = outputData[k] - reference[k]; 55 assert_less_than_equal( 56 Math.abs(diff), 57 diffThreshold, 58 `Max error mapping ${bufferData[k].toFixed(decimals)} to ` + 59 `${outputData[k].toFixed(decimals)}`); 60 } 61 }; 62 63 promise_test(async t => { 64 context = new OfflineAudioContext(1, testFrames, sampleRate); 65 // Create input values between -1.1 and 1.1 66 const buffer = new AudioBuffer({ length: testFrames, 67 numberOfChannels: 1, sampleRate: context.sampleRate }); 68 bufferData = new Float32Array(testFrames); 69 const start = -1 - scale; 70 for (let k = 0; k < testFrames; ++k) { 71 bufferData[k] = k * scale + start; 72 } 73 buffer.copyToChannel(bufferData, 0); 74 75 const source = new AudioBufferSourceNode(context, { buffer }); 76 77 // Create simple waveshaper. It should map -1 to 0, 0 to 1, and +1 78 // to 0 and interpolate all points in between using a simple linear 79 // interpolator. 80 const curve = new Float32Array(3); 81 curve[0] = 0; 82 curve[1] = 1; 83 curve[2] = 0; 84 85 const shaper = new WaveShaperNode(context, { curve }); 86 source.connect(shaper); 87 shaper.connect(context.destination); 88 89 source.start(); 90 const renderedBuffer = await context.startRendering(); 91 checkResult(renderedBuffer); 92 }, 'WaveShaperNode maps input values outside [-1,1] according to curve' + 93 ' and clamps output correctly'); 94 </script> 95 </body> 96 </html>