<!DOCTYPE html>
<html>
<head>
<title>
Test AudioBufferSourceNode looping without explicit duration
</title>
<script src="../../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">
// Reasonably low sample rate for the optimum test speed.
let sampleRate = 8192;
let audit = Audit.createTaskRunner();
// Task: create a short linear ramp and enable looping. The test will
// verify that the ramp was looped the appropriate number of times.
audit.define('loop-count', (task, should) => {
// How many loops of the source we want to render. Any whole number
// greater than 1 will work.
let loopCount = 4;
let sourceFrames = 8;
let renderFrames = sourceFrames * loopCount;
let context = new OfflineAudioContext(1, renderFrames, sampleRate);
let source = context.createBufferSource();
let linearRampBuffer = createLinearRampBuffer(context, sourceFrames);
source.buffer = linearRampBuffer;
source.connect(context.destination);
// Enable looping and start the source with an offset, but without a
// duration. In this case, the source should loop "forever".
// See crbug.com/457009.
source.loop = true;
source.start(0, 0);
context.startRendering()
.then(function(renderedBuffer) {
let badIndex = -1;
let success = true;
let actual = renderedBuffer.getChannelData(0);
let linearRamp = linearRampBuffer.getChannelData(0);
// Manually create a |loopCount| copies of linear ramps.
let expected = new Float32Array(linearRamp.length * loopCount);
for (let i = 0; i < loopCount; i++)
expected.set(linearRamp, linearRamp.length * i);
// The actual output should match the created loop.
should(actual, 'The output of actual and expected loops')
.beEqualToArray(expected);
})
.then(() => task.done());
});
// Task: Test that looping an AudioBufferSource works correctly if the
// source is started and the buffer is assigned later, but before the
// source would start.
audit.define('delayed-start', (task, should) => {
let renderDuration = 2;
let context =
new OfflineAudioContext(2, sampleRate * renderDuration, sampleRate);
let linearRampBuffer = createLinearRampBuffer(context, 128);
let normal = context.createBufferSource();
let delayed = context.createBufferSource();
let merger = context.createChannelMerger(2);
// Connect the normally started source to the left channel, and the
// delayed to the right channel.
normal.connect(merger, 0, 0);
delayed.connect(merger, 0, 1);
merger.connect(context.destination);
normal.buffer = linearRampBuffer;
normal.loop = true;
delayed.loop = true;
normal.start(1, 0);
delayed.start(1, 0);
// Assign the buffer to the delayed source node at 0.5 second.
context.suspend(0.5).then(function() {
delayed.buffer = linearRampBuffer;
context.resume();
});
context.startRendering()
.then(function(buffer) {
// The left and right channel must match regardless of the timing
// of buffer assignment.
should(
buffer.getChannelData(0),
'The content of the left and right channel')
.beEqualToArray(buffer.getChannelData(1));
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>