blob: 4bd5d6e05d9dc3f0692b8c52b551c55c23e74c04 [file] [log] [blame]
<!doctype html>
<title>Test AudioContext.getOutputTimestamp() method</title>
<style type="text/css">
body {
margin: 2em;
.manual-test-ui {
font-family: Arial;
padding: 1em;
border: 1px solid #999;
.manual-test-ui button {
padding: 1em;
font-size: 1em;
.manual-test-ui div {
padding: 10px;
font-size: 1.5em;
.manual-test-ui-beep-indicator {
padding: 10px;
display: inline-block;
border-radius: 50%;
width: 10px;
height: 10px;
background: gray;
<h1>Test AudioContext.getOutputTimestamp() method</h1>
<p>Tests the values returned from AudioContext.getOutputTimestamp()</p>
<p>Press "Start testing" to run the test. You should hear a sine tone (beeping) in 2 seconds.
During the delay the color of "beeping indicator" is red.</p>
<p>The color of "beeping indicator" is yellow when 'context.currentTime' is at beeping
interval but the estimated output position is not there yet and thus beeping is not audible.</p>
<p><b>Note: </b> the "beeping indicator" might never be seen yellow if the test is run in the
environment with low latency audio (i.e. if the output latency is smaller than frame update
<p>The color of "beeping indicator" is green when the estimated output position is at beeping
interval, this should happen exactly when beeping is audible.</p>
<p>Press "Refresh values" to fetch the fresh output audio timestamp values
and compare them to 'AudioContext.currentTime' and ''. </p>
<p>When context is running the obtained audio timestamp and performance timestamp values must be always
slightly behind of 'AudioContext.currentTime' and '' correspondingly.</p>
<p>Please see <a href="">Web Audio
API</a> for more details.</p>
<div class="manual-test-ui">
<div id="audioTime"></div>
<div id="performanceTime"></div>
<div id="timestampContextTime"></div>
<div id="timestampPerformanceTime"></div>
<div class="manual-test-ui-beep-indicator" id="beepIndicator"></div>
<button id="startButton" onclick="startTesting()">Start testing</button>
<button id="valuesButton" onclick="refreshValues()">Refresh values</button>
<button onclick="context.suspend()">Suspend context</button>
<button onclick="context.resume()">Resume context</button>
<script type="text/javascript">
var context = new AudioContext();
let startBeepingTime;
let endBeepingTime;
let indicator = document.querySelector('#beepIndicator');
function inBeepingInterval(audioPosition) {
return audioPosition >= startBeepingTime && audioPosition <= endBeepingTime;
function checkAudioOutputPosition() {
if (!document.querySelector('#startButton').disabled)
if (context.state == "suspended") { = "green";
let timestamp = context.getOutputTimestamp();
let audioOutputPosition = ( - timestamp.performanceTime) * 0.001 + timestamp.contextTime;
if (inBeepingInterval(audioOutputPosition)) = "green";
else if (inBeepingInterval(context.currentTime)) = "yellow";
function startTesting() {
document.querySelector('#startButton').disabled = true;
let oscillator = context.createOscillator();
startBeepingTime = context.currentTime + 2.0;
endBeepingTime = startBeepingTime + 3.0;
oscillator.stop(endBeepingTime); = "red";
oscillator.onended = () => {
document.querySelector('#startButton').disabled = false; = "gray";
function refreshValues() {
document.querySelector("#audioTime").innerHTML = "context.currentTime: " + context.currentTime;
document.querySelector("#performanceTime").innerHTML = " " +;
let timestamp = context.getOutputTimestamp();
document.querySelector("#timestampContextTime").innerHTML = "timestamp audio: " + timestamp.contextTime;
document.querySelector("#timestampPerformanceTime").innerHTML = "timestamp performance: " + timestamp.performanceTime;