<!DOCTYPE html>
<html>
  <head>
    <title>
      AudioBufferSourceNode - playbackRate test
    </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();

      // Any sample rate mutiple of 128 is valid for this test, but here it uses
      // 48000Hz because it is a commonly used number that happens to be
      // multiple of 128.
      let sampleRate = 32768;

      // The test iterates over 60 pitches starting from 36. (MIDI pitch of C2)
      let fundamentalPitch = 36;
      let numberOfPitches = 60;

      let noteDuration = Math.floor(0.025 * sampleRate) / sampleRate;
      let totalDuration = noteDuration * numberOfPitches;

      // Test constraints for each octave.
      let testConstraints = [
        {thresholdSNR: 97.215, thresholdDiffULP: 0.6446},
        {thresholdSNR: 97.212, thresholdDiffULP: 0.6446},
        {thresholdSNR: 97.217, thresholdDiffULP: 0.6446},
        {thresholdSNR: 97.196, thresholdDiffULP: 0.6485},
        {thresholdSNR: 97.074, thresholdDiffULP: 0.6915}
      ];

      function pitchToFrequency(midiPitch) {
        return 440 * Math.pow(2, (Math.floor(midiPitch) - 69) / 12);
      }

      function pitchDiffToPlaybackRate(midiPitchDiff) {
        return Math.pow(2, midiPitchDiff / 12);
      }

      function createSineWaveBuffer(context, frequency, duration) {
        let buffer = context.createBuffer(1, duration * sampleRate, sampleRate);
        let data = buffer.getChannelData(0);
        let omega = 2 * Math.PI * frequency / sampleRate;
        for (let i = 0; i < data.length; i++)
          data[i] = Math.sin(omega * i);

        return buffer;
      }

      // This is the fundamental buffer for playbackRate modulation. The
      // duration of this buffer is arbitrary but long enough to produce the
      // sound without running short.
      let fundamentalBuffer;

      // A unit test consists of 2 sources: the 'actual' source runs a buffer
      // with the playback rate modulated and the 'expected' source runs a
      // mathmatically generated sound buffer.
      function runUnitTest(context, noteStart, notePitch) {
        let actualSrc = context.createBufferSource();
        let expectedSrc = context.createBufferSource();
        let merger = context.createChannelMerger(2);

        actualSrc.buffer = fundamentalBuffer;
        expectedSrc.buffer = createSineWaveBuffer(
            context, pitchToFrequency(notePitch), noteDuration);
        actualSrc.playbackRate.value =
            pitchDiffToPlaybackRate(notePitch - fundamentalPitch);

        actualSrc.connect(merger, 0, 0);
        expectedSrc.connect(merger, 0, 1);
        merger.connect(context.destination);

        actualSrc.start(noteStart);
        actualSrc.stop(noteStart + noteDuration);
        expectedSrc.start(noteStart);
        expectedSrc.stop(noteStart + noteDuration);
      }


      // Test if AudioBufferSourceNode.playbackRate can playback at different
      // rates properly.
      audit.define('playbackrate-test', (task, should) => {
        let context =
            new OfflineAudioContext(2, totalDuration * sampleRate, sampleRate);
        fundamentalBuffer = createSineWaveBuffer(
            context, pitchToFrequency(fundamentalPitch), totalDuration);

        // Schedule tests up to 60 pitches above from the fundamental pitch.
        for (let iteration = 0; iteration < numberOfPitches; iteration++)
          runUnitTest(
              context, noteDuration * iteration, fundamentalPitch + iteration);

        // Once the rendering is complete, split the buffer into 5 octaves. Then
        // perform the SNR and the maximum difference ULP check for each octave
        // with different constraints.
        context.startRendering()
            .then(function(renderedBuffer) {
              let actual = renderedBuffer.getChannelData(0);
              let expected = renderedBuffer.getChannelData(1);
              let octaveLength = Math.floor(noteDuration * 12 * sampleRate);

              for (let i = 0; i < numberOfPitches / 12; i++) {
                let start = i * octaveLength;
                let end = (i + 1) * octaveLength;
                let octaveActual = actual.subarray(start, end);
                let octaveExpected = expected.subarray(start, end);

                compareBuffersWithConstraints(
                    should, octaveActual, octaveExpected, {
                      prefix: i,
                      thresholdSNR: testConstraints[i].thresholdSNR,
                      thresholdDiffULP: testConstraints[i].thresholdDiffULP
                    });
              }

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

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