<!doctype html>
<html>
  <head>
    <title>
      Test Reconnection of Tail-Processing Nodes
    </title>
    <script src="../../imported/w3c/web-platform-tests/resources/testharness.js"></script>
    <script src="../../resources/testharnessreport.js"></script>
    <script src="../resources/audit.js"></script>
    <script src="../resources/audit-util.js"></script>
  </head>

  <body>
    <script>
      let audit = Audit.createTaskRunner();

      audit.define(
          {
            test: 'Test Compressor',
            label: 'Reconnect graph to DynamicsCompressor before end of tail'
          },
          (task, should) => {
            // Arbitrary sample rate
            const sampleRate = 16000;

            // These constants taken from dyanmics_compress_kernel.{cc,h}.
            const preDelayFrames = 1024;
            const meteringReleaseTime = 0.325;
            const tailTime = 5 * meteringReleaseTime;
            const latencyTime = preDelayFrames / sampleRate;
            const tailProcessingTime = tailTime + latencyTime;

            // The DynamicsCompressorNode has a tail + latency time of a little
            // over 1.68 sec, so make the duration longer than that.
            const renderDuration = 3;

            let context = new OfflineAudioContext(
                1, renderDuration * sampleRate, sampleRate);


            runTest(context, should, {
              testNodeName: 'DynamicsCompressorNode',
              nodeOptions: null,
              suspendTime: 2,
              tailProcessingTime: tailProcessingTime
            }).then(() => task.done());
          });

      audit.define(
          {
            test: 'Test Biquad',
            label: 'Reconnect graph to Biquad before end of tail'
          },
          (task, should) => {
            let renderDuration = 1;
            let sampleRate = 16384;

            let context = new OfflineAudioContext(
                1, renderDuration * sampleRate, sampleRate);

            // Taken from BiquadFilter/tail-time-lowpass.html
            let filterOptions = {
              type: 'lowpass',
              Q: 40,
              frequency: sampleRate / 4
            };
            let tailProcessingTime = 2079.4 / context.sampleRate;

            runTest(context, should, {
              testNodeName: 'BiquadFilterNode',
              nodeOptions: filterOptions,
              suspendTime: .5,
              tailProcessingTime: tailProcessingTime
            }).then(() => task.done());

          });

      // Run a test using the given test node that has a tail time.
      // |options| is a dictionary with the following members:
      //   testNodeName:  name of the node (used as a constructor)
      //   nodeOptiosn:   any options needed to create the node with the right
      //                  properties.
      //   suspendTime:   Time at which oscillator should start.
      //   tailProcessingTime:  Length of the tail of the node, in sec.
      function runTest(context, should, options) {
        // This test basically taken from the repro case in crbug.com/829767
        let osc = new OscillatorNode(context);
        let g0 = new GainNode(context);
        let g1 = new GainNode(context);
        let g2 = new GainNode(context);
        let g3 = new GainNode(context);
        let testNode =
            new window[options.testNodeName](context, options.nodeOptions);

        osc.connect(g0)
            .connect(g1)
            .connect(testNode)
            .connect(g2)
            .connect(g3)
            .connect(context.destination);

        // Disconnect the rest of the graph from g0.  This should place the
        // test node on the internal tail processing list.
        g0.disconnect();
        // Now reconnect g0 to the graph..  This should re-enable the test node
        // output and remove it from the tail list.
        g0.connect(g1);

        // Start the source after the tail time of the test node.
        context.suspend(options.suspendTime)
            .then(() => {
              // Sanity check that we start the oscillator after the tail
              // processing time.
              should(context.currentTime, 'Oscillator start time')
                  .beGreaterThanOrEqualTo(options.tailProcessingTime);
              osc.start();
            })
            .then(() => context.resume());

        return context.startRendering().then(renderedBuffer => {
          // Just check that the output isn't silence.  If things are working
          // after reconnecting, there should be non-zero output.
          should(
              renderedBuffer.getChannelData(0),
              `Output of ${options.testNodeName}`)
              .notBeConstantValueOf(0);
        });
      }

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