<!DOCTYPE html>
<html>
  <head>
    <title>
      oscillator-late-start.html
    </title>
    <script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit-util.js"></script>
    <script src="../resources/audit.js"></script>
  </head>
  <body>
    <script id="layout-test-code">
      let audit = Audit.createTaskRunner();

      let sampleRate = 44100;
      let renderLength = 1;

      let context;
      let node;

      // Test the oscillator node is rendered correctly when the start time of
      // start() call is in the past in terms of the context time.
      audit.define('initialize', (task, should) => {
        should(
            () => context = new OfflineAudioContext(
                1, sampleRate * renderLength, sampleRate),
            'Creating offline context for testing')
            .notThrow();
        should(() => {
          // Set up a dummy signal path to keep the audio context running and
          // spend processing time before calling start(0).
          let osc = context.createOscillator();
          let silent = context.createGain();

          osc.connect(silent);
          silent.connect(context.destination);
          silent.gain.setValueAtTime(0.0, 0);
          osc.start();

          node = context.createOscillator();
          node.connect(context.destination);
        }, 'Creating graph for testing').notThrow();
        task.done();
      });

      audit.define('test-late-start', (task, should) => {
        // The node's start time will be clamped to the render quantum boundary
        // >0.1 sec. Thus the rendered buffer will have non-zero frames.
        // See issue: crbug.com/462167
        let suspendTime = 0.1;
        let suspendFrame = 128 * Math.floor(0.1 * context.sampleRate / 128);

        context.suspend(suspendTime).then(() => {
          node.start(0);
          context.resume();
        });

        // Start rendering and verify result: this verifies if 1) the rendered
        // buffer contains at least one non-zero value and 2) the non-zero value
        // is found later than the first output sample.
        context.startRendering()
            .then(buffer => {
              let channelData = buffer.getChannelData(0);
              let nonZeroValueIndex = channelData.findIndex(x => x != 0);

              should(
                  nonZeroValueIndex,
                  'The index (' + nonZeroValueIndex +
                      ') of first non-zero output value')
                  .beGreaterThanOrEqualTo(suspendFrame);

              should(
                  channelData.slice(0, suspendFrame),
                  'Output[0:' + (suspendFrame - 1) + ']')
                  .beConstantValueOf(0);
            })
            .then(() => task.done());
        ;
      });

      audit.run();
    </script>
  </body>
</html>
