Source code
Revision control
Copy as Markdown
Other Tools
Test Info: Warnings
- This test has a WPT meta file that expects 6 subtest issues.
- This WPT test may be referenced by the following Test IDs:
- /webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-playbackrate-zero.html - WPT Dashboard Interop Dashboard
<!DOCTYPE html>
<html>
<head>
<title>
audiobuffersource-playbackrate-zero.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">
// Sample rate should be power of 128 to observe the change of AudioParam
// at the beginning of rendering quantum. (playbackRate is k-rate) This is
// the minimum sample rate in the valid sample rate range.
let sampleRate = 8192;
// The render duration in seconds, and the length in samples.
let renderDuration = 1.0;
let renderLength = renderDuration * sampleRate;
let context = new OfflineAudioContext(1, renderLength, sampleRate);
let audit = Audit.createTaskRunner();
// Task: Render the actual buffer and compare with the reference.
audit.define('synthesize-verify', (task, should) => {
let ramp = context.createBufferSource();
let rampBuffer = createLinearRampBuffer(context, renderLength);
ramp.buffer = rampBuffer;
ramp.connect(context.destination);
ramp.start();
// Leave the playbackRate as 1 for the first half, then change it
// to zero at the exact half. The zero playback rate should hold the
// sample value of the buffer index at the moment. (sample-and-hold)
ramp.playbackRate.setValueAtTime(1.0, 0.0);
ramp.playbackRate.setValueAtTime(0.0, renderDuration / 2);
context.startRendering()
.then(function(renderedBuffer) {
let data = renderedBuffer.getChannelData(0);
let rampData = rampBuffer.getChannelData(0);
let half = rampData.length / 2;
let passed = true;
let i;
for (i = 1; i < rampData.length; i++) {
if (i < half) {
// Before the half position, the actual should match with the
// original ramp data.
if (data[i] !== rampData[i]) {
passed = false;
break;
}
} else {
// From the half position, the actual value should not change.
if (data[i] !== rampData[half]) {
passed = false;
break;
}
}
}
should(passed, 'The zero playbackRate')
.message(
'held the sample value correctly',
'should hold the sample value. ' +
'Expected ' + rampData[half] + ' but got ' + data[i] +
' at the index ' + i);
})
.then(() => task.done());
});
audit.define('subsample start with playback rate 0', (task, should) => {
let context = new OfflineAudioContext(1, renderLength, sampleRate);
let rampBuffer = new AudioBuffer(
{length: renderLength, sampleRate: context.sampleRate});
let data = new Float32Array(renderLength);
let startValue = 5;
for (let k = 0; k < data.length; ++k) {
data[k] = k + startValue;
}
rampBuffer.copyToChannel(data, 0);
let src = new AudioBufferSourceNode(
context, {buffer: rampBuffer, playbackRate: 0});
src.connect(context.destination);
// Purposely start the source between frame boundaries
let startFrame = 27.3;
src.start(startFrame / context.sampleRate);
context.startRendering()
.then(audioBuffer => {
let actualStartFrame = Math.ceil(startFrame);
let audio = audioBuffer.getChannelData(0);
should(
audio.slice(0, actualStartFrame),
`output[0:${actualStartFrame - 1}]`)
.beConstantValueOf(0);
should(
audio.slice(actualStartFrame), `output[${actualStartFrame}:]`)
.beConstantValueOf(startValue);
})
.then(() => task.done());
});
audit.run();
</script>
</body>
</html>