chromium/third_party/blink/web_tests/webaudio/resources/scriptprocessornode-testing.js

// For the current implementation of JavaScriptAudioNode, when it works with
// OfflineAudioContext (which runs much faster than real-time) the
// event.inputBuffer might be overwrite again before onaudioprocess ever get
// chance to be called. We carefully arrange the renderLengthInFrames and
// bufferSize to have exactly the same value to avoid this issue.
let renderLengthInFrames = 512;
let bufferSize = 512;

let context;

function createBuffer(context, numberOfChannels, length) {
  let audioBuffer = context.createBuffer(numberOfChannels, length, sampleRate);

  fillData(audioBuffer, numberOfChannels, audioBuffer.length);
  return audioBuffer;
}

function processAudioData(event) {
  buffer = event.outputBuffer;
  if (buffer.numberOfChannels != outputChannels)
    testFailed('numberOfOutputChannels doesn\'t match!');

  if (buffer.length != bufferSize)
    testFailed('length of buffer doesn\'t match!');

  buffer = event.inputBuffer;

  let success = checkStereoOnlyData(buffer, inputChannels, buffer.length);

  if (success) {
    testPassed('onaudioprocess was called with correct input data.');
  } else {
    testFailed('onaudioprocess was called with wrong input data.');
  }
}

function fillData(buffer, numberOfChannels, length) {
  for (let i = 0; i < numberOfChannels; ++i) {
    let data = buffer.getChannelData(i);

    for (let j = 0; j < length; ++j)
      if (i < 2)
        data[j] = i * 2 - 1;
      else
        data[j] = 0;
  }
}

// Both 2 to 8 upmix and 8 to 2 downmix are just directly copy the first two
// channels and left channels are zeroed.
function checkStereoOnlyData(buffer, numberOfChannels, length) {
  for (let i = 0; i < numberOfChannels; ++i) {
    let data = buffer.getChannelData(i);

    for (let j = 0; j < length; ++j) {
      if (i < 2) {
        if (data[j] != i * 2 - 1)
          return false;
      } else {
        if (data[j] != 0)
          return false;
      }
    }
  }
  return true;
}

function runJSNodeTest() {
  // Create offline audio context.
  context = new OfflineAudioContext(2, renderLengthInFrames, sampleRate);

  let sourceBuffer =
      createBuffer(context, sourceChannels, renderLengthInFrames);

  let bufferSource = context.createBufferSource();
  bufferSource.buffer = sourceBuffer;

  let scriptNode =
      context.createScriptProcessor(bufferSize, inputChannels, outputChannels);

  bufferSource.connect(scriptNode);
  scriptNode.connect(context.destination);
  scriptNode.onaudioprocess = processAudioData;

  bufferSource.start(0);
  context.oncomplete = finishJSTest;
  context.startRendering();
}