<!DOCTYPE html>
<html>
  <head>
    <title>
      Test Handling of Tail Processing
    </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 id="layout-test-code">
      let audit = Audit.createTaskRunner();

      // Fairly arbitrary but must be a power of two to eliminate roundoff when
      // we compute times from sample frames
      const sampleRate = 32768;

      // Fairly arbitrary duration
      const renderDuration = 0.25;
      const renderFrames = renderDuration * sampleRate;

      audit.define(
          {label: 'grain', description: 'ABSN grain has the correct duration'},
          (task, should) => {
            // Test that the grain duration is the requested duration.
            let context = new OfflineAudioContext(2, sampleRate, sampleRate);
            let merger = new ChannelMergerNode(
                context, {numberOfInputs: context.destination.channelCount});
            merger.connect(context.destination);

            // Number of frames for the grain we want to play. (Pretty much
            // arbitrary.)
            let grainFrames = 128;

            // Test signal.  Just fill the buffer with all ones.
            let bTest = new AudioBuffer(
                {length: context.length, sampleRate: context.sampleRate});
            bTest.getChannelData(0).fill(1);
            let sTest = new AudioBufferSourceNode(context, {buffer: bTest});

            // Reference signal. 
            let bRef = new AudioBuffer(
                {length: context.length, sampleRate: context.sampleRate});
            bRef.getChannelData(0).fill(1, 0, grainFrames);
            let sRef = new AudioBufferSourceNode(context, {buffer: bRef});

            sTest.connect(merger, 0, 0);
            sRef.connect(merger, 0, 1);

            sTest.start(0, 0, grainFrames / context.sampleRate);
            sRef.start();

            context.startRendering()
                .then(renderedBuffer => {
                  let actual = renderedBuffer.getChannelData(0);
                  let expected = renderedBuffer.getChannelData(1);

                  // The actual and expected should be the same because we got
                  // rid of the grain hack that caused a grain to play for an
                  // extra 512 frames.
                  should(actual, 'Rendered ABSN grain')
                      .beEqualToArray(expected);
                })
                .then(() => task.done());
          });

      audit.define('hrtf-panner-tail', (task, should) => {
        runTest('PannerNode', {panningModel: 'HRTF', distanceMode: 'linear'})
            .then(renderedBuffer => {
              let prefix = 'HRTF PannerNode';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let latencyFrame = findLatencyFrame(response);
              let tailFrame = findTailFrame(response);

              // The HRTF panner has both a latency component and a tail
              // component.  Make sure both are non-zero.
              should(latencyFrame, `${prefix} latency frame (${latencyFrame})`)
                  .beGreaterThan(0);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              // Because of the latency, the output is zero at the beginning.
              // Make sure this is true.
              should(
                  output.slice(0, latencyFrame),
                  `${prefix} Latency output[0:` + (latencyFrame - 1) + ']')
                  .beConstantValueOf(0);

              // Verify the rest of the output matches the expected values.  The
              // output should be non-zero from latencyFrame to tailFrame and
              // zero after tailFrame.
              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: latencyFrame,
                nonZeroEndFrame: Math.min(tailFrame, output.length),
                zeroStartFrame: roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });
            })
            .then(() => task.done());
      });

      audit.define('biquad-tail', (task, should) => {
        runTest('BiquadFilterNode', {Q: 20, frequency: 100})
            .then(renderedBuffer => {
              let prefix = 'BiquadFilter'
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let tailFrame = findTailFrame(response);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              // Verify biquad output which should be non-zero up to tailFrame
              // and zero afterwards.  However, the actual output isn't after
              // tailFrame because the internal biquad tail time uses an
              // approximation.  That's why zeroStartFrame is one render quantum
              // after tailFrame.
              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: 0,
                nonZeroEndFrame:
                    Math.min(tailFrame + RENDER_QUANTUM_FRAMES, output.length),
                zeroStartFrame: RENDER_QUANTUM_FRAMES + roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });
            })
            .then(() => task.done());
      });

      audit.define('iir-tail', (task, should) => {
        runTest('IIRFilterNode', {feedforward: [1], feedback: [1, -.99]})
            .then(renderedBuffer => {
              let prefix = 'IIRFilter';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let tailFrame = findTailFrame(response);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: 0,
                nonZeroEndFrame:
                    Math.min(tailFrame + RENDER_QUANTUM_FRAMES, output.length),
                zeroStartFrame: 2 * RENDER_QUANTUM_FRAMES + roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });
            })
            .then(() => task.done());
      });

      audit.define('delay-tail', (task, should) => {
        // For the test, make sure the delay is greater than one render
        // quantum.  If it's less we won't be able to tell if tail processing
        // worked because the input signal is an impulse.
        let delayFrames = RENDER_QUANTUM_FRAMES + 64;
        runTest('DelayNode', {delayTime: delayFrames / sampleRate})
            .then(renderedBuffer => {
              let prefix = 'Delay';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let tailFrame = findTailFrame(response);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              // As a delay node with delay time greater than one render
              // quantum, the first render quantum must be 0.
              should(
                  output.slice(0, RENDER_QUANTUM_FRAMES),
                  `${prefix} output[0:` + (RENDER_QUANTUM_FRAMES - 1) + ']')
                  .beConstantValueOf(0);

              // The output of the delay node should be nonzero in the second
              // render quantum and zero forever after.
              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: RENDER_QUANTUM_FRAMES,
                nonZeroEndFrame: Math.min(tailFrame, output.length),
                zeroStartFrame: roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });

            })
            .then(() => task.done());
      });

      audit.define('convolver-tail', (task, should) => {
        // The convolver response.  It needs to be longer than one render
        // quantum to show the tail processing.
        let response = new AudioBuffer(
            {length: RENDER_QUANTUM_FRAMES + 64, sampleRate: sampleRate});
        // For simplicity, just make the response all ones.
        response.getChannelData(0).fill(1);

        runTest('ConvolverNode', {disableNormalization: true, buffer: response})
            .then(renderedBuffer => {
              let prefix = 'Convolver';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let tailFrame = findTailFrame(response);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: 0,
                nonZeroEndFrame:
                    Math.min(tailFrame + RENDER_QUANTUM_FRAMES, output.length),
                zeroStartFrame: RENDER_QUANTUM_FRAMES + roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });
            })
            .then(() => task.done());
      });

      audit.define('dynamics-compressor-tail', (task, should) => {
        runTest('DynamicsCompressorNode', {})
            .then(renderedBuffer => {
              let prefix = 'DyamicsCompressor';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              let tailFrame = findTailFrame(response);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              let latencyFrame = roundDown(tailFrame - 1);
              should(
                  output.slice(0, latencyFrame),
                  `${prefix} output[0:` + (latencyFrame - 1) + ']')
                  .beConstantValueOf(0);

              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: latencyFrame,
                nonZeroEndFrame: Math.min(tailFrame, output.length),
                zeroStartFrame: roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });

            })
            .then(() => task.done());
      });

      audit.define('waveshaper-tail', (task, should) => {
        // Fairly arbitrary curve for the WaveShaper
        let curve = Float32Array.from([-1, -.5, 0, 0.5, 1]);

        runTest('WaveShaperNode', {curve: curve, oversample: '2x'})
            .then(renderedBuffer => {
              let prefix = 'WaveShaper';
              let output = renderedBuffer.getChannelData(0);
              let response = renderedBuffer.getChannelData(1);
              // FFT resampler introduces some very small round-off.  Use a
              // threshold of zero to find the tail frame.
              let tailFrame = findTailFrame(response, 0);

              should(tailFrame, `${prefix} tail frame (${tailFrame})`)
                  .beGreaterThan(0);

              verifyOutput(should, output, {
                prefix: prefix,
                startFrame: 0,
                nonZeroEndFrame: Math.min(tailFrame, output.length),
                zeroStartFrame: roundUp(tailFrame),
                tailFrame: tailFrame,
                reference: response
              });
            })
            .then(() => task.done());
      });

      audit.run('waveshaper-tail');

      function runTest(nodeName, nodeOptions) {
        // Two-channel output.  Channel 0 is the test result; channel 1 is the
        // impulse response that is used to figure out when the tail should
        // start.
        let context = new OfflineAudioContext(2, sampleRate, sampleRate);

        // Merge channels for the destination.
        let merger = new ChannelMergerNode(context, {numberOfInputs: 2});
        merger.connect(context.destination);

        let src = new ConstantSourceNode(context, {offset: 1});

        // Impulse for testing.  We want a full buffer so as not to worry about
        // the source disconnecting prematurely from the filter.
        let b = new AudioBuffer(
            {length: context.length, sampleRate: context.sampleRate});
        b.getChannelData(0)[0] = 1;
        let impulse = new AudioBufferSourceNode(context, {buffer: b});

        let testNode = new window[nodeName](context, nodeOptions);
        let refNode = new window[nodeName](context, nodeOptions);

        src.connect(testNode).connect(merger, 0, 0);
        impulse.connect(refNode).connect(merger, 0, 1);

        src.start();
        src.stop(1 / context.sampleRate);
        impulse.start();

        return context.startRendering();
      }

      // Starting from the end find the first frame that exceeds our threshold.
      // This assumes that everything less than the threshold is equivalent to 0
      // for our purposes.
      function findTailFrame(response, zeroThreshold) {
        // Any value below this is considered to be zero for our purpose of
        // finding the first non-zero value.  Somewhat arbitrary, but the value
        // here is the size of the LSB of a 16-bit PCM sample.
        let threshold = zeroThreshold === undefined ? 1 / 32768 : zeroThreshold;
        let tailFrame = response.length;

        for (let k = response.length - 1; k >= 0; --k) {
          if (Math.abs(response[k]) > threshold) {
            tailFrame = k + 1;
            break;
          }
        }

        return tailFrame;
      }

      function findLatencyFrame(response) {
        for (let k = 0; k < response.length; ++k) {
          if (response[k] != 0)
            return k;
        }

        return response.length;
      }

      function verifyOutput(should, output, options) {
        let prefix = options.prefix || '';
        if (options.tailFrame && options.reference) {
          should(
              output.slice(0, options.tailFrame),
              `${prefix} Tail output[0:` + (options.tailFrame - 1) + ']')
              .beEqualToArray(options.reference.slice(0, options.tailFrame));
        }

        // Verify that |output| is non-zero between |startFrame| and
        // |nonZeroEndFrame|.
        for (let k = options.startFrame; k < options.nonZeroEndFrame;
             k += RENDER_QUANTUM_FRAMES) {
          should(
              output.slice(k, k + RENDER_QUANTUM_FRAMES),
              `${prefix} output[` + k + ':' + (k + 127) + ']')
              .notBeConstantValueOf(0);
        }

        // Verify |output| is zero starting at frame |zeroStartFrame|, inclusive
        if (options.zeroStartFrame < output.length) {
          should(
              output.slice(options.zeroStartFrame),
              `${prefix} output[` + options.zeroStartFrame + ':]')
              .beConstantValueOf(0);
        }
      }

      function roundDown(frame) {
        return RENDER_QUANTUM_FRAMES *
            Math.floor(frame / RENDER_QUANTUM_FRAMES);
      }

      function roundUp(frame) {
        return RENDER_QUANTUM_FRAMES * Math.ceil(frame / RENDER_QUANTUM_FRAMES);
      }
    </script>
  </body>
</html>
