<!DOCTYPE html>
<title>Test convolution to delay a triangle pulse</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
const sampleRate = 48000;
const LENGTH = 12800;
// tolerate 16-bit math.
const EPSILON = 1.0 / Math.pow(2, 15);

// Triangle pulse
var sourceBuffer = new OfflineAudioContext(1, 1, sampleRate).
  createBuffer(1, 2 * 128, sampleRate);
var channelData = sourceBuffer.getChannelData(0);
for (var i = 0; i < 128; ++i) {
  channelData[i] = i/128;
  channelData[128 + i] = 1.0 - i/128;
}

function test_delay_index(delayIndex) {

  var context = new OfflineAudioContext(2, LENGTH, sampleRate);

  var merger = context.createChannelMerger(2);
  merger.connect(context.destination);

  var impulse = context.createBuffer(1, delayIndex + 1, sampleRate);
  impulse.getChannelData(0)[delayIndex] = 1.0;
  var convolver = context.createConvolver();
  convolver.normalize = false;
  convolver.buffer = impulse;
  convolver.connect(merger, 0, 0);

  var delayTime = delayIndex/sampleRate;
  var delay = context.createDelay(delayTime || 1/sampleRate);
  delay.delayTime.value = delayTime;
  delay.connect(merger, 0, 1);

  var source = context.createBufferSource();
  source.buffer = sourceBuffer;
  source.connect(convolver);
  source.connect(delay);
  source.start(0);

  return context.startRendering().
    then((buffer) => {
      var convolverOutput = buffer.getChannelData(0);
      var delayOutput = buffer.getChannelData(1);
      var maxDiff = 0.0;
      var maxIndex = 0;
      for (var i = 0; i < buffer.length; ++i) {
        var diff = Math.abs(convolverOutput[i] - delayOutput[i]);
        if (diff > maxDiff) {
          maxDiff = diff;
          maxIndex = i;
        }
      }
      // The convolver should produce similar output to the delay.
      assert_approx_equals(convolverOutput[maxIndex], delayOutput[maxIndex],
                           EPSILON, "output at " + maxIndex);
    });
}

// The 5/4 ratio provides sampling across a range of delays and offsets within
// blocks.
for (var delayIndex = 0;
     delayIndex < LENGTH;
     delayIndex = Math.floor((5 * (delayIndex + 1)) / 4)) {
  promise_test(test_delay_index.bind(null, delayIndex),
               "Delay " + delayIndex);
}
</script>
