Handle k-rate AudioParam inputs for AudioWorkletNode

Support k-rate input to AudioParams for an AudioWorkletNode.
Previously, inputs to a k-rate AudioParam were ignored, which is
incorrect.  The input must be summed with any timeline value.

Manually ran the new test case with Chrome stable and the tests fail
as expected (output is constantly 0 which is wrong).

Bug: 1015760
Test: k-rate-audioworklet-connections.https.html
Change-Id: I5dbba311fb84b9a162e1b2ac4fc9ef902ff36eb6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2194189
Commit-Queue: Raymond Toy <rtoy@chromium.org>
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#767820}
diff --git a/webaudio/the-audio-api/the-audioparam-interface/k-rate-audioworklet-connections.https.html b/webaudio/the-audio-api/the-audioparam-interface/k-rate-audioworklet-connections.https.html
new file mode 100644
index 0000000..4d2eb40
--- /dev/null
+++ b/webaudio/the-audio-api/the-audioparam-interface/k-rate-audioworklet-connections.https.html
@@ -0,0 +1,77 @@
+<!doctype html>
+<html>
+  <head>
+    <title>Test k-rate AudioParams with inputs for AudioWorkletNode</title>
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+    <script src="/webaudio/resources/audit-util.js"></script>
+    <script src="/webaudio/resources/audit.js"></script>
+  </head>
+
+  <body>
+    <script>
+      const audit = Audit.createTaskRunner();
+
+      // Use the worklet gain node to test k-rate parameters.
+      const filePath =
+          '../the-audioworklet-interface/processors/gain-processor.js';
+
+      // Context for testing
+      let context;
+
+      audit.define('Create Test Worklet', (task, should) => {
+        // Arbitrary sample rate and duration.
+        const sampleRate = 8000;
+
+        // Only new a few render quanta to verify things are working.
+        const testDuration = 4 * 128 / sampleRate;
+
+        context = new OfflineAudioContext({
+          numberOfChannels: 3,
+          sampleRate: sampleRate,
+          length: testDuration * sampleRate
+        });
+
+        should(
+            context.audioWorklet.addModule(filePath),
+            'Construction of AudioWorklet')
+            .beResolved()
+            .then(() => task.done());
+      });
+
+      audit.define('AudioWorklet k-rate AudioParam', async (task, should) => {
+        let src = new ConstantSourceNode(context);
+        let kRateNode = new AudioWorkletNode(context, 'gain');
+        src.connect(kRateNode).connect(context.destination);
+
+        let kRateParam = kRateNode.parameters.get('gain');
+        kRateParam.automationRate = 'k-rate';
+        kRateParam.value = 0;
+
+        let mod = new ConstantSourceNode(context);
+        mod.offset.setValueAtTime(0, 0);
+        mod.offset.linearRampToValueAtTime(
+            10, context.length / context.sampleRate);
+        mod.connect(kRateParam);
+
+        mod.start();
+        src.start();
+
+        const audioBuffer = await context.startRendering();
+        let output = audioBuffer.getChannelData(0);
+
+        // Verify that the output isn't constantly zero.
+        should(output, 'output').notBeConstantValueOf(0);
+        // Verify that the output from the worklet is step-wise
+        // constant.
+        for (let k = 0; k < output.length; k += 128) {
+          should(output.slice(k, k + 128), ` k-rate output [${k}: ${k + 127}]`)
+              .beConstantValueOf(output[k]);
+        }
+        task.done();
+      });
+
+      audit.run();
+    </script>
+  </body>
+</html>