Source code
Revision control
Copy as Markdown
Other Tools
Test Info:
- This WPT test may be referenced by the following Test IDs:
- /webaudio/the-audio-api/the-audiobuffersourcenode-interface/sample-accurate-scheduling.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<!--
Tests that we are able to schedule a series of notes to playback with sample-accuracy.
We use an impulse so we can tell exactly where the rendering is happening.
-->
<html>
<head>
<title>
sample-accurate-scheduling.html
</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/webaudio/resources/audit-util.js"></script>
<script src="/webaudio/resources/audit.js"></script>
</head>
<body>
<script id="layout-test-code">
let audit = Audit.createTaskRunner();
let sampleRate = 44100.0;
let lengthInSeconds = 4;
let context = 0;
let bufferLoader = 0;
let impulse;
// See if we can render at exactly these sample offsets.
let sampleOffsets = [0, 3, 512, 517, 1000, 1005, 20000, 21234, 37590];
function createImpulse() {
// An impulse has a value of 1 at time 0, and is otherwise 0.
impulse = context.createBuffer(2, 512, sampleRate);
let sampleDataL = impulse.getChannelData(0);
let sampleDataR = impulse.getChannelData(1);
sampleDataL[0] = 1.0;
sampleDataR[0] = 1.0;
}
function playNote(time) {
let bufferSource = context.createBufferSource();
bufferSource.buffer = impulse;
bufferSource.connect(context.destination);
bufferSource.start(time);
}
function checkSampleAccuracy(buffer, should) {
let bufferDataL = buffer.getChannelData(0);
let bufferDataR = buffer.getChannelData(1);
let impulseCount = 0;
let badOffsetCount = 0;
// Left and right channels must be the same.
should(bufferDataL, 'Content of left and right channels match and')
.beEqualToArray(bufferDataR);
// Go through every sample and make sure it's 0, except at positions in
// sampleOffsets.
for (let i = 0; i < buffer.length; ++i) {
if (bufferDataL[i] != 0) {
// Make sure this index is in sampleOffsets
let found = false;
for (let j = 0; j < sampleOffsets.length; ++j) {
if (sampleOffsets[j] == i) {
found = true;
break;
}
}
++impulseCount;
should(found, 'Non-zero sample found at sample offset ' + i)
.beTrue();
if (!found) {
++badOffsetCount;
}
}
}
should(impulseCount, 'Number of impulses found')
.beEqualTo(sampleOffsets.length);
if (impulseCount == sampleOffsets.length) {
should(badOffsetCount, 'bad offset').beEqualTo(0);
}
}
audit.define(
{label: 'test', description: 'Test sample-accurate scheduling'},
function(task, should) {
// Create offline audio context.
context = new OfflineAudioContext(
2, sampleRate * lengthInSeconds, sampleRate);
createImpulse();
for (let i = 0; i < sampleOffsets.length; ++i) {
let timeInSeconds = sampleOffsets[i] / sampleRate;
playNote(timeInSeconds);
}
context.startRendering().then(function(buffer) {
checkSampleAccuracy(buffer, should);
task.done();
});
});
audit.run();
</script>
</body>
</html>