k-rate-connections.html (4622B)
1 <!doctype html> 2 <html> 3 <head> 4 <title>k-rate AudioParams with Inputs</title> 5 <script src="/resources/testharness.js"></script> 6 <script src="/resources/testharnessreport.js"></script> 7 <script src="/webaudio/resources/audit-util.js"></script> 8 </head> 9 10 <body> 11 <script> 12 // Must be power of two to eliminate round-off 13 const sampleRate = 8192; 14 15 // Arbitrary duration that doesn't need to be too long to verify k-rate 16 // automations. Probably should be at least a few render quanta. 17 const testDuration = 8 * RENDER_QUANTUM_FRAMES / sampleRate; 18 19 // Helper function to set up a test subgraph for verifying k-rate 20 // AudioParam automation. 21 function createTestSubGraph( 22 context, src, merger, nodeName, paramName, options = {}) { 23 // The test node which has its AudioParam set up for k-rate automations. 24 const testNode = new window[nodeName](context); 25 26 if (options.setups) { 27 options.setups(testNode); 28 } 29 testNode[paramName].automationRate = 'k-rate'; 30 31 // Modulating signal for the test node. Just a linear ramp. This is 32 // connected to the AudioParam of the testNode. 33 const testMod = new ConstantSourceNode(context); 34 if (options.testModSetup) { 35 options.testModSetup(testMod); 36 } else { 37 testMod.offset.linearRampToValueAtTime(context.length, testDuration); 38 } 39 40 testMod.connect(testNode[paramName]); 41 src.connect(testNode).connect(merger, 0, 0); 42 43 // The ref node is the same type of node as the test node, but uses 44 // a-rate automation. However, the modulating signal is k-rate. This 45 // causes the input to the audio param to be constant over a render, 46 // which is basically the same as making the audio param be k-rate. 47 const refNode = new window[nodeName](context); 48 const refMod = new ConstantSourceNode(context); 49 refMod.offset.automationRate = 'k-rate'; 50 if (options.testModSetup) { 51 options.testModSetup(refMod); 52 } else { 53 refMod.offset.linearRampToValueAtTime(context.length, testDuration); 54 } 55 56 refMod.connect(refNode[paramName]); 57 src.connect(refNode).connect(merger, 0, 1); 58 59 testMod.start(); 60 refMod.start(); 61 } 62 63 // Test k-rate GainNode.gain is k-rate 64 promise_test(async t => { 65 const context = new OfflineAudioContext({ 66 numberOfChannels: 2, 67 sampleRate: sampleRate, 68 length: testDuration * sampleRate 69 }); 70 71 const merger = new ChannelMergerNode( 72 context, {numberOfInputs: context.destination.channelCount}); 73 merger.connect(context.destination); 74 75 const src = new ConstantSourceNode(context); 76 77 createTestSubGraph(context, src, merger, 'GainNode', 'gain'); 78 79 src.start(); 80 const buffer = await context.startRendering(); 81 82 const actual = buffer.getChannelData(0); 83 const expected = buffer.getChannelData(1); 84 85 for (let k = 0; k < actual.length; k += RENDER_QUANTUM_FRAMES) { 86 assert_constant_value( 87 actual.slice(k, k + RENDER_QUANTUM_FRAMES), 88 expected[k], 89 `gain[${k}:${k + RENDER_QUANTUM_FRAMES}]`); 90 } 91 }, 'Gain - k-rate GainNode.gain'); 92 93 // Test k-rate StereoPannerNode.pan is k-rate 94 promise_test(async t => { 95 const context = new OfflineAudioContext({ 96 numberOfChannels: 2, 97 sampleRate: sampleRate, 98 length: testDuration * sampleRate 99 }); 100 101 const merger = new ChannelMergerNode( 102 context, {numberOfInputs: context.destination.channelCount}); 103 merger.connect(context.destination); 104 105 const src = new ConstantSourceNode(context); 106 107 createTestSubGraph( 108 context, src, merger, 'StereoPannerNode', 'pan', { 109 testModSetup: node => { 110 node.offset.setValueAtTime(-1, 0); 111 node.offset.linearRampToValueAtTime(1, testDuration); 112 } 113 }); 114 115 src.start(); 116 const renderedBuffer = await context.startRendering(); 117 118 const actual = renderedBuffer.getChannelData(0); 119 const expected = renderedBuffer.getChannelData(1); 120 121 for (let k = 0; k < actual.length; k += 128) { 122 assert_constant_value( 123 actual.slice(k, k + 128), 124 expected[k], 125 `pan[${k}:${k + 128}]`); 126 } 127 }, 'StereoPanner - k-rate StereoPannerNode.pan'); 128 </script> 129 </body> 130 </html>