<!doctype html>
<html>

<head>
  <script src="../resources/js-test.js"></script>
  <script src="resources/compatibility.js"></script>
  <script src="resources/audio-testing.js"></script>
  <script src="resources/audioparam-testing.js"></script>
  <title>AudioParam Initial Events </title>
</head>

<body>
  <script>
    description("Test Automation Ramps without Initial Event");
    window.jsTestIsAsync = true;

    var sampleRate = 48000;
    // Number of frames in a rendering quantum.
    var quantumFrames = 128;
    // Test doesn't need to run for very long.
    var renderDuration = 0.2;
    var renderFrames = renderDuration * sampleRate;
    var automationEndTime = 0.1;

    var audit = Audit.createTaskRunner();

    // The following tests start a ramp automation without an initial event.  This should cause an
    // initial event to be added implicitly to give a starting point.
    audit.defineTask("linear-ramp", function (done) {
      runTest("Linear ramp", {
          automationFunction: function (node, value, time) {
            node.gain.linearRampToValueAtTime(value, time);
          },
          referenceFunction: linearRamp,
          // Experimentally determined threshold
          threshold: 6.0003e-8,
          // The starting value of the gain node
          v0: 0.5,
          // The target value of the automation
          v1: 0,
        })
        .then(done);
    });

    audit.defineTask("exponential-ramp", function (done) {
      runTest("Exponential ramp", {
          automationFunction: function (node, value, time) {
            node.gain.exponentialRampToValueAtTime(value, time);
          },
          referenceFunction: exponentialRamp,
          threshold: 2.3842e-6,
          v0: 0.5,
          v1: 2,
        })
        .then(done);
    });

    // Same tests as above, but we delay the call to the automation function. This is to verify that
    // the we still do the right thing after the context has started.
    audit.defineTask("delayed-linear-ramp", function (done) {
      runTest("Delayed linear ramp", {
          automationFunction: function (node, value, time) {
            node.gain.linearRampToValueAtTime(value, time);
          },
          referenceFunction: linearRamp,
          // Experimentally determined threshold
          threshold: 9.87968e-8,
          // The starting value of the gain node
          v0: 0.5,
          // The target value of the automation
          v1: 0,
          delay: quantumFrames / sampleRate
        })
        .then(done);
    });

    audit.defineTask("delayed-exponential-ramp", function (done) {
      runTest("Delayed exponential ramp", {
          automationFunction: function (node, value, time) {
            node.gain.exponentialRampToValueAtTime(value, time);
          },
          referenceFunction: exponentialRamp,
          // Experimentally determined threshold
          threshold: 1.3948e-5,
          // The starting value of the gain node
          v0: 0.5,
          // The target value of the automation
          v1: 2,
          delay: quantumFrames / sampleRate
        })
        .then(done);
    });

    audit.defineTask("finish", function (done) {
      finishJSTest();
      done();
    });

    audit.runTasks();

    // Generate the expected waveform for a linear ramp starting from the value |v0|, ramping to
    // |v1| at time |endTime|.  The time of |v0| is assumed to be 0.  |nFrames| is how many frames
    // to generate.
    function linearRamp(v0, v1, startTime, endTime, nFrames) {
      var expected = createLinearRampArray(startTime, endTime, v0, v1, sampleRate);
      var preFiller = new Array(Math.floor(startTime * sampleRate));
      var postFiller = new Array(nFrames - Math.ceil(endTime * sampleRate));
      preFiller.fill(v0);
      return preFiller.concat(expected.concat(postFiller.fill(v1)));
    }

    // Generate the expected waveform for an exponential ramp starting from the value |v0|,
    // ramping to |v1| at time |endTime|.  The time of |v0| is assumed to be 0.  |nFrames| is how
    // many frames to generate.
    function exponentialRamp(v0, v1, startTime, endTime, nFrames) {
      var expected = createExponentialRampArray(startTime, endTime, v0, v1, sampleRate);
      var preFiller = new Array(Math.floor(startTime * sampleRate));
      preFiller.fill(v0);
      var postFiller = new Array(nFrames - Math.ceil(endTime * sampleRate));
      return preFiller.concat(expected.concat(postFiller.fill(v1)));
    }

    // Run an automation test. |message| is the message to use for printing the results. |options|
    // is a property bag containing the configuration of the test including the following:
    //
    // automationFunction - automation function to use,
    // referenceFunction  - function generating the expected result
    // threshold          - comparison threshold
    // v0                 - starting value
    // v1                 - end value for automation
    function runTest(message, options) {
      var automationFunction = options.automationFunction;
      var referenceFunction = options.referenceFunction;
      var threshold = options.threshold;
      var v0 = options.v0;
      var v1 = options.v1;
      var delay = options.delay;

      var context = new OfflineAudioContext(1, renderFrames, sampleRate);

      // A constant source of amplitude 1.
      var source = context.createBufferSource();
      source.buffer = createConstantBuffer(context, 1, 1);
      source.loop = true;

      // Automation is applied to a gain node
      var gain = context.createGain();
      gain.gain.value = v0;

      // Delay start of automation, if requested
      if (delay) {
        context.suspend(options.delay).then(function () {
          automationFunction(gain, v1, automationEndTime);
          context.resume();
        });
      } else {
        automationFunction(gain, v1, automationEndTime);
      }

      source.connect(gain);
      gain.connect(context.destination);

      source.start();

      return context.startRendering()
        .then(function (resultBuffer) {
          var result = resultBuffer.getChannelData(0);
          var expected = referenceFunction(v0, v1, delay ? delay : 0, automationEndTime, renderFrames);
          Should(message, result).beCloseToArray(expected, threshold);
        });
    }
  </script>
</body>

</html>