no-dezippering.html (3653B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title> 5 Gain Dezippering Test: Dezippering Removed 6 </title> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/webaudio/resources/audit-util.js"></script> 10 </head> 11 <body> 12 <script> 13 promise_test( 14 () => testWithAutomation({prefix: ''}), 15 'Compare value setter and setValueAtTime'); 16 17 promise_test( 18 () => testWithAutomation({ 19 prefix: 'With modulation: ', 20 modulator: true 21 }), 22 'Automation effects'); 23 24 promise_test(async () => { 25 // Only need a few frames to verify that dezippering has been 26 // removed from the GainNode. Sample rate is pretty arbitrary. 27 const context = new OfflineAudioContext(1, 1024, 16000); 28 29 // Send a unit source to the gain node so we can measure the effect 30 // of the gain node. 31 const src = new ConstantSourceNode(context, {offset: 1}); 32 const g = new GainNode(context, {gain: 1}); 33 src.connect(g).connect(context.destination); 34 35 // Schedule the suspend but DON’T await it here 36 context 37 .suspend(RENDER_QUANTUM_FRAMES / context.sampleRate) 38 .then(() => { 39 g.gain.value = 0.5; 40 return context.resume(); 41 }); 42 43 src.start(); 44 45 // Now start rendering and wait for it to finish 46 const audio = await context.startRendering(); 47 const c = audio.getChannelData(0); 48 49 // If dezippering has been removed, the gain output should 50 // instantly jump at frame 128 to 0.5. 51 assert_constant_value(c.slice(0, 128), 1, 'output[0:127]'); 52 assert_constant_value(c.slice(128), 0.5, 'output[128:]'); 53 }, 'Dezippering of GainNode removed'); 54 55 async function testWithAutomation(options) { 56 // Sample rate must be a power of two to eliminate round-off in 57 // computing the time at render quantum boundaries. 58 const context = new OfflineAudioContext(2, 1024, 16384); 59 const merger = new ChannelMergerNode(context, {numberOfChannels: 2}); 60 merger.connect(context.destination); 61 62 const src = new OscillatorNode(context); 63 const gainTest = new GainNode(context); 64 const gainRef = new GainNode(context); 65 66 src.connect(gainTest).connect(merger, 0, 0); 67 src.connect(gainRef).connect(merger, 0, 1); 68 69 if (options.modulator) { 70 const mod = new OscillatorNode(context, {frequency: 1000}); 71 const modGain = new GainNode(context); 72 mod.connect(modGain); 73 modGain.connect(gainTest.gain); 74 modGain.connect(gainRef.gain); 75 mod.start(); 76 } 77 78 // Change the gains. Must do the change on a render boundary! 79 const changeTime = 3 * RENDER_QUANTUM_FRAMES / context.sampleRate; 80 const newGain = 0.3; 81 82 gainRef.gain.setValueAtTime(newGain, changeTime); 83 context 84 .suspend(changeTime) 85 .then(() => { 86 gainTest.gain.value = newGain; 87 return context.resume(); 88 }); 89 90 src.start(); 91 92 const audio = await context.startRendering(); 93 const actual = audio.getChannelData(0); 94 const expected = audio.getChannelData(1); 95 96 // The values using the .value setter must be identical to the 97 // values using setValueAtTime. 98 assert_array_equals( 99 actual, expected, 100 options.prefix + '.value setter output matches setValueAtTime'); 101 } 102 103 </script> 104 </body> 105 </html>