<!DOCTYPE html>
<html>
  <head>
    <title>
      Test k-rate AudioParams
    </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 sampleRate = 48000;
      let renderLength = 2048;
      let eventEndTime = 0.015;

      let audit = Audit.createTaskRunner()

      audit.define(
          {label: 'validate', description: 'Validate test parameters'},
          function(task, should) {
            should(eventEndTime, 'eventTime')
                .beLessThan(renderLength / sampleRate);
            task.done();
          });

      audit.define(
          {
            label: 'playbackrate+detune',
            description: 'Test k-rate AudioBufferSourceNode AudioParams'
          },
          function(task, should) {

            let context = new OfflineAudioContext(1, renderLength, sampleRate);
            let buffer = createConstantBuffer(context, renderLength, 1);
            let node = new AudioBufferSourceNode(context, {buffer: buffer});

            node.connect(context.destination);

            // Initialize detune and playbackRate to some non-zero value
            // (because we're using exponential ramps.  Then add exponential
            // ramp to some non-zero end value.  The actual values don't matter
            // as long as they're strictly positive.
            node.detune.setValueAtTime(0.125, 0);
            node.playbackRate.setValueAtTime(1, 0);

            node.detune.exponentialRampToValueAtTime(0.75, 0.015);
            node.playbackRate.exponentialRampToValueAtTime(0.5, 0.015);

            node.start();

            context.startRendering()
                .then(function() {
                  // The final values for each attribute should be the expected
                  // final value.
                  should(node.detune.value, 'Final node.detune.value')
                      .beEqualTo(0.75);
                  should(
                      node.playbackRate.value, 'Final node.playbackRate.value')
                      .beEqualTo(0.5);
                })
                .then(task.done.bind(task));
          });

      audit.define(
          {
            label: 'panner-k-rate',
            description:
                'Test k-rate PannerNode and AudioListenerNode AudioParams'
          },
          function(task, should) {

            let context = new OfflineAudioContext(1, renderLength, sampleRate);
            let buffer = createConstantBuffer(context, renderLength, 1);
            let source = new AudioBufferSourceNode(context, {buffer: buffer});

            let panner = new PannerNode(context, {panningModel: 'HRTF'});

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

            // Initialize the k-rate parameters to some positive value.  Then
            // add exponential ramp to some non-zero end value.  The actual
            // values don't matter as long as they're strictly positive.
            panner.orientationX.setValueAtTime(1, 0);
            panner.orientationY.setValueAtTime(1, 0);
            panner.orientationZ.setValueAtTime(1, 0);

            panner.positionX.setValueAtTime(5, 0);
            panner.positionY.setValueAtTime(5, 0);
            panner.positionZ.setValueAtTime(5, 0);

            context.listener.forwardX.setValueAtTime(1, 0);
            context.listener.forwardY.setValueAtTime(1, 0);
            context.listener.forwardZ.setValueAtTime(1, 0);

            context.listener.positionX.setValueAtTime(.5, 0);
            context.listener.positionY.setValueAtTime(.5, 0);
            context.listener.positionZ.setValueAtTime(.5, 0);

            context.listener.upX.setValueAtTime(1, 0);
            context.listener.upY.setValueAtTime(1, 0);
            context.listener.upZ.setValueAtTime(1, 0);

            panner.orientationX.exponentialRampToValueAtTime(2.5, 0.015);
            panner.orientationY.exponentialRampToValueAtTime(2.5, 0.015);
            panner.orientationZ.exponentialRampToValueAtTime(2.5, 0.015);

            panner.positionX.exponentialRampToValueAtTime(11, 0.015);
            panner.positionY.exponentialRampToValueAtTime(11, 0.015);
            panner.positionZ.exponentialRampToValueAtTime(11, 0.015);

            context.listener.forwardX.exponentialRampToValueAtTime(3, 0.015);
            context.listener.forwardY.exponentialRampToValueAtTime(3, 0.015);
            context.listener.forwardZ.exponentialRampToValueAtTime(3, 0.015);

            context.listener.positionX.exponentialRampToValueAtTime(0.5, 0.015);
            context.listener.positionY.exponentialRampToValueAtTime(0.5, 0.015);
            context.listener.positionZ.exponentialRampToValueAtTime(0.5, 0.015);

            context.listener.upX.exponentialRampToValueAtTime(4, 0.015);
            context.listener.upY.exponentialRampToValueAtTime(4, 0.015);
            context.listener.upZ.exponentialRampToValueAtTime(4, 0.015);

            source.start();

            context.startRendering()
                .then(function() {
                  // The final values for each attribute should be the expected
                  // final value.
                  should(
                      panner.orientationX.value,
                      'Final panner.orientationX.value')
                      .beEqualTo(2.5);
                  should(
                      panner.orientationY.value,
                      'Final panner.orientationY.value')
                      .beEqualTo(2.5);
                  should(
                      panner.orientationZ.value,
                      'Final panner.orientationZ.value')
                      .beEqualTo(2.5);
                  should(panner.positionX.value, 'Final panner.positionX.value')
                      .beEqualTo(11);
                  should(panner.positionY.value, 'Final panner.positionY.value')
                      .beEqualTo(11);
                  should(panner.positionZ.value, 'Final panner.positionZ.value')
                      .beEqualTo(11);

                  should(
                      context.listener.forwardX.value,
                      'Final context.listener.forwardX.value')
                      .beEqualTo(3);
                  should(
                      context.listener.forwardY.value,
                      'Final context.listener.forwardY.value')
                      .beEqualTo(3);
                  should(
                      context.listener.forwardZ.value,
                      'Final context.listener.forwardZ.value')
                      .beEqualTo(3);
                  should(
                      context.listener.positionX.value,
                      'Final context.listener.positionX.value')
                      .beEqualTo(0.5);
                  should(
                      context.listener.positionY.value,
                      'Final context.listener.positionY.value')
                      .beEqualTo(0.5);
                  should(
                      context.listener.positionZ.value,
                      'Final context.listener.positionZ.value')
                      .beEqualTo(0.5);
                  should(
                      context.listener.upX.value,
                      'Final context.listener.upX.value')
                      .beEqualTo(4);
                  should(
                      context.listener.upY.value,
                      'Final context.listener.upY.value')
                      .beEqualTo(4);
                  should(
                      context.listener.upZ.value,
                      'Final context.listener.upZ.value')
                      .beEqualTo(4);
                })
                .then(task.done.bind(task));
          });

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