setTargetAtTime-after-event-within-block.html (3707B)
1 <!DOCTYPE html> 2 <title>Test setTargetAtTime after an event in the same processing block</title> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script> 6 promise_test(function() { 7 const bufferSize = 179; 8 const valueStartOffset = 42; 9 const targetStartOffset = 53; 10 const sampleRate = 48000; 11 const scheduledValue = -0.5; 12 13 var context = new OfflineAudioContext(1, bufferSize, sampleRate); 14 15 var gain = context.createGain(); 16 gain.gain.setValueAtTime(scheduledValue, valueStartOffset/sampleRate); 17 gain.gain.setTargetAtTime(scheduledValue, targetStartOffset/sampleRate, 18 128/sampleRate); 19 gain.connect(context.destination); 20 21 // Apply unit DC signal to gain node. 22 var source = context.createBufferSource(); 23 source.buffer = 24 function() { 25 var buffer = context.createBuffer(1, 1, context.sampleRate); 26 buffer.getChannelData(0)[0] = 1.0; 27 return buffer; 28 }(); 29 source.loop = true; 30 source.start(); 31 source.connect(gain); 32 33 return context.startRendering(). 34 then(function(buffer) { 35 assert_equals(buffer.length, bufferSize, "output buffer length"); 36 var output = buffer.getChannelData(0); 37 var i = 0; 38 for (; i < valueStartOffset; ++i) { 39 // "Its default value is 1." 40 assert_equals(output[i], 1.0, "default gain at sample " + i); 41 } 42 for (; i < buffer.length; ++i) { 43 // "If the next event (having time T1) after this SetValue event is 44 // not of type LinearRampToValue or ExponentialRampToValue, then, for 45 // T0≤t<T1: v(t)=V". 46 // "Start exponentially approaching the target value at the given time 47 // with a rate having the given time constant." 48 // The target is the same value, and so the SetValue value continues. 49 assert_equals(output[i], scheduledValue, 50 "scheduled value at sample " + i); 51 } 52 }); 53 }, "setTargetAtTime() after setValueAtTime()"); 54 55 promise_test(async function() { 56 const bufferSize = 129; 57 const sampleRate = 16384; 58 const startSample1 = 125; 59 const target1 = Math.fround(-1./Math.expm1(-1.)); 60 // Intentionally testing the second curve before and after the 61 // rendering quantum boundary. 62 const startSample2 = startSample1 + 1; 63 const target2 = 0.; 64 const timeConstant = 1./sampleRate; 65 const tolerance = Math.pow(2, -24); // Allow single precision math. 66 const context = new OfflineAudioContext(1, bufferSize, sampleRate); 67 68 const source = new ConstantSourceNode(context, {offset: 0.}); 69 source.start(); 70 source.offset.setTargetAtTime(target1, startSample1/sampleRate, 71 timeConstant); 72 source.offset.setTargetAtTime(target2, startSample2/sampleRate, 73 timeConstant); 74 source.connect(context.destination); 75 76 const buffer = await context.startRendering(); 77 78 assert_equals(buffer.length, bufferSize, "output buffer length"); 79 const output = buffer.getChannelData(0); 80 for (let i = 0; i <= startSample1; ++i) { 81 assert_equals(output[i], 0., "initial offset at sample " + i); 82 } 83 assert_approx_equals( 84 output[startSample2], 85 Math.fround(target1 * -Math.expm1(-(startSample2 - startSample1))), 86 tolerance, 87 "scheduled value at startSample2"); 88 assert_approx_equals( 89 output[startSample2 + 1], 90 Math.fround(output[startSample2] * Math.exp(-1.)), 91 tolerance, 92 "scheduled value at startSample2 + 1"); 93 assert_approx_equals( 94 output[startSample2 + 2], 95 Math.fround(output[startSample2] * Math.exp(-2.)), 96 tolerance, 97 "scheduled value at startSample2 + 2"); 98 }, "setTargetAtTime() after setTargetAtTime()"); 99 </script>