large-exponentialRamp.html (1853B)
1 <!DOCTYPE html> 2 <title>Test exponentialRampToValueAtTime() with a large ratio of change</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script> 6 'use strict'; 7 8 promise_test(async function() { 9 const sampleRate = 16384; 10 // not a power of two, so that there is some rounding error in the exponent 11 const rampEndSample = 255; 12 const bufferSize = rampEndSample + 1; 13 const offset0 = 20.; 14 const offset1 = 20000.; 15 // Math.pow(2, -23) ~ 1 unit in the last place (ulp). 16 // Single-precision powf() amplifies rounding error of less than 0.5 ulp in 17 // to the exponent to more than 2 ulp when the curve spans this large ratio. 18 // This test is not in upstream wpt because this may be more precision than 19 // expected from an implementation. 20 const relativeTolerance = Math.pow(2, -23); 21 22 const context = new OfflineAudioContext(1, bufferSize, sampleRate); 23 24 const source = new ConstantSourceNode(context); 25 source.start(); 26 // Explicit event to work around 27 // https://bugzilla.mozilla.org/show_bug.cgi?id=1265393 28 source.offset.setValueAtTime(offset0, 0.); 29 source.offset.exponentialRampToValueAtTime(offset1, rampEndSample/sampleRate); 30 source.connect(context.destination); 31 32 const buffer = await context.startRendering(); 33 assert_equals(buffer.length, bufferSize, "output buffer length"); 34 const output = buffer.getChannelData(0); 35 const ratio = offset1 / offset0; 36 for (let i = 0; i < bufferSize; ++i) { 37 // Math.pow() uses double precision, while `output` has single precision, 38 // but `tolerance` is enough to accommodate differences. 39 const expected = offset0 * Math.pow(offset1/offset0, i/rampEndSample); 40 assert_approx_equals( 41 output[i], 42 expected, 43 relativeTolerance * expected, 44 "scheduled value at " + i); 45 } 46 }); 47 </script>